쉬는시간/xcz.kr

[xcz.kr] PROB18 문제풀이

happy-nut 2015. 11. 3. 23:26

18번 문제의 Title은 「Web Basic」입니다. Basic이라는 걸 보니 그리 어려운 문제는 아닌 것 같아 보입니다.

View source 아래 부분을 보시면 "wrong T.T"라는 문자열이 보입니다. 아직 문제를 풀기 전인데도 저런 문자열이 뜨는 건 누가봐도 좀 이상합니다. 만약 이 문제를 풀게되면 바로 저 부분에 답이 나올 것만 같다는 느낌이 드셨다면, 문제를 푸는 센스가 좋은 편이라고 볼 수 있습니다.

View source 링크를 클릭하여 들어가면 18번 문제의 소스코드가 보입니다.

"<?" 표시는 이제부터 php 코드로 해석해달라고 브라우져에게 알려주는 신호입니다. php는 소스코드가 외부에 노출되지 않게 하는 게 기본 설정이지만 이 문제에서는 공격자를 배려하여 소스코드를 노출하고 있습니다.

변수명이 난잡하므로 알기 쉽게 치환해서 풀어써보면 다음과 같습니다.

$key = "Congratulations! Key is ??????????????????"; 
$cookie = @$_COOKIE['c']; 
$get_g = @$_GET['g']; 
$post_p = @$_POST['p']; 
if(empty($cookie) || empty($get_g) || empty($post_p)){exit ('wrong T.T');} 
$valueA = $get_g . $cookie; 
$valueB = $post_p; 

function test($a){ 
$b = ''; 
    for($i=0; $i < strlen($a); $i++){ 
        $b = $b . ' - ' . ord(substr($a,$i,1)); 
    } 
    return $b; 
} 
if(test($valueA)==" - 103 - 105 - 118 - 101 - 109 - 101 - 112 - 97 - 115 - 115 - 119 - 111 - 114 - 100" || test($valueB) == " - 107 - 101 - 121 - 112 - 108 - 122 - 33"){ 
    echo $key; 
} 
else{ 
    echo 'wrong T.T'; 
}

이 포스팅에서 처음 code highlight를 해봤습니다. 그리 썩 맘에 들진 않지만 없는 것 보단 나은 것 같습니다. 코드를 처음부터 찬찬히 들여다 봅시다. 

line 2~7 : get 메소드로 받은 g의 값과 Cookiec를 합친 문자열이 valueA에 들어가고, post 메소드로 받은 pvalueB에 들어갑니다.

line 9~15 : php에서 ord()함수는 인자로 받은 문자의 아스키(Ascii)코드 값을 결과로 반합니다. 이 사실을 상기하고 잘 들여다 보면 test 함수는 인자로 받은 문자열을 1글자 단위로 조각내어 아스키 코드를 구하고 ' - ' 로 이어붙이는 역할을 담당하고 있음을 알 수 있습니다.

따라서 valueA는 " - 103 - 105 - 118 - 101 - 109 - 101 - 112 - 97 - 115 - 115 - 119 - 111 - 114 - 100" 로 미루어 보아 "givemepassword" 이고, valueB는 " - 107 - 101 - 121 - 112 - 108 - 122 - 33" 로 미루어 보아 "keyplz!"임을 알 수 있습니다.

Tip. 이런 경우에 인터넷에서 아스키코드 표를 찾아다니며 눈아프게 짜맞추기 보단, 메모장(notepad)를 활용하면 빠르고 쉽게 매치되는 문자를 찾을 수 있습니다. ALT키를 누른 체로 아스키코드값을 누르게 되면 해당 Ascii값에 해당하는 문자가 메모장에 찍힙니다.

ex) ALT + 65 = 'A'

따라서 get으로 "giveme"를 넘기고, cookie에 "password"를 갱신하고, post로 "keyplz!"를 넘기면 문제는 바로 풀릴겁니다.

이는 파로스와 같은 툴을 사용하면 굉장히 쉽게 해결될 일이지만, 이 문제에 대해 포스팅을 하고 있는 이 시점 필자는 군대에 있는 까닭에 최대한 인터넷에서 프로그램을 다운로드를 받지 않고 문제를 풀어야 합니다.(pc가 악성코드에 감염되면 군생활이 늘어날지도 모르기 때문에 ㅠ)


우선 문제를 풀기 위해 해야 할 일은 앞서 설명드렸듯이 다음 3가지 입니다.

  1. get으로 "giveme"라는 값을 가진 g를 넘긴다.
  2. cookie에 "password"라는 값을 가진 c를 갱신한다.
  3. post로 "keyplz!"라는 값을 가진 p를 넘긴다.

차근차근 해 보겠습니다.


1. get으로 "giveme"라는 값을 가진 g를 넘긴다.

get방식으로 값을 넘기는 건 굉장히 쉽습니다. 주소뒤에 간단히 추가만 하면 되기 때문입니다.

URL에다 http://xcz.kr/START/prob/prob18.php?g=giveme라고 입력하면 get방식으로 "giveme"라는 값을 가진 g가 넘어갈 것입니다.(이는 파로스(Paros)나 피들러(Fiddler) 같은 툴로 확인해보면 알 수 있습니다)



2. cookie에 "password"라는 값을 가진 c를 갱신한다.

cookie에 "password"라는 값을 갱신하는 것도 어렵지 않습니다. 주소창에 간단한 Javascript코드만 섞어주면 되기 때문입니다.

 javascript:alert(document.cookie);

javascript:는 뒤에 올 문자열이 주소값이 아닌, javascript라고 명시를 해줍니다. 따라서 브라우져는 이를 인식하고 해당페이지에 javascript코드를 실행시키게 됩니다. 주소창에 위 코드를 치고 Enter을 누르게 되면 해당 브라우져가 가지고 있는 쿠키 값이 나타납니다.

이제 주소창에 다음과 같이 입력을 해보면, 쿠키값이 갱신된 것을 확인할 수 있습니다.

 javascript: document.cookie="c=password";alert(document.cookie);



3. post로 "keyplz!"라는 값을 가진 p를 넘긴다.

문제는 POST인데, "<form>태그에서 submit으로 전송될 때 값이 post로 넘어간다"는 POST의 특징을 잘 생각해보면 이것 역시 Javascript로 만들어 볼 수 있습니다.

Step 1. Form 태그 만들기

var form = document.createElement("form");
form.setAttribute("method", "post");
form.setAttribute("action", "http://xcz.kr/START/prob/prob18.php");

createElement는 인자로 받은 문자열과 매치되는 태그를 생성해 줍니다. setAttrubute는 태그에 속성을 부여하는 역할을 합니다. 


Step 2. Form 태그에 Input태그 추가하기

var input = document.createElement("input");
input.setAttribute("type", "hidden");
input.setAttribute("name", "p");
input.setAttribute("value", "keyplz!");
form.appendChild(input);

이번엔 input태그를 만드는 과정이고, form태그를 만들 때와 크게 다른 점은 없습니다.


step 3. Document에 Form 을 추가하고 submit 하기

document.body.appendChild(form);form.submit();

appendChild는 인자로 받은 Element를 document안에 실질적으로 추가해줍니다. submit을 하게되면 form에 attribute로 등록했던 주소로 POST메소드를 이용해 data를 전송하게 됩니다.

여기까지 하면 POST로 "keyplz!"라는 값을 가진 p를 넘길 준비가 끝났습니다. 


이제 하나씩 준비했던 1, 2, 3 세 가지를 전부 합치는 일만 남았습니다. 쿠키는 새로운 세션을 만들거나 쿠키 삭제를 하지 않는 이상은 계속 남아 있을 테니, POST와 GET을 한번에 보내기만 하면 됩니다. 이것 역시 GET방식으로 보낼 때 필요한 URL로 POST방식으로 보낼 때 필요한 URL을 대체하면 아무 문제 없습니다. 

Step 1. POST와 GET 한번에 보내기
function post(URL) {
 var form = document.createElement("form");
 form.setAttribute("method", "post");
 form.setAttribute("action", URL);
 var input = document.createElement("input");
 input.setAttribute("type", "hidden");
 input.setAttribute("name", "p");
 input.setAttribute("value", "keyplz!");
 form.appendChild(input);
 document.body.appendChild(form);
 form.submit();

post("http://xcz.kr/START/prob/prob18.php?g=giveme");     //get을 위한 URL을 입력한다.

주석에 명시되어 있듯이, POST를 할 주소를 GET방식이 적용된 주소로 바꿔주면 해당 페이지는 GET과 POST 두가지 방법으로 data를 전송하게 됩니다.


Step 2. 주소창에 복사하기

Step 1.에서 만든 코드 앞에 javascript:를 붙여 페이지 URL 입력란에 입력하게 되면 아래와 같이 툴을 전혀 쓰지 않고도 깔끔하게 문제가 풀린다.(만약 복사했는데 안된다면, 맨 앞의 javascript: 가 확실히 복사되었는지 확인해보면 되겠습니다)



답 : web_basic_problem_haha


'쉬는시간 > xcz.kr' 카테고리의 다른 글

[xcz.kr] PROB14 문제풀이  (0) 2015.11.07
[xcz.kr] PROB20 문제풀이  (0) 2015.11.05
[xcz.kr] PROB7 문제풀이  (0) 2015.11.01
[xcz.kr] PROB22 문제풀이  (0) 2015.11.01
[xcz.kr] PROB6 문제풀이  (0) 2015.11.01