WEB攻防篇(二):PHP & 常见函数 & 伪协议
函数
md5()
用于计算字符串的 MD5 散列。
1 |
|
绕过:
0e绕过:PHP会将每一个以0e开头的哈希值解释为0,那么只要传入的不同字符串经过哈希以后是以0e开头的,那么PHP会认为它们相同。
s878926199a => 0e545993274517709034328855841020
s155964671a => 0e342768416822451524974117254469数组绕过:MD5不能直接对数组进行加密,它会返回NULL。
要满足
$a != $b && md5($a) == md5($b)
=> 传入 a[]=1&b[]=2 即可绕过
==与===
==
运算符只比较变量的值,不考虑它们的类型。===
运算符不仅比较变量的值,还比较它们的类型。
‘10’ == 10 为 true,因为字符串 “10” 会自动转换为整型。
‘10’ === 10 为 false,因为字符串 “10” 和整型 10 的类型不同。
intval()
用于获取变量的整数值。
通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。
1 | int intval ( mixed $var [, int $base = 10 ] ) |
绕过:
- 使用进制绕过。
- 使用小数点绕过。
- 使用科学计数法绕过。
strpos()
用于查找字符串在另一字符串中第一次出现的位置(区分大小写)。
1 | strpos (string, find, start) |
in_array()
用于搜索数组中是否存在指定的值。
1 | bool in_array (mixed $needle , array $haystack [, bool $strict = FALSE ] ) |
绕过:
- 第三个参数如果不指定为true则不判断类型,相当于==。
array_search()
用于在数组中搜索某个值,并返回对应的键名。如果找不到该值,则返回 false。
1 | array_search(mixed $needle, array $haystack, bool $strict = false): int|string|false |
绕过:
- “ABC” == 0 成立
- “ABC” == true 成立。
preg_match()
用于执行一个正则表达式匹配。
1 | int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] ) |
绕过:
a[]='flag.php'
数组写法绕过。- 不带/m的正则表达式可以用换行绕过。
str_replace()
用于替换字符串中的一些字符(区分大小写)。
1 | str_replace (find, replace, string, count) |
绕过:
- 双写绕过。如seselectlect将select替换为空后剩余字符串还是select。
魔术方法
__call()
用于处理对未定义或不可访问的方法的调用。也就是说,当你在对象上调用一个不存在或不可见的方法时,__call() 会被自动调用。
1 |
|
__destruct()
在对象生命周期结束时自动调用,通常用于清理资源。它可以在对象超出作用域、脚本执行结束或显式调用 unset() 时触发。
__invoke()
当尝试以类似函数调用的方式调用对象时,PHP会自动调用对象的__invoke()方法。
1 | // 有参数 |
__get()
用于获取类中不可访问或不存在的属性。当你尝试访问一个未定义或不可见的属性时,PHP 会自动调用 __get() 方法。
1 |
|
__toString()
尝试将一个对象转换为字符串时,PHP 会自动调用这个方法。
1 |
|
伪协议
file://
- 作用:用于访问文件(绝对路径、相对路径、网络路径)。
- 示例:
http://www.xx.com?file=file:///etc/passswd
php://
- 作用:访问输入输出流。
php://filter
- 作用:读取源代码并进行base64编码输出。
- 示例:
http://www.xx.com?file=php://filter/read=convert.base64-encode/resource=[文件名]
php://input
作用:执行POST数据中的php代码。
示例:
http://www.xx.com?cmd=php://input
POST数据:
<?php phpinfo()?>
注意:
enctype="multipart/form-data"
的时候php://input
是无效的。
data://
- 作用:自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。一般需要用到base64编码传输。
- 示例:
http://www.xx.com?file=data://text/plain;base64,aGVsbG9jdGY=
aGVsbG9jdGY=的base64解码为”helloctf”
CTF题相关技巧
绕过空格
${IFS}
,例题:https://www.nssctf.cn/problem/4251
2
3
4
5
6$ip=$_GET['url'];
if(preg_match("/ /", $ip)){ // 判断有没有空格
die('nonono');
}
$a = shell_exec($ip);
echo $a;构造:
?url=ls${IFS}/
$IFS$1
,例题:https://www.nssctf.cn/problem/1096${IFS}
,$IFS
,$IFS$1
的区别:首先$IFS在linux下表示分隔符,只有cat$IFSa.txt的时候,bash解释器会把整个IFSa当做变量名,所以导致没有办法运行,然而如果加一个{}就固定了变量名,同理在后面加个$可以起到截断的作用,而$1指的是当前系统shell进程的第1个参数的持有者,就是一个空字符串,因此$1相当于没有加东西,等于做了一个前后隔离,同理$1~$9都可实现相同的效果。
绕过请求中的 .
例题:第十五届极客大挑战 rce_me
其中一段代码如下:
1 | if ( |
这里如果直接传入 __2024.geekchallenge.ctf
的话,PHP在处理的时候会转换成 __2024_geekchallenge_ctf
,这样的话 $_POST["__2024.geekchallenge.ctf"]
读出来就是null,PHP的官方手册也对其进行了解释:
绕过:
当PHP版本小于8时,如果参数中出现中括号
[
,中括号会被转换成下划线_
,但是会出现转换错误,导致后面的非法字符不会转换成下划线_
。
因此构造参数 _[2024.geekchallenge.ctf
即可满足要求。