본문 바로가기
웹 해킹/CTF

[DIMI CTF] simple sqli

by L3m0n S0ju 2021. 3. 23.

118명 중에 20명이 위 문제를 풀었다.

 

 


 

 

주어진 주소르 이동하면 그림과 같은 페이지가 출력된다. 문제 이름이 simple sqli이므로 SQL 인젝션을 사용해서 문제를 해결해야 한다. 위 그림에서 해당 페이지의 소스가 궁금하다면 여기를 클릭하라고 한다. 클릭하여 코드를 열람하자.

 

 


<?php 

//error_reporting(E_ALL); 
//ini_set("display_errors", 1); 


require 'lib.php'; 

if (isset($_GET['view-source'])){ 
    highlight_file(__FILE__); 
    exit; 


$id = $_POST['id']; 
$pw = $_POST['pw']; 

//var_dump($conn); 

if (preg_match("/information|admin|or|\=| |\#|\'|_|where/i", $id . $pw)) 
    die("No Hack ~_~"); 

if (isset($id, $pw)) { 
    $query = "SELECT * FROM `users` WHERE `id` = trim('{$id}') AND `pw` = trim('{$pw}')"; 
    $result = mysqli_fetch_array(mysqli_query($conn, $query)); 

    if ($result['id'] === 'admin') 
        echo "<h1>{$flag}</h1>"; 

    if ($result['id']) { 
        $message = "{$result['id']}님 안녕하세요!"; 
    } else { 
        $message = "로그인에 실패하였습니다. 다시 시도해주세요."; 
    } 

 

 


 

위 코드는 문제 페이지 코드 중에 php 부분만 가져온 것이다. 여기서 봐야할 코드는 아래와 같다.

 

if (preg_match("/information|admin|or|\=| |\#|\'|_|where/i", $id . $pw)) 
    die("No Hack ~_~");

 

해당 php코드는 우리가 information, admin, or, =,  , #, ', _, where(대소문자 구별X) 같은 특수문자가 id, pw 변수 안에 존재하다면 필터링한다. 

 

 

 

 

$query = "SELECT * FROM `users` WHERE `id` = trim('{$id}') AND `pw` = trim('{$pw}')"; 

 

해당 데이터베이스 질의문은 users라는 테이블에서 우리가 입력한 아이디와 비밀번호가 일치하는지 결과가 query에 저장된다.

 


 

하지만 이번 문제 역시 필터링 함수에 취약점이 존재한다. 필터링 방식이 블랙 리스트인 것부터가 문제이지만 필터링해야 되는 특수문자인데 필터링 되지 않는 문자들이 존재한다. 바로 \(역슬래쉬), (Tab), ||(or) 같은 특수문자들은 필터링 되지 않는다.

 

기본적으로 가장 보편적인 sql injection은 ' or 1=1 -- 이다. 여기서 띄어쓰기는 필터링 되지만 (Tab)으로 대신할 수 있고 or은 || 으로 대신할 수 있다. 문제점은 '(작은 따옴표)는 다른 문자로 대체할 수 없다. 따라서 역슬래쉬를 이용하여 {$id} 뒤에 '(작은 따옴표)를 질의어 기능이 아닌 문자열로 바꾸는 방법을 사용한다.

 

id와 pw에 각각 id=\ pw=) || 1<2 --  를 입력하면 아래와 같이 질의어가 형성된다.(띄어쓰기는 (Tab)으로 대체한다)

 

$query = "SELECT * FROM `users` WHERE `id` = trim('\') AND `pw` = trim(') || 1<2 --  ')"; 

 

\'는 문자열 '(작은 따옴표)를 의미하므로 trim 뒤에 있는 '\') AND `pw` = trim(' 까지가 문자열이 되어 trim의 인자로 들어간다. 이를 문자열 S라고 가정하면 trim('S' 과 같이 오른쪽에 괄호가 없는 형태가 된다. 그래서 pw 앞에 )를 입력하여 trim 함수를 닫아준다. 그리고 ||은 or을 의미하고 뒤에는 항상 참이므로. 해당 주입문을 입력하면 플래그가 도출된다. pw=) || 1<2 -- 에서 마지막에 띄어쓰기를 빼먹으면 오류가 발생하므로 -- 뒤에도 탭을 입력하는 것을 주의하자.

 

 


플래그

 

'웹 해킹 > CTF' 카테고리의 다른 글

[Square CTF] Password checker  (0) 2021.08.11
[WebGoat] General - HTTP Proxies  (0) 2021.05.15
[WebGoat] General - HTTP Basics  (0) 2021.05.15
[DIMI CTF] exec me  (0) 2021.03.25
[DIMI CTF] 5shared  (0) 2021.03.23

댓글