본문 바로가기
Security/[게임] CTF 풀이

Hacklu 2013 web200 writeup

by blackcon 2013. 10. 25.
728x90

<main>




<key.js>

document.forms[0].addEventListener('submit', function(e) {

    var key = document.getElementById('key').value;

    var xhr = new XMLHttpRequest();

    xhr.open('post', document.forms[0].action);

    xhr.addEventListener('load', function() {

        data = JSON.parse(xhr.responseText);

        if (data['success']) {

            document.getElementById('error').style.display = 'none';

            document.getElementById('noise').style.display = 'none';

            document.getElementById('news').style.display = 'block';

            document.getElementById('newstext').innerHTML = data['response'];

        } else {

            document.getElementById('error').innerHTML = data['response'];

        }

    });

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    xhr.send('key=' + encodeURIComponent(key)/* + '&debug'*/)

    e.preventDefault();

    return false;

});

document.getElementById('key').focus(); 



값을 전송하고 응답은 json형식으로  {"response":"Wrong flag", "success":"false"}가 날라온다.


key.js에서 &debug의 주석을 없애고 다시 데이터를 전송하면 

  {"start":[timestamp], "end":[timestamp], "response":"Wrong flag", "success":"false"}가 온다.

값은 end > start이었고 이걸로 미루어 보아 전송한 키값으로 연산을 하고 응답패킷을 보내는듯 하다.


그럼 end-start값을 화면에 보기좋게 하기 위해서 key.js 코드를 아래와 같이 수정하였다.


document.forms[0].addEventListener('submit', function(e) {

    var key = document.getElementById('key').value;

    var xhr = new XMLHttpRequest();

    xhr.open('post', document.forms[0].action);

    xhr.addEventListener('load', function() {

        data = JSON.parse(xhr.responseText);

        document.getElementById('noise').style.display = 'none';

        document.getElementById('news').style.display = 'block';

        document.getElementById('newstext').innerHTML =  data['response'];

        document.getElementById('error').innerHTML =data['end']-data['start'];

        

    });

    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');

    xhr.send('key=' + encodeURIComponent(key) + '&debug')

    e.preventDefault();

    return false;

});

document.getElementById('key').focus(); 


 오른쪽 하단에 나오는 숫자가 end-start를 한 값이다.(캡처해둔 사진이 이것밖에 없어서 중간 과정 못보여드린점 양해바라구요...ㅜㅜ)

 password를 전송해서 서버에서는 한글자씩 flag와 비교를 하여 틀리면 바로 return, 글자가 맞으면 sleep(n)정도 한 후 return을 전송한다.


 모든 글자가 틀렸을 경우 end-start = 0.000375838 이런 식으로 아주 작은 숫자였으나,

첫자리부터 차례로 비교를 했을대 처음 한자리가 맞다면 0.10284028, 둘재자리까지 맞다면 0.2392049, 위의 사진처럼 7자리가 모두 맞다면 '0.7083284로 나타내어 진다. 이 과정은 문자 하나씩 입력하여 10분만 투자하면 바로 얻을 수 있다. 물론 코드로 해도 좋고!ㅎㅎ


  password가 일치하는 순간  {"response":"OH_THAT_ARTWORK", "success":"true"}를 받게되고  tv에 flag가 뜬다.

  password : AXMNP93               flag : OH_THAT_ARTWORK



[숨겨진 힌트!!] = tv옆 신문에 적혀있다.

side channel attack : 신호나 연산 시간으로 key를 얻을수 있다.



728x90