Wargame/HackCTF

[HackCTF] Authenticate 풀이 (350p)

bjloed 2020. 7. 11. 20:48

문제 종류 - Web
사용한 툴 - 

 

풀이

문제에 들어가면 다음과 같은 로그인 창이 존재한다.

처음에는 SQL Injection인줄 알았으나, 아니었다. 소스 코드를 확인해보자.

Javascript부분에 해당 코드가 존재한다.

$(".c_submit").click(function(event) {
    event.preventDefault();
    var u = $("#cpass").val();
    var k = $("#cuser").val();
    var func = "\x0d\x13\x45\x17\x48\x09\x5e\x4b\x17\x3c\x1a\x1f\x2b\x1b\x7a\x0c\x1f\x66\x0b\x1a\x3e\x51\x0b\x41\x11\x58\x17\x4d\x55\x16\x42\x01\x52\x4b\x0f\x5a\x07\x00\x00\x07\x06\x40\x4d\x07\x5a\x07\x14\x19\x0b\x07\x5a\x4d\x03\x47\x01\x13\x43\x0b\x06\x50\x06\x13\x7a\x02\x5d\x4f\x5d\x18\x09\x41\x42\x15\x59\x48\x4d\x4f\x59\x1d\x43\x10\x15\x00\x1a\x0e\x17\x05\x51\x0d\x1f\x1b\x08\x1a\x0e\x03\x1c\x5d\x0c\x05\x15\x59\x55\x09\x0d\x0b\x41\x0e\x0e\x5b\x10\x5b\x01\x0d\x0b\x55\x17\x02\x5a\x0a\x5b\x05\x10\x0d\x52\x43\x40\x15\x46\x4a\x1d\x5f\x4a\x14\x48\x4b\x40\x5f\x55\x10\x42\x15\x14\x06\x07\x46\x01\x55\x16\x42\x48\x10\x4b\x49\x16\x07\x07\x08\x11\x18\x5b\x0d\x18\x50\x46\x5c\x43\x0a\x1c\x59\x0f\x43\x17\x58\x11\x04\x14\x48\x57\x0f\x0a\x46\x17\x48\x4a\x07\x1a\x46\x0c\x19\x12\x5a\x22\x1f\x0d\x06\x53\x43\x1b\x54\x17\x06\x1a\x0d\x1a\x50\x43\x18\x5a\x16\x07\x14\x4c\x4a\x1d\x1e";
    buf = "";
    if (k.length == 9) {
        for (i = 0, j = 0; i < func.length; i++) {
            c = parseInt(func.charCodeAt(i));
            c = c ^ k.charCodeAt(j);
            if (++j == k.length) {
                j = 0;
            }
            buf += eval('"' + a(x(c)) + '"');
        }
        eval(buf);
    }
    
    else {
        $("#cresponse").html("<div class='alert alert-danger'>Invalid creds...</div>");
    }
});

function a(h) {
    if (h.length != 2) {
        h = "\x30" + h;
    }
    return "\x5c\x78" + h;
}

function x(d) {
    if (d < 0) {
        d = 0xFFFFFFFF + d + 1;
    }
    return d.toString(16).toUpperCase();
}

함수 a와 함수 x의 작동 방식은 딱히 알 필요는 없다.

\x0을 붙이거나 16진수화 시켜주는 함수이다.

 

이제 문제를 풀어야 하는데 main쪽 부분에 user의 길이가 9여야 정상적으로 코드가 동작한다.

개발자 도구 콘솔을 이용해 Javascript를 동작시켜봤다.

username에 123456789를 넣고 실행해봤다.

코드 동작을 위해 수정한 코드는 다음과 같다.

function main() {
    var c = "";
    var k = "123456789";
    var func = "\x0d\x13\x45\x17\x48\x09\x5e\x4b\x17\x3c\x1a\x1f\x2b\x1b\x7a\x0c\x1f\x66\x0b\x1a\x3e\x51\x0b\x41\x11\x58\x17\x4d\x55\x16\x42\x01\x52\x4b\x0f\x5a\x07\x00\x00\x07\x06\x40\x4d\x07\x5a\x07\x14\x19\x0b\x07\x5a\x4d\x03\x47\x01\x13\x43\x0b\x06\x50\x06\x13\x7a\x02\x5d\x4f\x5d\x18\x09\x41\x42\x15\x59\x48\x4d\x4f\x59\x1d\x43\x10\x15\x00\x1a\x0e\x17\x05\x51\x0d\x1f\x1b\x08\x1a\x0e\x03\x1c\x5d\x0c\x05\x15\x59\x55\x09\x0d\x0b\x41\x0e\x0e\x5b\x10\x5b\x01\x0d\x0b\x55\x17\x02\x5a\x0a\x5b\x05\x10\x0d\x52\x43\x40\x15\x46\x4a\x1d\x5f\x4a\x14\x48\x4b\x40\x5f\x55\x10\x42\x15\x14\x06\x07\x46\x01\x55\x16\x42\x48\x10\x4b\x49\x16\x07\x07\x08\x11\x18\x5b\x0d\x18\x50\x46\x5c\x43\x0a\x1c\x59\x0f\x43\x17\x58\x11\x04\x14\x48\x57\x0f\x0a\x46\x17\x48\x4a\x07\x1a\x46\x0c\x19\x12\x5a\x22\x1f\x0d\x06\x53\x43\x1b\x54\x17\x06\x1a\x0d\x1a\x50\x43\x18\x5a\x16\x07\x14\x4c\x4a\x1d\x1e";
    buf = "";
    if (k.length == 9) {
        for (i = 0, j = 0; i < func.length; i++) {
            c = parseInt(func.charCodeAt(i));
            c = c ^ k.charCodeAt(j);
            if (++j == k.length) {
                j = 0;
            }
            buf += eval('"' + a(x(c)) + '"');
        }
        console.log(buf);
    }else {
        $("#cresponse").html("<div class='alert alert-danger'>Invalid creds...</div>");
    }
}


function a(h) {
    if (h.length != 2) {
        h = "\x30" + h;
    }
    return "\x5c\x78" + h;
}

function x(d) {
    if (d < 0) {
        d = 0xFFFFFFFF + d + 1;
    }
    return d.toString(16).toUpperCase();
}

출력 결과는 다음과 같다.

그냥 쓰레기 값이다.

아무런 정보도 주어지지 않은채로 username을 어떻게 맞춰야 할까 고민을 했는데 코드를 보니까 cresponse라는 9글자 문자열이 존재했었다. id라는 이름으로 지어진 것을 보아하니 아마 맞는 듯하다.

username 부분에 cresponse를 넣고 코드를 돌려봤다.

sdumbh4ck5라는 굉장히 수상해보이는 문자열이 출력되었는데, 해당 문자열은 10글자이니,

sdumbh4ck 이거나 dumbh4ck5이 맞는 문자열인 것 같다. 둘 다 username 값에 넣고 돌려봤다.

먼저 sdumbh4ck의 결과이다.

음... 일단 아니고 ^---^.. 다음은 dumbh4ck5의 결과이다.

XorIsNotSooS3cur3이 u 값일 경우, if문이 실행된다. 한번 넣어보자.