一、弱类型比较问题
原则:
1.字符串和数字比较,字符串回被转换成数字。
"admin" ==0(true)
admin被转换成数字,由于admin是字符串,转换失败,变成0
int(admin)=0,所以比较结果是ture
2.混合字符串转换成数字,看字符串的第一个
“1admin” == 1 ‘’2admin“ == 2
3.字符串开头以xex开头,x代表数字。会被转换成科学计数法
1e9 => 1x10^9
例题一
GIVE ME THE MONEY!!!
<?php
include "flag.php";
highlight_file(__FILE__);
if (isset($_GET['money'])) {
$money=$_GET['money'];
if(strlen($money)<=4&&$money>time()&&!is_array($money))
{
echo $flag;
}
else echo "Wrong Answer!";
}
else echo "Wrong Answer!";
?>
使用到第三个原则,输入参数为四个字节,含有字母e分隔的字符串,设置数值比较大,就可以大过time()时间戳
例题二,经典的0e绕过MD5
<!DOCTYPE html>
<!--html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
$flag="ctf{YOU_4re_DO1ng_GREAT!}";
if (isset($_GET['a'])&&isset($_GET['b'])) {
$a=$_GET['a'];
$b=$_GET['b'];
if($a==$b)
{
echo "<center>Wrong Answer!</center>";
}
else {
if(md5($a)==md5($b))
{
echo "<center>".$flag."</center>";
}
else echo "<center>Wrong Answer!</center>";
}
}
else echo "NONONO";
?>
</body>
</html-->
题目要求输入的两个参数a、b满足条件1:a!=b同时满足条件条件2:MD5(a)==MD5(b)
MD5加密的特点是,输入的明文不同,输出的结果必然不同
为了同时实现条件1和条件2,这种极端环境下就要用到弱类型比较问题的三个原则
分析MD5加密,它输出的格式是16进制格式的(输出的元素只有0-9和a-f)
在a-f范围内有个特殊的字符e存在 ,所以用到三原则中的第三个原则
等号比较的两边有xex格式的,都当作科学计数法形式来比较
输入两个0e开头不相同的字符串,就可以同时满足两个条件
二、数组类型参数绕过
- 许多函数的参数输入并非数组
- 强行输入数组会返回特殊结果
传入参数为数组类型,函数返回结果为NULL
例题
输入参数为三个不同的数组
md5($v1)==md5($v2) =>null==null
strcmp()函数比较两字符串是否相同,相同返回0,不相同返回1
v3强行输入数组形式,函数返回值为null,加!变为ture
通常出现strcmp()函数都使用数组绕过,还有就是针对字符串操作的函数
三、传参允许是空值,并实现绕过
<?php
include("extract_flag.php");
extract($_GET);
if(isset($aurora))
{
$content=trim(file_get_contents($flag));
if($aurora==$content)
{
echo $flag;
}
else { echo'Oh.no'; } }?>
- extract函数 :讲传入的数组,转换为变量名和变量值的声明,例如输入的get参数是a=1&b=2经过该函数作用了,就多了两个变量$a=1,$b=2。作用类似于n个$_GET(a)语句
- file get contents():传入参数为文件名,函数将传入文件的内容读取出来
- trim():去除字符串首尾的空格
本题是在考验我们是否已经知道了服务器上的某个文件的内容,就是参数aurora值传已知文件的内容,$flag传文件名,就能得到flag
但是问题在于不知道某个文件的内容
解决办法是传空值绕过,传空值不是没传值isset()是可以满足的
aurora&flag
四、%00绕过
php底层的解析器是由c语言实现的,在c语言表达字符串的终结是'\0',在php中是‘%00’
某些函数不过没有对‘%00’进行特殊处理,就存在着可能绕过的空间
ereg就是这样的函数,当输入123%00到ereg函数中,遇到%00就认为字符串终结,不再判断直接符合条件,返回ture
<?php
include("strpos_flag.php");
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
echo 'You password must be alphanumeric';
else if (strpos ($_GET['password'], '--') !== FALSE)
die('Flag: ' . $flag);
else
echo 'Invalid password';}?>
- strpos():实现字符串的字符查找是否存在
- ereg():正则表达式的匹配,
ereg
(
"^[a-zA-Z0-9]+$"
,
$_GET
[
'password'
]只允许包含【】内的字符
获取后端源代码的方法
1.后端源码会以注释形式展示在前端源代码中
- 右键查看前端页面源代码
- 地址栏中后跟/.index.php~,会自动下载页面源码
2.由于电脑或vim编辑器非正常退出,会保留交换文件,后端源码就保存在交换文件中
例题:
题目提示说电脑会自动关机,电脑自动关机说明文本编辑器肯定会非正常退出,就会留下交换文件
在地址栏中后跟/.index.php.swp
就会自动下载交换文件
文件内的内容就包含后端源代码