[bWAPP] HTML Injection - Reflected(GET)
1. HTML Injection이 무엇인지 정리하시오.
1) HTML Injection
- 공격자가 악의적인 목적으로 html 태그를 삽입하는 공격
- 악의적인 html 태그를 삽입하여 원치 않은 내용을 보게 하거나 다른 사이트로 리다이렉션 하는 등의 공격을 함
2) 종류
① Reflected(GET)
② Reflected(POST)
③ Stored
3) 반사기법 (Reflected)
- url에 공격자가 악의적인 html 태그를 삽입하여 공격하는 방법
- 공격 방법
ⓐ 취약한 변수에 악의적인 html 태그 삽입
ⓑ 사용자가 링크를 누르면 악의적인 html 코드 실행
- 종류
① Reflected(GET)
- 사용자가 요청한 url의 취약한 파라미터를 공격자가 조작하여 공격하는 방법
- 값을 header에서 조작
- 전송할 수 있는 데이터의 양 제한되어 있음
② Reflected(POST)
- 사용자가 요청한 url의 취약한 파라미터를 공격자가 조작하여 공격하는 방법
- 값을 body에서 조작
- 많은 양의 데이터 전송 가능
4) 저장기법 (Stored)
- 공격자가 취약한 사이트에 악의적인 스크립트가 포함된 게시글 등을 올릴 경우 이 게시물을 열람하면 스크립트가 실행됨
- 공격 당한 사용자는 쿠키를 탈취당하거나 다른 사이트로 리다이렉션 되는 등의 피해를 입음
- 데이터베이스에 저장되고 해당 게시물을 열람한 사용자들이 공격의 대상이 되기 때문에 파급력이 큼
- 공격 방법
ⓐ 악성 행위를 하는 html 코드를 게시물에 심음
ⓑ 사용자가 게시물을 조회하면 악성 html 코드 실행
2. 아래 화면을 출력하시오
[난이도 low]
일단 빈칸에 각각 1을 입력하니 위와 같은 출력이 나왔다.
이번에는 스크립트 태그를 넣어볼까 싶어서 빈칸에 h1, h2 태그를 넣어보았다.
h1 태그에는 / 가 1개, h2 태그에는 / 가 2개씩 붙는 것을 확인할 수 있었다.
출력해야할 결과화면에 / 가 1개씩 있었으므로 First name에는 h1 태그로 두른 SUCCESS가 들어가야 한다는 것을 알았다.
따라서 First name의 빈칸에 들어가야할 내용은 <h1>SUCCESS</h1> 이다.
그리고 아래에는 벌 그림이 들어가야하므로 img 태그를 써야하고, 이미지파일의 경로를 src 속성으로 줘야한다.
따라서 Last name의 빈칸에 들어가야할 내용은 <img src="http://172.30.1.57/bWAPP/images/bee_1.png"> 이다.
이렇게 입력해주니
원하는 화면을 출력할 수 있었다.
난이도 & 결과 화면 확인
[난이도 medium]
일단 low 단계에서 입력했던 내용 그대로 다시 입력해보았다.
이번에는 태그가 적용되지 않고 입력한 값 그대로 출력되는 것을 확인할 수 있다.
어떻게 할까 고민하다가 소스코드를 확인해보기로 했다.
개발자 도구로 사용된 함수 파일명을 확인한 뒤에 비 박스 파일의 경로를 따라가서 htmli_get 파일을 열었다.
function htmli($data)
{
switch($_COOKIE["security_level"])
{
case "0" :
$data = no_check($data);
break;
case "1" :
$data = xss_check_1($data);
break;
case "2" :
$data = xss_check_3($data);
break;
default :
$data = no_check($data);
break;
}
return $data;
}
코드 내용 중에 위의 부분을 발견했는데 문제 난이도인 low, medium, high 레벨에 따라 적용되는 함수가 달라지는 듯 했다.
실제로 문제 난이도에 따라 케이스 0, 1, 2로 바뀌는 지 소스코드를 확인해보았다.
생각한 게 맞았다.
이번에는 각 케이스마다 사용된 함수의 기능을 알아보기 위해 함수를 찾아보기로 했다.
위에 적혀있는 외부 파일들을 하나씩 확인해보다가 function_external 파일에 해당 함수들이 있는 것을 발견했다.
function_external 파일을 확인해서 no_check와 xss_check_1 함수의 기능을 살펴보았다.
function no_check($data)
{
return $data;
}
function xss_check_1($data)
{
// Converts only "<" and ">" to HTLM entities
$input = str_replace("<", "<", $data);
$input = str_replace(">", ">", $input);
// Failure is an option
// Bypasses double encoding attacks
// <script>alert(0)</script>
// %3Cscript%3Ealert%280%29%3C%2Fscript%3E
// %253Cscript%253Ealert%25280%2529%253C%252Fscript%253E
$input = urldecode($input);
return $input;
}
코드를 확인해보니 xss_check_1 함수는 str_replace 함수를 이용해서 <와 >를 태그가 아닌 문자 자체로 바꿔주고 있었다.
그래서 이번에는 URL Encoding을 사용해보기로 했다.
URL Encoding : 특수문자 등을 사용할 수 있도록 아스키코드의 16진수 값에 %를 붙여주는 것
아스키코드표를 참고해서 <는 %3C, >는 %3E임을 파악하고 low 단계에서 사용했던 코드의 <와 >를 각각 %3C, %3E로 바꿔서 입력해주었다.
따라서 이렇게 입력을 하니
원하는 화면을 출력할 수 있었다.
난이도 & 결과 화면 확인
[난이도 high]
일단 low 단계에서 입력했던 내용을 입력하니 마찬가지로 텍스트 그대로 출력되는 것을 확인할 수 있었다.
medium 단계에서 입력했던 내용을 입력하니 이번에도 텍스트 그대로 출력되는 것을 확인할 수 있었다.
문제에서 제시했듯 풀 수 없는 문제라고 했지만 한번 확인해보았다.
이번에도 소스코드를 확인해보았다.
case "2" :
$data = xss_check_3($data);
break;
high 단계이므로 레벨 value 값이 2이고 2이면 아래의 코드가 적용된다.
function_external 파일을 확인해서 xss_check_3 함수의 기능을 살펴보았다.
function xss_check_3($data, $encoding = "UTF-8")
{
// htmlspecialchars - converts special characters to HTML entities
// '&' (ampersand) becomes '&'
// '"' (double quote) becomes '"' when ENT_NOQUOTES is not set
// "'" (single quote) becomes ''' (or ') only when ENT_QUOTES is set
// '<' (less than) becomes '<'
// '>' (greater than) becomes '>'
return htmlspecialchars($data, ENT_QUOTES, $encoding);
}
htmlspecialchars 함수를 사용하고 있는데, 이 함수는 문자열에서 특정한 특수 문자를 html entity로 변환한다.
변환되는 문자는 아래와 같다.
특수 문자 | 변환된 문자 |
& | & |
"" | " |
'' | ' |
< | < |
> | > |
따라서 위의 코드를 해석하자면
$data로 받은 문자열을 "", '' 둘 다 변환하여 UTF-8 문자셋으로 변환한다는 뜻이다.
사용자의 입력 값에서 html injection과 관련된 문자들을 위의 표대로 변환시키기 때문에 사용자가 어떤 값을 입력하더라도 브라우저가 html 요소로 해석하지 않아서 xss가 불가능하다.
따라서 난이도 high의 문제는 푸는 게 불가능하다.