iframe Injection
iframe은 HTML 문서 안에서 또 다른 HTML 문서를 출력하는 태그로, 어느 위치든 상관없이 인젝션 공격을 할 수 있다.
iframe 인젝션은 독립적으로 만들 수 있어서 HTML 인젝션 중에서도 공격에 자주 사용한다.
HTML 인젝션에서 사용하는 태그와 마찬가지로 페이지 내에 iframe 태그를 주입하는데, 주로 악성 URL을 삽입한 후 사이즈를 0으로 설정하여 숨기는 방법을 사용한다.
따라서 사용자가 의도하지 않은 악성 웹 사이트에 접속하거나 경고창을 띄울 수 있다.
이번 실습에서 목표로 하는 것은 success 경고창을 띄우는 것이다.
난이도 low
iframei.php 페이지는 GET 방식으로 데이터를 전송받으므로 URL에 변수를 노출한다.
변수는 ParamUrl, ParamWidth, ParamHeight 총 세 가지로, ParamUrl은 연결할 주소를 받아오고, ParamWidth와 ParamHeight는 내용을 출력할 크기를 지정한다.
웹 브라우저 개발자 도구로 코드를 확인했다.
iframei.php 페이지는 iframe 태그를 사용하여 bWAPP 디렉터리에 있는 robots.txt 파일의 내용을 출력한다.
URL에서 ParamUrl 변수의 값은 robot.txt.이다.
이 변수에 입력한 내용이 iframe 태그에 추가되어 기존 iframe 태그를 강제로 닫고 URL에 노출된 변수에 악의적인 iframe 태그를 주입하는 방법을 사용한다.
iframe 태그로 사용자 모르게 악의적인 HTML 페이지를 출력하는 공격을 하기 위하여 HTML 페이지를 먼저 만든다.
웹 서버가 없는 경우 비박스의 웹 서버에 HTML 페이지를 먼저 만든다.
비박스는 리눅스 기반의 CLI 환경이어서 터미널을 통하여 명령어를 입력하여 프로그램을 실행한다.
HTML 페이지를 만드려면 비박스의 가상환경에서 터미널을 실행한다.
터미널을 열면 사용자 이름과 로컬 호스트 명, 현재 있는 디렉터리 위치와 $ 표시를 출력한다.
웹 애플리케이션에서 접근할 수 있는 디렉터리에 악의적인 HTML 페이지를 생성해야 iframe 태그로 페이지를 호출할 수 있다.
따라서 비박스에서 지정된 웹 애플리케이션 디렉터리인 /var/www/bWAPP으로 이동한다.
cd /var/www/bWAPP
vi 편집기를 사용하여 bad.html이라는 파일을 생성한다.
파일 생성이나 수정 권한은 루트만 갖고 있기 때문에 sudo 명령어를 앞에 추가한다.
sudo vi bad.html
입력하면 아무 내용이 없는 빈 파일이 열린다.
키보드에서 'i'를 누르면 편집 가능한 상태가 되고 여기에 HTML 코드를 입력한다.
<html>
<head>
<h1>Iframe Injection</h1>
<script>alert("Succeed")</script>
</head>
</html>
HTML 코드 내용은 헤딩 태그로 'Iframe Injection'이라는 제목을 웹 페이지에 출력하고 Succeed'라는 메시지를 경고창으로 출력한다.
입력을 마치면 ESC를 누른다.
ESC를 누르면 화면 하단에 vi 편집기 명령어를 입력할 수 있는데, :wq!를 입력하여 내용을 저장하고 vi 편집기를 종료한다.
그 다음 bad.html 파일이 제대로 생성되었는지 알아보기 위하여 ls 명령어를 입력한다.
이전에는 존재하지 않았던 bad.html 파일이 생긴 것을 확인했다.
vi 편집기를 사용하기 어려운 경우는 GUI 기반의 파일 편집기를 실행한다.
마찬가리졸 파일 생성 권한이 있어야 하므로 sudo 명령어를 사용한다.
GUI 파일 편집 프로그램인 gedit을 입력하면 루트 권한으로 gedit이 실행된다.
sudo gedit
gedit에 앞의 HTML 코드를 입력하고 저장한다.
저장할 때는 반드시 파일 이름 명에 .html 확장자를 입력하고 파일 저장 위치가 /var/www/bWAPP인지를 확인한다.
HTML 페이지를 만들고 나면 iframei.php 페이지로 이동하여 ParamUrl 변수에 악의적인 HTML 페이지를 호출하는 iframe 태그를 입력한다.
ParamUrl 변수의 값이 원래 페이지의 iframe 태그에 추가되기 때문에 ></iframe>을 입력하여 원래 페이지의 iframe 태그를 닫는다.
그리고 /var/www/bWAPP 디렉터리 안에 생성한 bad.html 페이지를 iframe의 src 속성에 입력한다.
http://localhost/bWAPP/iframei.php?ParamUrl=robots.txt"></iframe><iframe src="bad.html" width="250" height="250"></iframe>&ParamWidth=250&ParamHeight=250
변수에 iframe 태그를 입력하고 엔터를 누르면 웹 브라우저에서 bad.html 파일의 코드를 해석하고 iframe 인젝션 결과로 'Succeed'라는 메시지를 경고창으로 출력한다.
OK 버튼을 클릭하면 robots.txt 내용 옆에 bad.html에 입력한 헤딩 태그를 출력하고 그 옆에는 정상 iframe 태그에 들어가는 넓이와 높이 속성이 문자열로 출력한다.
OK 버튼을 클릭하면 robots.txt 내용 옆에 bad.html에 입력한 헤딩 태그를 출력하고 그 옆에는 정상 iframe 태그에 들어가는 넓이와 높이 속성이 문자열로 출력한다.
정상 iframe 태그를 강제로 닫았기 때문에 속성이 노출된 것이다.
ParamWidth 변수에 iframe 태그를 주입하면 정상 iframe 태그의 가장 마지막이기 때문에 ">만 출력한다.
iframe 태그를 주입한 후 웹 개발자 도구로 iframei.php 페이지의 소스 코드를 확인하면 원래 있던 iframe 태그가 닫히고 악의적으로 주입한 iframe 태그가 추가된 것을 볼 수 있다.
사용자 몰래 iframe 인젝션 공격을 하기 위하여 iframe의 width 속성과 height 속성을 0으로 수정한다.
http://localhost/bWAPP/iframei.php?ParamUrl=robots.txt"></iframe><iframe src="bad.html" width="0" height="0"></iframe>&ParamWidth=250&ParamHeight=250
iframe의 넓이와 높이를 전부 0으로 만들어도 Succeed라는 메세지의 경고창은 출력된다.
그러나 이전과는 다르게 bad.html에 입력한 헤딩 태그를 출력하지 않는다.
따라서 공격자는 iframe 인젝션으로 경고창을 출력하여 원래 사이트에서 정상적인 응답인 것처럼 사용자를 속일 수 있다.
그러나 정상 iframe 태그의 높이와 넓이가 같이 출력된다면 페이지가 이상하다는 것을 발견할 것이다.
따라서 스크롤을 내리지 못하면 이상한 점을 눈치채지 못하도록 높이 속성을 아주 큰 값으로 설정한다.
http://localhost/bWAPP/iframei.php?ParamUrl=robots.txt" width=250 height=1000></iframe><iframe src="bad.html" width=0 height=0></iframe>&ParamWidth=250&ParamHeight=250
그러면 이전과는 다르게 정상적인 웹 페이지로 보인다.
난이도 high
화면에서 변화를 확인하기 위해 height를 변경하지 않은 iframe 태그를 입력하였다.
URL의 ParamUrl 변수에 iframe 태그를 입력하여도 아무 반응이 없다.
이는 결과를 출력하기 전에 우회 단계를 거치기 때문에 웹 브라우저에서 입력 데이터를 태그로 해석하지 않아서이다.
iframei.php 페이지의 소스 코드를 확인했다.
난이도 하와 다르게 xss_check_3 함수로 입력 데이터를 우회한다.
xss_check_3 함수는 functions_external.php에 정의되어 있다.
htmlspecialchars라는 함수를 이용해서 입력값을 우회한다.
htmlspecialchars 함수는 PHP에서 제공하는 기본 함수로, HTML에서 사용하는 특수 문자를 UTF-8로 반환한다.
문장 내에 HTML코드가 들어가는 특수문자를 포함시켜 입력하고 화면으로 출력할 때, HTML의 특수문자가 HTML태그로 적용되는 것이 아니라 일반 문자로 인식되어 그대로 출력한다.
따라서 iframe 인젝션을 막으려면 htmlspecialchars 함수를 사용하여 웹 브라우저에서 iframe 태그에 사용되는 문자들을 HTML 태그로 해석하지 않게 입력 데이터를 UTF-8로 인코딩한다.