4번 orc
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello admin</h2>";
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>
orc의 코드이다.
<?php
include "./config.php";
login_chk();
$db = dbconnect();
if(preg_match('/prob|_|\.|\(\)/i', $_GET[pw])) exit("No Hack ~_~");
$query = "select id from prob_orc where id='admin' and pw='{$_GET[pw]}'";
echo "<hr>query : <strong>{$query}</strong><hr><br>";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if($result['id']) echo "<h2>Hello admin</h2>";
preg_match를 통하여 필터링을 하며 get방식으로 pw를 받는다.
그리고 리턴값이 있다면 hello admin을 출력한다.
하지만 리턴값이 있으려면, 여기에서는 query 변수에 id를 admin으로 고정하였기 때문에,
진짜 pw값을 찾거나, pw를 우회하여야 한다.
$_GET[pw] = addslashes($_GET[pw]);
$query = "select pw from prob_orc where id='admin' and pw='{$_GET[pw]}'";
$result = @mysqli_fetch_array(mysqli_query($db,$query));
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
highlight_file(__FILE__);
?>
우선 addslashes 함수가 나왔다.
#addslashes
sql문으로 html문을 db로 입력할 때 ' " \ null 등으로 에러가 발생할 수 있다.
db에서는 이런 특수문자를 문자열을 구분하는 기준으로 보기 때문이다.
let's go 등의 문장을 넣을 때 '를 그냥 문자열이 아닌 html 기호로 보는 것이다.
이 때 addslashes를 함수를 이용하여 기호 앞에 \를 붙혀주면 문자열로 인식하게 된다. -> let\'s go
이러한 변환을 특수기호를 이스케이프 시켜준다라고 표현 할 수 있고, 반대로 웹에서 보여줄 때 붙혔던 \를 제거하는
stripslashes 함수가 있다.
ref) https://rootable.tistory.com/entry/addslashes-mysqlrealescapestring-%EC%9A%B0%ED%9A%8C
이 코드에서는 mysqli_fetch_array, preg_match와 같이 특수문자를 필터링하는 용도로 보면 된다.
if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("orc");
이 부분을 보면 입력한 pw값인 get pw값과 addslashes, 쿼리실행, mysqli_fetch_array를 거친 result pw 값이 같아야 한다.
즉 우회가 불가능하며 진짜 pw값을 찾아야한다. --> blind sql injection
pw=' or id='admin' and length(pw)=8#
먼저 mysql함수인 length 함수를 이용하여 비밀번호의 길이를 알아봤다.
pw=' or id='admin' and length(pw)=1# 를 입력하여 1부터 숫자를 올려 8에 갔을 때, hello admin이 출력되어 쿼리를 시켜 리턴값이 있음을 알 수 있다.
주의 해야 할 점은 id='admin'을 입력하여야 한다. (db에 admin 과 다른 아이디도 등록되어있다면 어떤 pw값을 쿼리하는지 알 수 없다) ,
pw=' or id='admin' and length(pw)=1#를 입력할 때, url을 보면 #만 인코딩 되지 않은 것을 볼 수 있다. #값을 %23으로 변경시켜서 쿼리를 날려야 한다.
길이를 알았으니 이제 실제 pw 값을 알아볼 것이다.
제일 많이 쓰는 substr 함수를 사용하였다.
substr(pw,1,1) 에서 첫번째 1은 자릿수이며 두번째 1은 출력할 갯수이다.
쿼리를 날려 참이면 hello admin을 출력하기 때문에, 부등호를 이용하여 아스키숫자의 범위를 좁혀가며 풀 수 있다.
<60 했을 때, hello admin이 나오며 1씩 줄여 <57까지 가면 출력되지 않는다. -> =57
노가다를 해서 각 자릿수 값을 모아 입력하면 클리어된다.
'wargame > los.rubiya.kr' 카테고리의 다른 글
6번 darkelf (0) | 2019.11.16 |
---|---|
5번 wolfman (0) | 2019.11.16 |
3번 goblin (0) | 2019.11.05 |
2번 cobolt (0) | 2019.11.04 |
1번 gremlin (0) | 2019.11.01 |