Quest. 분명 당신은 검색 창에 아무 의미도 없는 값을 입력했습니다. 하지만 burp suite라는 취약점 분석 도구를 통해 아래의 유의미한 결과를 출력할 수 있게 되었습니다. 이 도구를 통해 아무 값을 입력하여 아래 사진과 같이 출력하세요.
[난이도-low]
> hint1 GET 방식과 다르게 POST 방식은 전송되는 변수 값이 보이지 않습니다. 하지만 burp suite를 이용한다면 클라이언트에서 서버로 전송되는 값이 모두 보입니다. 이걸 이용하여 값을 조작해봅시다.
First name에 h1태그를 이용해 hello를 써주고 h2태그를 이용해 world를 입력해보았더니 위와 같이 나타났다.
버프 스위트에 위와 같이 나타났다. 16줄을 확인해보면 내가 작성한 값이 저장되어있는것을 확인할 수 있다.
first name에 <h1>SUCCESS</h1>를 입력했고 last name에 <img src="http://[본인IP]/bWAPP/images/bee_1.png">을 입력해주었다.
그랬더니 다음과 같은 결과를 얻을 수 있었다.
[난이도-medium]
> hint1 페이지 소스 코드를 확인해봅시다. <p>Enter your first and last name:</p> <form action="/bWAPP/htmli_post.php" method="POST"> <p><label for="firstname">First name:</label><br /> <input type="text" id="firstname" name="firstname"></p> <p><label for="lastname">Last name:</label><br /> <input type="text" id="lastname" name="lastname"></p> <button type="submit" name="form" value="submit">Go</button> </form> 우리는 form의 정보가 htmli_post.php로 전달됨을 알 수 있습니다.
> hint2 htmli_post.php 파일에 include("functions_external.php");라는 코드가 있습니다. 일부 함수를 functions_external.php 파일에 저장하는 듯 합니다.
> hint3 <과 >을 인코딩 했는데도 여전히 풀리지 않습니다. 더블 인코딩에 대해 알아봐야 할 것 같습니다.
위에서 본 결과와 다르게 h태그가 적용된 결과가 아닌 태그 그대로 출력됨을 확인할 수 있다.
페이지 소스코드를 확인해보았다.
<이 <로 변환되고, >이 >로 변환된다는 것을 확인할 수 있었다.
버프 스위트에서 security_level이 1인것을 알 수 있다.
htmli_post.php를 열어주어 확인해주었다. security_level이 1이므로 해당 단계는 xss_check_1에 해당된다.
xss_check_1함수를 찾아주었다.
여기서 <이 <로 변환되고, >이 >로 변환되도록 했다는 것을 알 수 있다.
first name에 %3Ch1%3ESUCCESS%3C%2Fh1%3E
last name에 %3Cimg%20src%3D%22http%3A%2F%2F[본인IP]%2FbWAPP%2Fimages%2Fbee_1.png%22%3E을 입력해주었다. 이는 low단계에 적었던 답들을 인코딩한 값에 해당된다.
[난이도-high] - 풀 수 없는 이유를 설명하세요
hint1. 서버에서 변수를 처리할 때 값을 조작하는 것 같습니다. php 파일을 살펴보면서 변수가 전달되는 과정을 지켜보면 답이 나올 듯 합니다. + burp suite가 작동하지 않을 때는 인증서 설정을 확인해보세요.
난이도 high에서는 security_level이 2이다. 이 함수를 위 과정과 동일하게 찾아보도록 하자.
case 2에 해당하므로 xss_check_3함수를 이용한다.
저번 실습에서 본 것과 동일하게 htmlspecialchars함수를 사용하고 있다. 이는 data로 받은 문자열을 UTF-8로 반환하는데 ", ' 둘 다 변환되기 때문에 문제를 풀 수 없다.
HTML injection 이란? 코드 인젝션 공격의 하위 개념으로 취약한 매개변수에 악의적인 HTML 코드를 삽입하는 공격
① 반사기법
: URL에 악의적인 HTML 태그를 삽입하여 링크를 클릭한 사용자의 PC에서 HTML 태그가 실행되게 하는 공격
- GET 방식으로 데이터를 전송할 경우, URL에 변수 이름과 입력 값을 노출한다.
② 저장기법
: 악의적인 HTML 태그를 데이터베이스에 저장하여 저장된 태그 내용을 확인한 사용자의 PC에 HTML 태그가 실행되게 하는 공격
반사기법
저장기법
차이점
URL에 HTML 태그 삽입
서버의 DB에 저장
2. 아래 화면 출력하기
먼저 실습 환경 구축을 해주었다.
[ 난이도 low ] img src: http://[본인IP]/bWAPP/images/bee_1.png hint1. 페이지 소스 코드를 확인해봅시다.
First name에 hello, Last name에 world를 입력해보았더니 Welcome hello world가 출력되는걸 볼 수 있었다.
그리고 URL이 bWAPP/htmli_get.php?firstname=hello&lastname=world&form=submit 로 변경되었다.
이렇게 URL에 데이터가 노출된다는 것을 확인할 수 있었다.
그리고 페이지 소스에도 Welcome hello world가 추가되었다.
이번엔 h1태그를 이용해 hello를 써주고 h2태그를 이용해 world를 입력해보았더니 위와 같이 나타났다.
그리고 이와 같은 소스코드가 생겼다.
URL은 ?firstname=<h1>hello<%2Fh1>&lastname=<h2>world<%2Fh2> 이러한 형식으로 바뀌었다.
※ 출력해야 하는 화면 중 First name에 해당하는 부분이 /SUCCESS/ 이므로 <h1>SUCCESS</h1>이 들어가야 한다고 생각했다. 그리고 Last name 부분에는 이미지가 들어가야 하므로 문제에서 준 img src: http://[본인IP]/bWAPP/images/bee_1.png 코드를 활용하고자 하였다.
이미지 태그를 삽입하기 위해 <img src="http://[본인IP]/bWAPP/images/bee_1.png">이라고 작성해주었더니
다음과 같은 결과가 나왔다.
[난이도 medium]
hint1. low일 때 성공한 페이지와 비교해봅시다. 소스코드 차이점이 반드시 있습니다.
hint2. URL Encoding
먼저 위에서 한 것과 동일하게 First name에 hello, Last name에 world를 입력해주었더니 동일한 결과가 나왔다
하지만 h태그를 이용해 작성해주었더니
위에서 본 결과와 다르게 h태그가 적용된 결과가 아닌 태그 그대로를 출력함을 확인할 수 있었다.
URL은 ?firstname=hello<%2Fh1>&lastname=world<%2Fh2>의 형태로 동일하게 나타났다.
페이지 소스 코드에서 low와의 다른점을 찾을 수 있었다.
좌측은 low의 코드, 우측은 medium의 코드이다.
우측 코드를 보면 <이 <로 변환되고, >이 >로 변환된다는 것을 알 수 있었다.
<와 >에 대해 검색해보니 마크업기반 언어에서 수식 속 부등호를 사용하기 위한 코드라고 한다.
따라서 우측 코드에서는 <와 >을 코드가 아닌 부등호로 인식한다는 것을 알 수 있었다.
firstname=hello<%2Fh1>&lastname=world<%2Fh2>에서도 볼 수 있듯이 인코딩이 필요하다고 생각했다.
<nav>
<div id="underline"></div>
<a href="About.php">About</a>
<a href="Board.php">Board</a>
<a href="Search.php">Search</a>
</nav>
<script>
let under = document.getElementById("underline");
let menu = document.querySelectorAll("nav a");
menu.forEach((menu)=>menu.addEventListener("mouseover",(e)=>indicator(e)));
function indicator(e){
under.style.left=e.currentTarget.offsetLeft+"px";
under.style.width=e.currentTarget.offsetWidth+"px";
under.style.top=e.currentTarget.offsetTop+e.currentTarget.offsetheight+"px";
}
</script>
a태그로 각 버튼에 알맞는 페이지를 연결시켰다. 이를 nav태그로 한번에 감싸주었다. 이렇게 각자 버튼을 만들었다.
여기서 각 버튼에 마우스를 가져갔을 때 밑에 밑줄을 생기도록 하고 싶었다. 그래서 자바스크립트를 이용해주었다.
먼저 underline과 nav a태그인 메뉴들을 가져와주었고 각 메뉴에다가 mouseover이벤트가 일어날때마다 indicator 함수를 실행하도록 하였다. 그리고 addEventListener을 통해 자동으로 event(e)를 넘겨주었다. 이 event 안에 뭘 선택했는지가 나오게 된다.
indicator함수에서는 인자를 e로 받아왔다.
div태그를 직사각형으로 보았을 때 아래쪽 변은 offsetWidth, 높이는 offsetheight, 위쪽 변과 상단 브라우저의 높이 차이는 offsetTop, 왼쪽 변과 좌측 브라우저의 간격 길이는 offsetLeft이다.
underline을 그리는 시작점은 (offsetLeft, offsetTop+offsetheight)이다.
따라서 left시작값인 x좌표는 offsetleft, width는 해당 메뉴(직사각형)의 너비만큼만 그려주면 되므로 offsetWidth, y좌표는 offsetTop+offsetheight로 지정해주었다.
이번주에는 리뷰 작성 페이지에 OTT와 카테고리를 선택하는 부분을 추가했다. 둘 다 제목 선택하는 것과 마찬가지로 select로 내용을 입력받도록 했다. 무조건 입력해야 하는 내용이므로 required 속성을 적용했고 초기의 상태인 ==선택== 은 disabled를 이용해 선택이 불가능하도록 설정했다. 나머지 다른 선택지들은 각각의 내용에 따라 적당한 value 값을 설정하여 구분하도록 하였다.