sliping beauty -- Zip Slip Attack

URL: http://webhacking.kr:10015arrow-up-right

sliping_beauty-1.png
<?php
session_start();
if (!$_SESSION["uid"]) {
    $_SESSION["uid"] = "guest";
}
if ($_SESSION["uid"] == "admin") {
    include "/flag";
}
if ($_FILES["upload"]) {
    $path = $_FILES["upload"]["tmp_name"];
    $zip = new ZipArchive();
    if ($zip->open($_FILES["upload"]["tmp_name"]) === true) {
        for ($i = 0; $i < $zip->numFiles; $i++) {
            $filename = $zip->getNameIndex($i);
            $filename_ = $filename . rand(10000000, 99999999);
            if (strlen($filename) > 240) {
                exit("file name too long");
            }
            if (preg_match('/[\x00-\x1F\x7F-\xFF]/', $filename)) {
                exit("no hack");
            }
            if (
                copy(
                    "zip://{$_FILES["upload"]["tmp_name"]}#{$filename}",
                    "./upload/{$filename_}"
                )
            ) {
                echo "{$filename_} uploaded.<br>";
            } else {
                echo "{$filename_} upload failed.<br>";
            }
        }
        $zip->close();
    }
}
highlight_file(__FILE__);
?>

My initial thought about zip:// protocol was RCE via LFI, but that hypothesis quickly came to an end.

The filename restriction is be non-ascii characters are disallowed:

sliping_beauty.png

The $filename_ = $filename . rand(10000000, 99999999); made this challenge a bit tricky, while we could update our own session, the random number at the end prevents us from doing that. Luckily we can create sess_<RANDOM_NUMBER> which is a session file meaning we can use that PHPSESSID later to preview the flag.

Essentially create a zip file which contains a file that can traverse path, place the file in /var/lib/php/sessions and the filename will be changed from sess_ to sess_<RANDOM_NUMBER>, make a second request with that PHPSESSID to get flag.

Last updated