基于intval()函数特性的漏洞绕过

前言

最近在做ctfshow的时候碰到intval()函数,虽然题目比较简单,却发现有很多的绕过手段,所以写下这篇博客进行总结

intval()函数

函数用于获取变量的整数值。intval函数有个特性:“直到遇上数字或正负符号才开始做转换,在遇到非数字或字符串结束时(\0)结束转换

  • 语法
int intval ( mixed $var [, int $base = 10 ] )

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

参数 描述
var 要转换成 integer 的数量值。
*base * 转化所使用的进制。

Note:

如果 base 是 0,通过检测 var 的格式来决定使用的进制:

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

函数的作用非常简单,就是获取变量的整数值
实例:

echo intval(42);            // 42
echo intval(4.2);           // 4
echo intval('42');          // 42
echo intval('+42');         // 42
echo intval('1e3');         //1000 

那我们来看看具体题目中的如何绕过

ctf.show 萌新 web1

源代码

(flag in id = 1000)
if(intval($id) > 999){
        # id 大于 999 直接退出并返回错误
        die("id error");
    }else{
        # id 小于 999 拼接sql语句
        $sql = "select * from article where id = $id order by id limit 1 ";
        echo "执行的sql为:$sql
"; # 执行sql 语句 $result = $conn->query($sql); # 判断有没有查询结果 if ($result->num_rows > 0) { # 如果有结果,获取结果对象的值$row while($row = $result->fetch_assoc()) { echo "id: " . $row["id"]. " - title: " . $row["title"]. "

" . $row["content"]. "
"; } } # 关闭数据库连接 $conn->close(); }

分析一下:
我们先上传参数id,如果小于999,进行sql语句拼接查询
那么我们上传的参数id值要小于999,可是题目提示flag在id=1000,完全是矛盾的

方法一

但是我们可以利用intval函数的特性,遇到非数字的直接停止转换,也就是

?id='1000'

这样肯定就小于999,并且又可以查到id=1000
基于intval()函数特性的漏洞绕过_第1张图片

方法二

遇到非数字的直接停止转换,那么我们再结合sql查询语句中数值型查询会自动进行运算操作
构造payload为?id=999+1
不过由于get传参,url编码一下

?id=999%2B1

执行结果同上

方法三

思路同上

?id=125*8

方法三

利用取反绕过,因为~~1000=1000

?id=~~1000

执行结果同上

方法四

我们再看intval()函数的另一个参数$base,由于默认是$base=10,那么我们传入1000的十六进制即可绕过,因为十六进制为0x开头,intval()函数遇到非数字无法将其转换,即为0小于999

?id=0x3E8

基于intval()函数特性的漏洞绕过_第2张图片

方法五

按位左移
payload

?id=125<<3

按位左移操作将二进制数向左移动指定的位数,并在右侧用零填充。在这里,125 的二进制表示是 1111101,将其左移3位后,得到 1111101000。将该二进制数转换为十进制,结果为1000。

你可能感兴趣的:(开发语言,php,web安全)