CERT
웹 모의해킹: Stored XSS
Pdev37
2024. 10. 5. 18:11
특징
- 공격자의 악성스크립트가 데이터베이스에 저장되고 이 값을 출력하는 페이지에서 피해가 발생하는 취약점
- 악성스크립트가 포함된 게시물을 사용자가 접근할 수 있는 페이지에 업로드
→ 사용자가 악성스크립트가 포함된 게시물을 요청
→ 공격자가 삽입한 악성스크립트가 사용자 측에서 동작
DVWA 실습
- DVWA 저장형 XSS 탭의 방명록 게시판
- 쿠키 정보를 노출 시키는 악성 스크립트 삽입 후 등록
- 악성 스크립트가 실행되어 쿠키 정보가 노출
- 게시판을 로드 할때 마다 스크립트가 실행
- 웹페이지 Html 을 분석해 보면 작성한 글이 그대로 스크립트로 적용되어 해석이됨
- 이 웹페이지는 콘솔로도 조작이 되는데 Name 부분은 현재 글자수 제한이 있어 스크립트를 사용하는데 제약
- 콘솔에 maxlength 를 제거해주는 코드 실행
- 실제로 서버에도 콘솔 명령어가 전달이 되어 Name 에도 악성 스크립트가 저장되어 실행
- 게시판에 들어 올때마다 저장된 웹페이지에서 악성코드가 실행
소스코드 분석
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ( isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"]) ) ? mysqli_real_escape_string( $GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("MySQLConverterToo! Fix the mysqli_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "" );
// Sanitize name input
$name = ( isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"]) ) ? mysqli_real_escape_string( $GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("MySQLConverterToo! Fix the mysqli_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "" );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query( $GLOBALS["___mysqli_ston"], $query ) or die( ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : ((($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false))) . '</pre>' );
}
// mysqli_close();
?>
- 공백만 제거하고 입력은 필터링 하지 않음
- SQL injection 은 방지 했지만 브라우저에서는 XSS 방지기능 없음
대응방안
- 입력 값 검증 및 필터링:
사용자 입력 값을 저장하기 전에 악성 스크립트가 포함되지 않도록 HTML 엔티티로 변환하거나, 스크립트 태그를 제거하는 등의 필터링 - 출력 시 HTML 인코딩:
입력된 값을 나중에 출력할 때는 반드시 HTML 인코딩을 적용하여 악성 스크립트를 포함한 입력을 하더라도, 그 내용이 단순한 텍스트로 표시되게 설정 - 화이트리스트 방식의 필터링:
특정 HTML 태그를 허용하고 나머지 태그는 모두 필터링