Try   HackMD

HKCert20 CTF : LockPickDuck v3 (I) (II) (III)

(25 pts, 23 solves) - (25 pts, 17 solves) - (428 pts, 7 solves)
Solver: T0022 - HKUST Member 2

This challenge has part (I), (II), (III) and (IV). This is the writeup of (I), (II) and (III). For part (IV), please click here.

http://tertiary.pwnable.hk:50011

<?php class SQZero3 extends SQLite3 { private $user; private $pass; function __construct($user, $pass) { $this->open(":memory:"); $this->exec("CREATE TABLE users (user text, pass text, hash text)"); $this->user = $user; $this->pass = $pass; } function checkHash(){ return @($this->querySingle("SELECT hash FROM users WHERE user='{$this->user}' AND pass='{$this->pass}'") == md5($this->pass)); } function checkUser(){ return @($this->querySingle("SELECT user FROM users WHERE user='{$this->user}' AND pass='{$this->pass}'") == $this->user); } function checkPass(){ return @($this->querySingle("SELECT pass FROM users WHERE user='{$this->user}'") == $this->pass); } function checkMate(){ return @($this->querySingle("SELECT hash FROM users WHERE user='{$this->user}' AND pass='{$this->pass}'") === md5($this->pass)) && @($this->querySingle("SELECT user FROM users WHERE user='{$this->user}' AND pass='{$this->pass}'") === $this->user) && @($this->querySingle("SELECT pass FROM users WHERE user='{$this->user}'") === $this->pass); } } if (isset($_GET["user"]) && isset($_GET["pass"])) { require("flag.php"); $sq = new SQZero3($_GET["user"], $_GET["pass"]); if ($sq->checkHash()) { echo "<p>Flag 1: $flag1</p>"; if ($sq->checkUser()) { echo "<p>Flag 2: $flag2</p>"; if ($sq->checkPass()) { echo "<p>Flag 3: $flag3</p>"; } } } else { echo "No Flag"; } if ($sq->checkMate()) { echo "<p>Flag 4: $flag4</p>"; } } else { highlight_file(__FILE__); } ?>

Okay. So we are going to get Flag 1-3. Let's analyze the php code first.

Analyze

As we can see, the website use GET to get the field user and pass. If the both fieids are set, it will first create a BLANK SQLite table. Then it will do a single query from that black table, to see if the query return value equals a specfic value. A worth note point is that the table is a blank table. How could it return value other than NULL? So we know that this is a SQL Injection challenge (Reference: CTF Wiki). We could also see that we have to satisfiy the situation of Flag 1 and 2 in order to get Flag 3. In other words, we get Flag 1 and 2 if we can get Flag 3. Let's see at what situation we can get Flag 3!

SELECT hash FROM users WHERE user='{$user}' AND pass='{$pass}' == md5($pass) AND
SELECT user FROM users WHERE user='{$user}' AND pass='{$pass}' == $user AND
SELECT pass FROM users WHERE user='{$user}' == $pass

If we could satisfy this statement, then we could get Flag 1, 2 and 3!

==
===

If you play Web Challenge much, this is actually a easy task. You could notice that the statement is using the == operator but not the === operator! By PHP manual, $a === $b will return TRUE if $a is equal to $b, and they are of the same type (identical). While$a == $b will return TRUE if $a is equal to $b after type juggling. It means that the type of the operand will change if they are not the same type. Therefore, when a string is compared with a int value by the == operator, the string will be converted to int! Following the conversion rule, if the string is not started with a numeric value, it will be converted to 0.

In this task, md5($pass), $user and $pass are all string. Therefore, if they are compared with a numeric value, all of them will be converted to 0! So just do the injection to make the SQL query return 0 and we will get all 3 flags! Easy points, huh?

The final payload will be:
$user: ' UNION SELECT 0 --
while $pass can be anything (just don't make it and it's md5 start with numeric value).


And this will make the final query be:

SELECT something FROM users WHERE user='' UNION SELECT 0 -- ' AND pass='abc'

Payload URL: http://tertiary.pwnable.hk:50011?user=' UNION SELECT 0 -- &pass=anything

tags: CTF, HKCert20CTF