
Bee-box XSS-Reflected(GET)문제 소스코드를 XSS 취약점 관점으로 탐구한다.
bee-box의 XSS-Redflected(GET) 페이지는 아래와 같다.
firstname, lastname 입력 후, Go 버튼을 누르면 두 파라미터가 합쳐진 결과가 웹 페이지에 랜더링 된다.
이 소스코드를 탐구해 보자.
소스 코드 위치
$ sudo gedit /var/www/bWAPP/xss_get.php
xss_get.php 소스코드에 보면 아래와 같이 이름을 합쳐주는 기능이 어떻게 구현되었는지 나온다.
echo와 xss 함수를 사용.
at Java
함수 : 단독 모듈로 호출해 사용 가능
메소드 : 클래스 종속

외부로부터 들어온 입력값을 검증없이 그대로 사용해주기 때문에, XSS 취약점이 존재한다고 볼 수 있다.
xss 메소드는 소스코드 상단에 아래와 같이 정의되어 있다.

security_level에 따라 사용 함수(no_check, xxs_check3, xxs_check4) 사용한다.
/var/www/bWAPP/functions_external.php에 해당 함수가 정의되어 있다.
먼저 no_check 함수를 확인해보자

아무 검증 없이 data를 반환한다.
xss_check 함수가 1부터 4까지 4개 존재한다.


xss_check_1($data)에서 ($data)를 함수 인자로 사용.
data에 < 를 < 로 대체, input 변수에 담는다.
input의 > 를 > 로 대체, input 변수에 담는다.
urldecode (PHP 기본 메소드)로 URL Decode시킨 후 반환.
가. data의 값이 (아래와 같음) 일때
%3Cscript%3Ealert%280%29%3C%2Fscript%3E
%3C == <
(%3C == < )이므로 이를 HTML 엔티티 < 로 변경.
따라서 특수한 의미가 사라지게 되고 의미가 없는 단순 문자열으로 사용.
나. data의 값이 (아래와 같음) 일때
<script>alert(0)</script>
xss_check_1 함수에서는 아무런 변경 없이 반환된다. (urldecode에서도 그대로 반환)
<script>alert(0)</script>
로 반환된다.

다. data의 값이 (아래와 같음) 일때
%253Cscript%253Ealert%25280%2529%253C%252Fscript%253E
이는 나.의 data를 두 번 인코딩한 값이다. 따라서 해당 메소드에서는 urldecode 메소드만 적용되어 가.의 입력값을 가지고 반환되게 된다. 따라서 해당 data 는 스크립트로 실행.
왜 그럴까?
브라우저의 렌더링 과정은 엔코딩 횟수와 상관 없이 브라우저가 받은 값의 특수한 의미를 찾아 스크립트로써 실행해주기 때문이다.
<script>alert(0)</script>
%3Cscript%3Ealert%280%29%3C%2Fscript%3E
%253Cscript%253Ealert%25280%2529%253C%252Fscript%253E


PHP 기본 함수 중 하나인 htmlentities()가 해당 소스코드에서 어떻게 동작할까?
아래 HTML로 사용자의 입력값을 입력받는다.
<input type="text" value="사용자 입력값">
value에 사용자 입력값을 아래와 같이 입력받는다면,
"
웹 서버가 해당 값을 응답해 렌더링 과정에서 HTML은 아래와 같다.
<input type="text" value="" onmouseover="alert('XSS')">
이때, htmlentities 함수는 ENT_QUOTES 사용해 아래와 같이 렌더링 되도록 한다.
<input type="text" value="" onmouseover="alert('XSS')">
xss_check_2함수에서는 PHP 기본 함수 htmlentities()함수를 사용해 문자열을 HTML 엔티티로 변환한다.
DB로부터 온 데이터, 사용자 입력을 HTML 페이지 표시할때 사용할 수 있다.
htmlentities 함수 옵션
ENT_QUOTES: 큰따옴표와 작은따옴표를 모두 변환
ENT_COMPAT: 큰따옴표만을 변환
ENT_NOQUOTES: 큰따옴표와 작은따옴표를 모두 변환하지 않음

htmlspecialchars는 PHP 내장 함수로써 아래와 같이 스크립트로써 실행될 수 있는 HTML 특수문자를 HTML 엔티티로 변경되어 스크립트로써 실행이 안 되는 문자로 변경해준다.
<script>alert('XSS')</script>
<script>alert('XSS')</script>
htmlspecialchars 함수 옵션
ENT_QUOTES: 이 옵션은 큰따옴표와 작은따옴표를 모두 HTML 엔티티로 변환
$encoding: 이 매개변수는 문자열 인코딩을 지정(UTF-8)


addslashed 메소드는 문자열에 백슬래시를 추가하여 SQL 쿼리에서 특수 문자를 이스케이핑해준다.
아래의 예를 입력값으로 사용하면,
"<script>alert(1)</script>";
addslashed 메소드를 적용해 아래와 같이 변경된다.
<script>alert(1)</script>
따라서 스크립트로써 실행되지 않는다.
하지만 주석 설명에 XSS 또는 HTML 유효성을 위해 해당 메소드를 사용하지 말라고 한다. 안전하면 다 좋은거 아닌가?
모든 입력값에 대해 addslashes 메소드를 사용하는 것을 지양하는 이유는?
PHP 5.4버전에서 문자열을 이스케이핑 하기 위해 magic_quotes_gpc 라는 함수를 사용했다.
그러나 SQL Injection이 아닌 문자열에 대해서 문제가 발생했다.
정상을 위해 비정상을 처리한다 ( 굿 )
그러나(버전별 호환성 다름) -> 비정상을 위해 정상을 처리한다 ( ??? )
따라서 PHP 5.4.0 버전 이후 magic_quotes_gpc를 폐기.
이후 버전에서의 addslashes는 폐기 사유로 인해 SQL Injection 대응 용도로 사용을 권장.
xss_check_1~4 에서 여러가지의 방법으로 XSS 취약점을 방어하기 위한 필터링을 수행한다. 단순히 한 방법이 좋은 것이 아닌, 여러 방법을 결합해 (addslashed는 사용하지 않고..) XSS 취약점 방어를 해야 할것 같다.