webhacking.kr 38번, 39번, 54번 풀이

julia·2021년 3월 22일
0

벌써 2주차라니ㅜㅜ 친구들과 상의 끝에, 쉬울 때 문제 개수를 늘리기로 했고 이번 주에는 8문제가 아닌 12문제를 풀기로 했다. 우선 38번은 추론 능력이 조금 필요했던 것 같고(추론이라고 거창하게 말하지만 엄청 쉬웠다><) 39번은 치환 문제였으며, 54번은 간단했지만 코드 해석 및 수정할 때 약간 헷갈리는 부분이 있었다.

💡 38번 문제 풀이

처음에는 뭘 해야 할지 잘 모르니까 아무거나 입력해본다. 그냥 1을 입력했는데 아무 일도 일어나지 않았고, 그래서 개발자 도구를 열어보니 admin.php로 이동하라는 내용이 주석처리 되어있는 걸 확인할 수 있었다. 이럴 때 보면 워게임 저난이도 문제들은 참 친절하다. 실제 해킹에서도 공격자가 주석으로 흔적 남겨주면 좋겠는데ㅋㅋㅋ그럴 일은 얼마나 될까ㅎ,,

이동하니까 밑의 이미지가 나왔고 내가 입력한 1이 "ip주소:" 옆에 입력되어있었다. 그래서 그냥 뭔가 1 대신 admin을 치면 되는 것 같았는데,, 그 정도로 어이없게 쉽진 않았다. admin을 치고 admin.php로 들어가니까 내가 admin을 입력했던 로그가 안보임 두둥

당황하지 않기,, '아무거나 입력하고 줄바꿈한 다음에 ip:admin 하면 되지 않을까' 라는 생각이 바로 들어서 다행이었다. 근데 아무 생각 없이 input박스에서 엔터쳤는데 줄바꿈이 아니라 submit이 되더라ㅜㅜ 난 바보였어.. 결국 개발자 도구에서 input을 textarea로 변경해주고 하니까 되었다!! 성공~

💡 39번 문제 풀이

<?php
  $db = dbconnect();
  if($_POST['id']){
    $_POST['id'] = str_replace("\\","",$_POST['id']);
    $_POST['id'] = str_replace("'","''",$_POST['id']);
    $_POST['id'] = substr($_POST['id'],0,15);
    $result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
    if($result[0] == 1){
      solve(39);
    }
  }
?>

위 소스코드를 보면 id='{$_POST['id']} 이 부분에서 닫는 ' 가 없다. 그래서 입력칸에 마지막에 '를 붙여줘야 되겠다는 생각은 쉽게 드는데, 길이 제한이 있고(여기서 substr함수는 처음부터 15개의 문자를 잘라준다) \\와 ' 를 치환한다는걸 고려해야 한다.
admin(공백 9개)'
이렇게 입력하면 마지막 ' 이 ''로 치환되는데, substr 때문에 15자만 잘려서 하나의 싱글쿼터만 남는다. \\는 그냥 공백으로 처리되기 때문에 쓸 필요가 없다.

💡 54번 문제 풀이

54번 문제로 들어가면 패스워드가 한글자씩 바뀌면서 보이는데 너무 순식간에 지나간다. 난 그걸 다 빨리 읽어 낼 초능력이 없당ㅎㅎ 패스워드를 다 보여주고 나서는 ? 를 보여준다. 아마 이게 초기화 상태인 것 같다.

<script>
function answer(i){
  x.open('GET','?m='+i,false);
  x.send(null);
  aview.innerHTML=x.responseText;
  i++;
  if(x.responseText) setTimeout("answer("+i+")",20);
  if(x.responseText=="") aview.innerHTML="?";
}
setTimeout("answer(0)",1000);
</script>

스크립트를 보면 어떻게 페이지가 작동하는지 볼 수 있는데 일단 메인이 되는 answer함수만 갖고 왔다. i++와 setTimeout함수를 이용해 패스워드를 한글자씩 다음 글자로 넘기면서 순식간에 촤라락 보여주나보다. 마지막 줄에 있는 setTimeout은 처음 값을 불러오기까지의 시간을 설정해준 것으로, 지금은 1초만에 패스워드 노출이 시작되지만 만약 10000으로 바꾼다면 10초 후에 패스워드를 호출해준다. 답을 한줄로 얻기 위해서는 스크립트를 조금 수정해줘야 할 것이다.

function answer(i){
  x.open('GET','?m='+i,false);
  x.send(null);
  aview.innerHTML+=x.responseText;
  i++;
  if(x.responseText) setTimeout("answer("+i+")",20);
}
setTimeout("answer(0)",1000);

수정 후의 코드이다.
사실 코드 해석할 때 대충은 이해가 되었지만 저 open 부분이 뭔지 몰라서 수정할 때 저 부분을 건드려야할지 말지 헷갈렸던 것 같다. 찾아보니 open(http요구 방식, 요구하고자 하는 url, 비동기 여부) 로 쓴다고 한다. 그래서 여기서는 get방식으로 '?m='+i라는 url을 요청하고 동기적으로 처리한다는 것이다. 동기/비동기는 더 공부해야겠다..

다시 수정 코드에 대해 얘기해보자면,,
if(x.responseText=="") aview.innerHTML="?"; 이 부분은 서버의 응답이 없을 때 더 이상 패스워드를 호출하지 않고 ? 로 초기화하는 코드이므로 제거해주었다. 그리고 aview.innerHTML+=x.responseText; 이 부분에서 =를 +=로 변경한 이유는 한글자씩이 아니라 완성된 패스워드를 보고 싶기 때문이다.
변경한 코드를 콘솔 창에 입력해 주면 패스워드가 전부 출력된다. 도출해낸 값(FLAG{답})을 AUTH 페이지에 가서 입력하면 포인트를 얻을 수 있다!!

😎 느낀점

전반적으로 아직까지는 엄청 간단하고 쉬운 문제들이지만 이 간단한 것들도 막상 스스로 하려니 시간이 좀 걸린다. 점점 어려워질 거라 겁이 나긴 하지만, 문제들 하나하나 해결해나가는 재미가 있고 꼭 해내야겠다는 오기가 생긴다. 특히 깨달은 점이 있다면, 소스코드를 보고 어떤 부분이 무슨 역할을 하는지 정확히 알아야 코드를 수정할 수 있다는 걸 알게 되었고 사소한 기본 개념이더라도 더 탄탄히 쌓아가야겠다는 생각이 들었다.

profile
Move Forward

0개의 댓글