2023/08/12:php的一些记录

来源
https://cloud.tencent.com/developer/article/1055505?from=15425
https://cloud.tencent.com/developer/article/2127498

要求变量原值不同但md5或sha1相同的情况下

sha1()md5()都用于计算字符串的散列值,但是两者都无法处理数组,不会抛出异常而是直接返回NULL

1.0e开头的全部相等(==判断)

240610708 和 QNKCDZO md5值类型相似,但并不相同,在”==”相等操作符的运算下,结果返回了true。Md5和sha1一样

2.利用数组绕过(===判断)

Md5和sha1对一个数组进行加密将返回NULL;而NULL===NULL返回true,所以可绕过判断

strcmp()函数

当输入的两个值为不是字符串时就会产生不预期的返回值,比如数组(php版本5.3.3至5.5中,不包含5.5)
ereg()strpos处理数组也会异常,返回NULL

parse_str()函数

解析字符串并注册成变量,在注册变量之前不会验证当前变量是否存在,所以直接覆盖掉已有变量
当parse_str()函数的参数值可以被用户控制时,则存在变量覆盖漏洞

intval()函数

用于获取变量的整数值
在转换时,函数会从字符串起始处进行转换直到遇到一个非数字的字符
即使出现无法转换的字符串也不会报错而是返回0

in_array()函数

用来判断一个值是否在某一个数组列表里面。其缺陷在于存在自动类型转换,当输入数字1后再紧跟其他字符串能够Bypass检测数组的功能

json_decode()函数

用于对json格式数据进行json解码操作,对于一个json类型的字符串,会解密成一个数组,其存在一个0=="efeaf"的Bypass

preg_match()函数

执行一个正则表达式匹配
int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )
1.$pattern:要搜索的模式,字符串形式
2.$subject:要搜索检测的目标字符串
3.matches:如果提供了参数matches,它将被填充为搜索结果matches[0]将包含完整模式匹配到的文本
4.$flags:可设置标记值
5.$offset:可选参数offset用于指定从目标字符串的某个未知开始搜索(单位是字节)
/i修饰符,大小写不敏感
/m修饰符,多行匹配,当出现换行符%0a的时候,会被当做两行处理,此时只可以匹配第1行,后面的行就会被忽略

preg_replace()函数

执行一个正则表达式的搜索和替换
preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) : mixed
1.$pattern:要搜索的模式,可以是字符串或一个字符串数组
2.$replacement:用于替换的字符串或字符串数组
3.$subject:要搜索替换的目标字符串或字符串数组
4.$limit:可选,对于每个模式用于每个 subject 字符串的最大可替换次数。默认是-1(无限制)
5.$count:可选,为替换执行的次数
/e修饰符
使preg_replace()将replacement参数当作 PHP 代码

register_globals全局变量覆盖

php.ini中有一项为register_globals,即注册全局变量
register_globals=On时,传递过来的值会被直接的注册为全局变量直接使用
register_globals=Off时,我们需要到特定的数组里去得到它
(PHP 5.3.0 起废弃并将自 PHP 5.4.0 起移除)
当register_globals=On,变量未被初始化且能够用户所控制时,就会存在变量覆盖漏洞

extract()变量覆盖

从数组中将变量导入到当前的符号表
使用数组键名作为变量名,使用数组键值作为变量值
针对数组中的每个元素,将在当前符号表中创建对应的一个变量
int extract ( array $var_array [, int $extract_type [, string $prefix ]] )
第二个参数指定函数将变量导入符号表时的行为:
1.当值为EXTR_OVERWRITE时,在将变量导入符号表的过程中,如果变量名发生冲突,则覆盖所有变量
2.值为EXTR_SKIP则表示跳过不覆盖
3.若第二个参数未指定,则在默认情况下使用EXTR_OVERWRITE
当extract()函数从用户可以控制的数组中导出变量且第二个参数未设置或设置为EXTR_OVERWRITE时,就存在变量覆盖漏洞

import_request_variables()变量覆盖

将GET、POST、Cookies中的变量导入到全局(4.1.0 <= PHP < 5.4.0)
bool import_request_variables (string $types [, string $prefix])
1.$type代表要注册的变量,G代表GET,P代表POST,C代表COOKIE
2.第二个参数为要注册变量的前缀

$$导致的变量覆盖

1.\$var是一个正常变量,名称为:var,存储任何值,如:string,integer,float等
2.\var是一个引用变量,用于存储斜杠

strstr()函数

大小写敏感

mt_rand()函数

随机数生成工具
问题在于每个php cgi进程期间,只有第一次调用mt_rand()会自动播种,接下来都会根据这个第一次播种的种子来生成随机数
所以可以通过逆向得到随机种子,然后获取后面其他随机数,如路径之类的信息就有了
使用php_mt_seed工具

当有两个is_numeric判断并用and连接时,and后面的is_numeric可以绕过

1
2
3
4
5
6
7
8
$a=$_GET['a'];
$b=$_GET['b'];
$c=is_numeric($a) and is_numeric($b);
var_dump(is_numeric($a));
var_dump(is_numeric($b));
var_dump($c); //$b可以不是数字,同样返回true
$test=false and true;
var_dump($test); //返回true

NULL,0,”0″,array()使用==和false比较时,都是会返回true的

eregi匹配

ereg()有区分大小写,eregi()与大小写无关
使用指定的模式搜索一个字符串中指定的字符串,如果匹配成功则返回true,否则返回false

1.数组绕过

ereg是处理字符串,传入数组之后,ereg是返回NULL

2.%00截断绕过

读到%00截止

接收参数$a得存在,并且$a==0可用.绕过(非数字都可绕过)

如:

1
2
3
4
5
6
7
8
<?php
$a=$_GET['a'];
if ($a==0) {
echo "1";
}
if ($a) {
echo "must";
}

is_numeric绕过

用于检测变量是否为数字或数字字符串,可被十六进制的值进行绕过
空格、\t、\n、\r、\v、\f、+、-能够出现在参数开头,“点”能够在参数任何位置,E、e只能出现在参数中间。

php5,3,29,这里可以直接用%0b绕过\s(空白字符)的匹配

既是0又是1的情况

$a==1&$test[$a]=t时;
php精度(16以上)var_dump(9999999999999999999==1);//true
科学计数法 .1e1 echo $b[‘.1e1’]//输出t
.是字符串所以在数组里面变成0,但在is_numeric中有点则正常输出为数字

伪协议

反序列化

当switch没有break时可以继续往下执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
if (isset ( $_GET ['which'] )) {
$which = $_GET ['which'];
switch ($which) {
case 0 :
case 1 :
case 2 :
echo $which . '.php';
break;
default :
echo "1";
break;
}
}

$which进入循环时没有break则按顺序继续往下执行

PHP-RCE:滥用对象创建

https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/php-tricks-esp/php-rce-abusing-object-creation-new-usd_get-a-usd_get-b
某天晚上土豆提到了
http://39.108.86.101:10001/
这个需要内置类