PHP黑魔法
古娜拉黑暗之神🪄
PHP基础函数
接着上一篇小bug,把那些也提溜过来继续写🧐
extract()
extract() 函数从数组中将变量导入到当前的符号表。该函数使用数组键名作为变量名,使用数组键值作为变量值。
语法
extract(array,extract_rules,prefix)
参数 | 描述 |
---|---|
array(数组名) | 规定要使用的数组 |
extract_rules(提取规则) | 可省略。extract() 函数将检查每个键名是否为合法的变量名,同时也检查和符号表中已存在的变量名是否冲突。对不合法和冲突的键名的处理将根据此参数决定。 |
prefix(前缀) | 可省略。请注意 prefix 仅在 extract_type 的值是 EXTR_PREFIX_SAME,EXTR_PREFIX_ALL,EXTR_PREFIX_INVALID 或 EXTR_PREFIX_IF_EXISTS 时需要。如果附加了前缀后的结果不是合法的变量名,将不会导入到符号表中。 |
extract_rules可能的值:
- EXTR_OVERWRITE - 默认。如果有冲突,则覆盖已有的变量
- EXTR_SKIP - 如果有冲突,不覆盖已有的变量。
- EXTR_PREFIX_SAME - 如果有冲突,在变量名前加上前缀 prefix。
- EXTR_PREFIX_ALL - 给所有变量名加上前缀 prefix。
- EXTR_PREFIX_INVALID - 仅在不合法或数字变量名前加上前缀 prefix。
- EXTR_IF_EXISTS - 仅在当前符号表中已有同名变量时,覆盖它们的值。其它的都不处理。
- EXTR_PREFIX_IF_EXISTS - 仅在当前符号表中已有同名变量时,建立附加了前缀的变量名,其它的都不处理。
- EXTR_REFS - 将变量作为引用提取。导入的变量仍然引用了数组参数的值。
1 |
|
1 |
|
1 |
|
1 |
|
isset()
isset() 函数用于检测变量是否已设置并且非 NULL。若使用 isset() 测试一个被设置成 NULL 的变量,将返回 FALSE。
语法
bool isset ( mixed $var [, mixed $... ] )
$var为要测试的变量
如果一次传入多个参数,那么 isset() 只有在全部参数都被设置时返回 TRUE,计算过程从左至右,中途遇到没有设置的变量时就会立即停止。
1 |
|
1 |
|
file_get_contents()
file_get_contents() 把整个文件读入一个字符串中。
1 |
|
1 |
|
strcmp()
strcmp()
把两个字符串以二进制方式进行比较,且该函数比较时区分大小写。
语法
strcmp(string1, string2)
返回值
如果返回值小于0,则str1小于str2;
如果返回值大于0,则str1大于str2;
如果返回值等于0,则str1等于str2;
有资料说返回值也不仅是-1和1,也可能是其他数据
1 |
|
还有个函数strcasecmp(),用法与strcmp()类似,只是不区分大小写
ereg/preg_match
ereg()
和preg_match()
是PHP中常用的正则表达式。
紧急补课—正则表达式
在编写处理字符串的程序或者网页的时候,经常会查找符合某些复杂规则的字符串的需要,正则表达式就是用于描述这些规则的语法。
作用: 分割, 匹配, 查找, 替换
例如: 验证邮箱地址格式, 手机号码格式等等
语法
preg_match(mode, string subject, array matches);
ereg(mode,string,subject,array regs);
mode : 正则表达式
subject : 需要验证的字符串
matches/regs : 匹配后得到的结果,以数组的方式存储
返回值
返回值是false或true
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
1 |
|
乱七八糟一堆符号我一个都看不懂我好得很哇
魔法部分
警告:麻瓜请自觉退出🚫
01 strcmp绕过
1 |
|
ps:从ws那里copy来的(x
解题思路
条件是strcmp($_GET['flag'], FLAG) == 0
,就是要**$_GET变量和FLAG**相等,但是我们除了严刑逼供出题人,根本就不知道FLAG是什么。
$_GET[‘flag’]意思是从url获取一个叫flag的GET参数
不要害怕!
当 strcmp() 比较出错时会返回 NULL;而返回 NULL 即为返回 0,我们只需要palyload一个非字符串变量和字符串FLAG比较就会出错并返回0。
欸,相等辣!
最终palyload: ?flag[]=0
02 md5绕过
1 |
|
解题思路
条件是($_GET['s1'])!=$-GET['s2'] && md5($GET[s1])==$_get['s2']
,就是变量s1和s2不能相等但是他们的md5要相等。
因为s2和s2不能相等,所以单纯md5加密得出的密文一定也不完全一样,这时就要利用一些歪门邪道(不是)。
紧急补课—md5
md5一种密码散列函数。MD5算法的原理可简要的叙述为:MD5码以512位分组来处理输入的信息,且每一分组又被划分为16个32位子分组,经过了一系列的处理后,算法的输出由四个32位分组组成,将这四个32位分组级联后将生成一个128位散列值。
补不了我看不懂🥲
001 科学计数法绕过
字符串经过md5加密后,会生成既有数字又有字母的密文,可以利用科学计数法的语法规律反推明文。
了解到md5是不可逆的所以应该不能解码,但是可以根据加密规律找满足需要的明文
0无论乘十的几次方都仍然为零,例如'0e123456'=='0e654321'==0
。所以只需要找到两个经过md5加密后以”0e“开头的字符串充当变量即可。
copy了一些加密后是0e开头的值:
- QNKCDZO
- 240610708
- s878926199a
- s155964671a
- s214587387a
- s214587387a
- 0e215962017
最终playload:?s1=QNKCDZO&s2=240610708
没有成功截图😣
不知道为什么自己运行的时候没成功,页面一片空白什么都没输出。
紧急补课
在php中,**’xey‘** 意为x乘10的y次方。例如:1000 == ‘1e3’。
002 数组绕过
冲浪冲到的
php中的md5函数不能用来加密数组,所以会出现结果NULL。例如md5([1,2]) == md5([3,4]) == NULL
。
最终playload:?s1[]=1&s2[]=2
但是在我的电脑上复现会报错而不是直接null绕过。
03 extract 变量覆盖绕过
1 |
|
解题思路
题目使用extract($_GET)
接受请求,并将其键名和键值转换为变量名和变量值,随后进行if条件的判断。$flag是一个输入的变量,file_get_contents($flag)
打开的一定是空文件,所以$content
一定为空
解题关键在于令$shiyan==$content
使用GET提交参数和值,利用extract($_GET)
进行覆盖,使flag和shiyan的值都为空,从而满足if条件,输出flag。
最终payload:?flag=&shiyan=
04 绕过过滤的空白字符
1 |
|
解题思路
这个代码好长让我来认真看一下🧐
从最后看echo $info
、$info=$flag
,我们知道如果满足前面的条件,flag会被赋值给$info
并输出。
再往上找条件
要不满足条件,即is_palindrome_number($req["number"])
为假。
前面代码有写is_palindrome_number
函数用来判断回文数字。
要满足$value1=$value2
,即intval($req["number"])=intval(strrev($req["number"]))
,$value反转后不能和原来相等。
strrev()函数反转字符串
is_numberic($REAUEST['NUMBER']
需要为假,且$req['number']==strval(intval(eq['number'])
再看看上面
我们要在url传入一个名为number的变量
这段的意思是把我们所有的输入收集到$global_var列表里,此时列表**$global_var=[$number]。再进入下一步循环,将键名赋值给$key,变量的值赋值给$value,即$key=0,$value=$number**。
进入循环内部后,trim()函数去除变量首尾的空白字符或其他字符后需满足条件is_string($value) && $req[$key] = addslashes($value)
,即$value为字符串并给字符串加反斜线。
判断条件如下
综上,要传入一个字符串,字符串不能是数字还必须是整数,不是回文数字还要是回文数字😅。
悖论!烦死了不做了去暴打出题人
没关系我们可以绕过。
intval()
和 is_numeric()
函数在开始判断前,会先跳过所有空白字符,但是is_palindrome_number()
不会,可以利用这个特点,在一个回文数字之前加上一个空白字符,比如\f121
就是%0c121
再用%00绕过is_numeric($_REQUEST['number'])
最终playload:?number=%00%0c121
这个怎么还显示代码捏
05 ereg/preg_match 正则 %00 截断
1 |
|
解题思路
001 %00截断
需要满足条件ereg ("^[a-zA-Z0-9]+$", $_GET['password'])
不为false,即输入的值必须有大小写字母或者数字。
还需满足strlen($_GET['password']) < 8 && $_GET['password'] > 99999999
,即输入值长度小于8且大于99999999。
最后要满足strpos ($_GET['password'], '*-*') !== FALSE
,也就是输入中必须有***-***。但是这条和第一条相悖,不慌,姐已经见过大世面了,姐可以绕过它。
当ereg语句遇到%00的时候就会认为是休止符,不再往后看
可以在字符串中添加%00,在它之后加*-*,骗一下第一个判断条件。
第二个条件可以使用科学计数法,比如1e10。
最终playload:?password=1e10%00*-*
本地复现没成功,我好得很哇我好的很哇😅
报错
本地复现不成功是打不倒我的,我擅长使用百度。
翻译了一下是“调用了未定义函数”。在php5.3以上的版本将不再支持eregi()和ereg()函数,看了一下的我的版本号是7.3。
问题也不是不可避免,只需要改一下格式,把ereg()
改成erge_match()
就行。
但我不会改😣
002 数组绕过
冲浪冲到的另外一种方法
在true和false之外还有一个返回值是null。可以利用这一特点进行绕过。
ereg() 只能处理字符串,遇到数组会返回null,而且null !== false
。同时,strlen()也不能处理数组,也会返回null,null的长度小于8。
因为要输入数组,数组大于整数,所以一定会返回true。
最终playload:?password=[]=1
06 sha()函数比较绕过
1 |
|
解题思路
要满足两个条件:($_GET['name'] !== $_GET['password']
和
sha1($_GET['name']) === sha1($_GET['password'])
。
就是要让输入的两个变量不相等但是sha1加密后相等。
不同的字符串经过sha1加密后一定不同,但是sha1不能加密数组,会报错返回null,如果让两个变量同时返回null就会相等辣。
最终playload:?name[]=1&password[]=2
07 session 验证绕过
1 |
|
题目分析
要满足条件$_GET['password'] == $_SESSION['password']
$_SESSION()存储会话信息
这里session中的password需要我们自己传入,如果不传就是null,同时password也传空,二者就相等啦
最终playload:?password=
08 urldecode 二次编码绕过
1 |
|
题目分析
需要满足两个条件:eregi("hackerDJ",$_GET['id'])
为false;经过urldecode编码后满足$_GET['id'] == "hackerDJ"
也就是说传入值不能是hackerDJ,但是传入值经过urldecode解码后要和hackerDJ相等。
所以传入时要将hackerDJ的url编码再编码一次。
最终playload:?id=%2568%2561%2563%256b%2544%254a
总觉得少了点什么原来是把这个笔记忘记喽
发上来防止自己手贱删掉🦭
把万师傅的原博放这里