
phpMyAdmin 5.2.3 - उच्च - रिमोट - XSS - Designer Visual Query Builder
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-vqb-xss
Class: Stored XSS Reach: Remote
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
js/src/designer/history.js innerHTML के साथ visual-query history बनाता है। Column names $('<div/>').text(...).html() से गुज़रते हैं। Table names नहीं गुज़रते। TableName अभी भी < और > की अनुमति देता है। साझा database पर CREATE TABLE वाला low-privilege account एक HTML identifier रखता है। जब कोई higher-privilege user Designer खोलता है, तो getTableName() पेज पर मौजूद होता है और DesignerHistory.display() उसे #ab में लिख देता है।
phpMyAdmin origin में एक stored XSS। PMASA-2025-1 के समान class, अलग feature। Check-tables headings escaped थे। यह path नहीं था।
| ID | अभी तक कोई CVE नहीं |
| Class | Stored XSS |
| Reach | Remote (authenticated CREATE TABLE; victim Designer खोलता है) |
| CWE | CWE-79 |
| CVSS | High: 8.0 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| Product | phpMyAdmin |
| Affected | 5.2.3 tag RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| Auth | authenticated। Attacker को उस database पर CREATE TABLE चाहिए जिसे victim Designer में खोलता है |
| License | GNU Affero GPL v3.0 |
| Lab | केवल 127.0.0.1 |
एक HTML table name रखें, फिर प्रतीक्षा करें कि कोई higher-privilege user उस database पर Designer खोले और visual-query history render करे।
| Privilege | Method / sink | Recon / integrity / availability | Lab-proven या inferred |
|---|---|---|---|
| phpMyAdmin origin में markup inject करें | DesignerHistory.display() getTab() को #ab innerHTML में concatenate करता है | Victim origin की integrity | Lab-proven। phpmyadmin:5.2.3 पर live history.js। <h3> में <i id="pma-vqb"> था |
Designer के table_name attribute से बाहर निकलें | database_tables.twig small_tab_pref_1 designerTable.getTableName() का उपयोग करता है | Designer DOM में raw MySQL name की recon | Lab-proven, raw identifier के रूप में पठनीय |
Victim session cookie और CSRF token पढ़ें | History render होने पर same-origin script | Victim PMA session की recon | PMA origin में stored XSS से inferred। यह lab एक <i> marker का उपयोग करता है, script का नहीं |
| Victim MySQL account के रूप में SQL चलाएँ, users प्रबंधित करें, export करें | Token-backed POST /sql, /server/privileges, export | उस MySQL account की integrity जो भी वह छू सकता है | Inferred। PMASA-2025-1 के समान impact class |
| 2FA / userconfig बदलें | Victim के रूप में POST /config/set | Victim preference store की integrity | Inferred। Sibling leftover, यह lab नहीं |
इस leftover पर बंद: unauthenticated access, OS RCE, और VQB OK button path। .small_tab_pref_click_opt table_name को pre-escape करता है और Twig उसे फिर से autoescape करता है, इसलिए वह click वर्तमान में getTab() में entities feed करता है। यह history.js का fix नहीं है। Column cells text-escaped रहते हैं (c<b id=pma-col>y, कोई <b id="pma-col"> node नहीं)।
Same pin: WebAuthn CustomServer leftover।
मैंने phpMyAdmin RELEASE_5_2_3 pin किया। PMASA-2025-1/2/3 पहले से 5.2.2 में हैं। Designer अभी भी VQB history HTML हाथ से बनाता है।
js/src/designer/history.js (js/dist/designer/history.js के रूप में shipped):
temp = historyArray[i].getTab();
str += '<h3 class="tiger"><a href="#">' + temp + '</a></h3>';
// ...
'<td width="175" style="padding-left: 5px">' + $('<div/>').text(historyArray[i].getColumnName()).html() + '<td>';
libraries/classes/Dbal/TableName.php केवल non-empty, max 64, no trailing space की जाँच करता है। < और > legal हैं। MySQL उन्हें quoted identifier में स्वीकार करता है।
templates/database/designer/database_tables.twig .small_tab_pref_1 पर designerTable.getTableName() को table_name में copy करता है। VQB option cell उसी name की pre-escaped copy का उपयोग करता है।
पहले से दर्ज गलत रास्ते: double-escaped option-button attribute को fix मानना (यह नहीं है - small_tab_pref_1 अभी भी raw name expose करता है, और history.js sink है); column helper को table names को cover करने वाला मानना; unauthenticated XSS का दावा; एक reverse shell। नाटक।
python3 phpmyadmin-vqb-xss-Abraxas-Labs.py
# or: cd lab && ./run.sh
लक्ष्य केवल http://127.0.0.1:19250। Images phpmyadmin:5.2.3 और mysql:8.0। Compose project phpmyadmin-vqb-xss। poc service में Playwright Chromium। Run के बाद stack tear down हो जाता है।
दो users, साझा shareddb। Low-priv creator चलाता है CREATE TABLE \tx` (`cy` INT)। Higher-priv victimphpMyAdmin में log in करता है औरquery=1के साथ Designer खोलता है। Livehistory.js container से copy है (h3-unescaped=yes, column helper मौजूद)। Chromium पेज पर getTableName()से table name के साथDesignerHistory.display()` call करता है।
परिणाम: #ab h3.tiger innerHTML है <a href="#">t<i id="pma-vqb">x</i></a>। Column td text है c<b id=pma-col>y बिना किसी b#pma-col node के।
SUCCESS phpmyadmin-vqb-xss h3-markup=yes col-escaped=yes how=live PMA-VQB-XSS-WITNESS
getTab() को <h3> में concatenate करने से पहले $('<div/>').text(temp).html() या Functions.escapeHtml से escape करें। एक attribute के Twig double-encoding पर निर्भर न रहें। Column-name helper को model के रूप में रखें।
962857e4f63d42e38f11ff4d63f5e722018add76)js/src/designer/history.jslibraries/classes/Dbal/TableName.phpGNU Affero GPL v3.0। देखें LICENSE। केवल Loopback lab। कोई warranty नहीं।