
phpMyAdmin - 높음 8.1 - 인증된 POST /index.php - 2FA 우회
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · PMA-5.2.3-WebAuthn-2FA
phpMyAdmin 5.2.3 - phpMyAdmin
기본 tarball. web-auth/webauthn-lib는 suggest / require-dev입니다. composer install --no-dev는 이를 설치하지 않습니다. 따라서 createServer는 CustomServer를 사용합니다. 해당 클래스는 response.signature를 파싱하며(필드가 존재하고 디코딩되어야 함) COSE 검증은 전혀 하지 않습니다. 저장된 credentialPublicKey를 절대 사용하지 않습니다. 제품 자체의 CustomServerTest는 공개 키 없이 어서션을 수락합니다.
MySQL 비밀번호 이후, challenge, origin, rpIdHash, user-present는 모두 일치하지만 서명은 쓰레기값인 WebAuthn 어서션이 완전한 phpMyAdmin 세션을 부여합니다. 그것이 곧 데이터베이스입니다.
| ID | 아직 CVE 없음 |
| CWE | CWE-347, CWE-287 |
| CVSS | High: 8.1 CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:N |
| 제품 | phpMyAdmin |
| 영향 받는 버전 | 5.2.3 기본 tarball (web-auth/webauthn-lib 부재) |
| 인증 | MySQL 비밀번호, 이후 WebAuthn 건너뜀 |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1 전용 |
공격자는 여전히 MySQL 비밀번호(쿠키 로그인)가 필요합니다. 그 비밀번호 이후, challenge, origin 호스트, rpIdHash, user-present, 등록된 credential id가 모두 일치하고 서명은 쓰레기값인 webauthn_request_response를 POST합니다. 그러면 정상 UI에 진입합니다. 2FA는 사라집니다. 이는 데이터에 대한 RCE이며, 호스트에 대한 PHP 셸은 아닙니다.
실제로 web-auth/webauthn-lib를 설치했다면 WebauthnLibServer를 사용하게 되므로 이 버그에 해당하지 않습니다.
createServer를 읽고, 이어서 parseAndValidateAssertionResponse를, 그다음 공개 키를 전달하지 않는 단위 테스트를 읽었습니다. 구조적 검사는 실제로 동작합니다: allowCredentials 내 credential id, clientData.type == webauthn.get, 세션과 일치하는 challenge, origin 호스트, rpIdHash, user-present. 서명은 파싱되고 무시됩니다.
이 취약점을 향해 처음 겨눈 클라이언트는 얌전했습니다. 사전 비밀번호 세션 없이 WebAuthn JSON을 POST했습니다. 로그인 페이지가 나왔습니다. 구조적 검사조차 통과하지 못하는 서명으로 route=/를 POST했습니다. 여전히 2FA에 머뭅니다. webauthn_request_response는 여전히 HTML에 있습니다.
이미 기록된 잘못된 시도들: Webauthn\Server 존재(잘못된 서버 클래스); 이 세션의 challenge가 아님; origin 호스트 불일치; user-present 플래그 미설정; allowCredentials에 없는 credential id; 인증되지 않음, MySQL 비밀번호 없음; 리버스 셸. 다 헛수고였습니다. 진짜 신호는 2FA 필드가 사라지고 phpMyAdmin 탐색 페이지가 나타나는 것입니다.
클라이언트 버그는 제품 버그처럼 보입니다. http.client를 가리는 헬퍼는 패킷을 전혀 보내지 않습니다. HTTPResponse에 대한 .recv()는 .read()가 아닙니다. 잠깐 phpMyAdmin이 멀쩡한 것처럼 보였기에 시간을 잡아먹었던 일이라 한 번 언급합니다.
그다음: username/password/token을 POST. 2FA 페이지에서 세션 challenge를 추출. 위조된 어서션을 POST. still_2fa=False landed=True. 랩 Dockerfile은 5.2.3을 복사하고, composer install --no-dev를 실행한 뒤, CustomServer가 사용되도록 vendor/web-auth를 삭제합니다. 마지막 php -r은 Webauthn\Server가 존재하면 종료 코드 1로 끝납니다. 라이브러리가 여전히 남아 있으면 이미지 빌드가 실패해야 합니다. init.sql은 하드웨어 키 없이 appuser에 WebAuthn 2FA를 등록합니다.
cd lab
./run.sh
오직 http://127.0.0.1:18080만 대상으로 합니다. 먼저 phpMyAdmin 5.2.3을 Dockerfile 옆의 src/로 배치하세요.
password-login status=200 webauthn=True
2fa-post status=200 still_2fa=False landed=True
SUCCESS PMA-WEBAUTHN-BYPASS WebAuthn 2FA accepted with garbage signature
createServer가 라이브러리를 사용하도록 web-auth/webauthn-lib를 설치하거나, CustomServer에서 저장된 공개 키에 대해 response.signature를 실제로 COSE 검증하십시오. 그때까지는 WebAuthn 2FA를 비활성화하거나 이 phpMyAdmin을 노출하지 마십시오.
CustomServer::parseAndValidateAssertionResponse · WebAuthn::createServer · CustomServerTestGNU Affero GPL v3.0. LICENSE를 참조하십시오. 루프백 실습 환경 전용입니다. 보증은 제공되지 않습니다.