
phpMyAdmin 5.2.3 - 높음 - 원격 - XSS - Designer Visual Query Builder
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · phpmyadmin-vqb-xss
분석 문서: https://abraxaslabs.tech/research/phpmyadmin-vqb-xss
분류: 저장형 XSS 도달 범위: 원격
phpMyAdmin 5.2.3 (RELEASE_5_2_3 / 962857e) - phpMyAdmin
js/src/designer/history.js는 innerHTML로 시각적 쿼리(visual-query) 기록을 구성합니다. 컬럼 이름은 $('<div/>').text(...).html()을 거칩니다. 테이블 이름은 그렇지 않습니다. TableName은 여전히 <와 >를 허용합니다. 공유 데이터베이스에 CREATE TABLE 권한을 가진 저권한 계정이 HTML 식별자를 심어둡니다. 더 높은 권한의 사용자가 Designer를 열면, getTableName()이 페이지에 존재하게 되고 DesignerHistory.display()가 이를 #ab에 기록합니다.
phpMyAdmin 오리진에서의 저장형 XSS. PMASA-2025-1과 같은 분류, 다른 기능. check-tables 제목은 이스케이프되었습니다. 이 경로는 그렇지 않았습니다.
| ID | 아직 CVE 없음 |
| 분류 | 저장형 XSS |
| 도달 범위 | 원격 (인증된 CREATE TABLE; 피해자가 Designer를 엶) |
| CWE | CWE-79 |
| CVSS | 높음: 8.0 CVSS:3.1/AV:N/AC:L/PR:L/UI:R/S:U/C:H/I:H/A:N |
| 제품 | phpMyAdmin |
| 영향받는 버전 | 5.2.3 태그 RELEASE_5_2_3 (962857e4f63d42e38f11ff4d63f5e722018add76) |
| 인증 | 인증됨. 공격자는 피해자가 Designer에서 여는 데이터베이스에 대한 CREATE TABLE 권한이 필요함 |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
HTML 테이블 이름을 심어둔 뒤, 더 높은 권한의 사용자가 해당 데이터베이스에서 Designer를 열고 시각적 쿼리 기록을 렌더링할 때까지 기다립니다.
| 권한 | 메서드 / 싱크 | 정보 수집 / 무결성 / 가용성 | 랩 검증 또는 추론 |
|---|---|---|---|
| phpMyAdmin 오리진에 마크업 주입 | DesignerHistory.display()가 getTab()을 #ab innerHTML에 연결 | 피해자 오리진의 무결성 | 랩 검증. phpmyadmin:5.2.3에서 실행 중인 history.js. <h3>에 <i id="pma-vqb">가 포함됨 |
designer table_name 속성에서 탈출 | database_tables.twig small_tab_pref_1이 designerTable.getTableName()을 사용 | Designer DOM에서 원시 MySQL 이름 정보 수집 | 랩 검증, 원시 식별자로 읽을 수 있음 |
피해자 세션 쿠키와 CSRF token 읽기 | 기록이 렌더링되면 동일 출처 스크립트 | 피해자 PMA 세션 정보 수집 | PMA 오리진의 저장형 XSS로부터 추론. 이 랩은 스크립트가 아닌 <i> 마커를 사용 |
| 피해자 MySQL 계정으로 SQL 실행, 사용자 관리, 내보내기 | 토큰 기반 POST /sql, /server/privileges, export | 해당 MySQL 계정이 접근할 수 있는 모든 것의 무결성 | 추론. PMASA-2025-1과 동일한 영향 분류 |
| 2FA / userconfig 변경 | 피해자로서 POST /config/set | 피해자 환경설정 저장소의 무결성 | 추론. 인접 잔여 항목, 이 랩 아님 |
이 잔여 항목에서 제외된 것: 인증되지 않은 접근, OS RCE, 그리고 VQB OK 버튼 경로. .small_tab_pref_click_opt는 table_name을 미리 이스케이프하고 Twig가 다시 자동 이스케이프하므로, 해당 클릭은 현재 엔티티를 getTab()에 전달합니다. 그것은 history.js의 수정이 아닙니다. 컬럼 셀은 텍스트 이스케이프 상태로 유지됩니다(c<b id=pma-col>y, <b id="pma-col"> 노드 없음).
동일 핀: WebAuthn CustomServer 잔여 항목.
phpMyAdmin RELEASE_5_2_3을 핀했습니다. PMASA-2025-1/2/3은 이미 5.2.2에 포함되어 있습니다. Designer는 여전히 VQB 기록 HTML을 수작업으로 구성합니다.
js/src/designer/history.js (js/dist/designer/history.js로 배포됨):
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는 비어 있지 않고, 최대 64자이며, 후행 공백이 없는지만 검사합니다. <와 >는 허용됩니다. MySQL은 따옴표로 묶인 식별자에서 이를 허용합니다.
templates/database/designer/database_tables.twig는 designerTable.getTableName()을 .small_tab_pref_1의 table_name에 복사합니다. VQB 옵션 셀은 동일한 이름의 미리 이스케이프된 복사본을 사용합니다.
이미 기록된 잘못된 판단: 이중 이스케이프된 옵션 버튼 속성을 수정 사항으로 간주한 것(그렇지 않습니다 - small_tab_pref_1은 여전히 원시 이름을 노출하며, history.js가 싱크입니다); 컬럼 헬퍼가 테이블 이름을 커버한다고 간주한 것; 인증되지 않은 XSS라고 주장한 것; 리버스 셸. 연극일 뿐입니다.
python3 phpmyadmin-vqb-xss-Abraxas-Labs.py
# or: cd lab && ./run.sh
오직 http://127.0.0.1:19250만 대상으로 합니다. 이미지 phpmyadmin:5.2.3 및 mysql:8.0. Compose 프로젝트 phpmyadmin-vqb-xss. poc 서비스에서 Playwright Chromium. 실행 후 스택은 해체됩니다.
두 사용자, 공유 shareddb. 낮은 권한의 creator가 CREATE TABLE \tx` (`cy` INT)를 실행합니다. 높은 권한의 victim이 phpMyAdmin에 로그인하고 query=1로 Designer를 엽니다. 라이브 history.js는 컨테이너에서 가져온 사본입니다(h3-unescaped=yes, column helper 존재). Chromium은 페이지의 getTableName()에서 가져온 테이블 이름으로 DesignerHistory.display()`를 호출합니다.
결과: #ab h3.tiger의 innerHTML은 <a href="#">t<i id="pma-vqb">x</i></a>입니다. Column td 텍스트는 c<b id=pma-col>y이며 b#pma-col 노드는 없습니다.
SUCCESS phpmyadmin-vqb-xss h3-markup=yes col-escaped=yes how=live PMA-VQB-XSS-WITNESS
<h3>에 연결하기 전에 getTab()을 $('<div/>').text(temp).html() 또는 Functions.escapeHtml로 이스케이프하세요. 하나의 속성에 대한 Twig의 이중 인코딩에 의존하지 마세요. 열 이름 헬퍼는 모델로 유지하세요.
962857e4f63d42e38f11ff4d63f5e722018add76)js/src/designer/history.jslibraries/classes/Dbal/TableName.phpGNU Affero GPL v3.0. LICENSE를 참조하세요. 루프백 랩 전용. 보증 없음.