网络安全必学SQL注入

这篇具有很好参考价值的文章主要介绍了网络安全必学SQL注入。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.1 .Sql注入攻击原理

SQL注入漏洞可以说是在企业运营中会遇到的最具破坏性的漏洞之一,它也是目前被利用得最多的漏洞。要学会如何防御SQL注入,首先我们要学习它的原理。

针对SQL注入的攻击行为可描述为通过在用户可控参数中注入SQL语法,破坏原有SQL结构,达到编写程序时意料之外结果的攻击行为。其成因可以归结为以下两个原因叠加造成的:

程序编写者在处理应用程序和数据库交互时,使用字符串拼接的方式构造SQL语句。未对用户可控参数进行足够的过滤便将参数内容拼接进入到SQL语句中。
注入攻击的本质,是把用户输入的数据当做代码执行。这里有两个关键条件:用户能够控制输入。
原本程序要执行的代码,拼接了用户输入的数据。

1.2 .Sql审计方法

手动找的话,可以直接找到sqlmapper.xml文件或者直接搜索 select、update、delete、insert “String sql=”等关键词,定位SQL xml配置文件。

如果 sql 语句中有出现 $ 进行参数拼接,则存在SQL注入风险。

当找到某个变量关键词有 SQL 注入风险时,可以再根据调用链找到该存在注入风险的业务逻辑代码,查看参数来源是否安全、是否有配置SQL危险参数过滤的过滤器,最终确认是否存在SQL注入。以下给出可能造成sql注入攻击的关键字,审计时可根据实际情况进项查找

常见SQL语句关键词

关键词 解释
ResultSet 数据库结果集的数据表,通常通过执行查询数据库的语句生成。
executeQuery 执行查询
select 数据库中的查询关键字
insert 数据库中的插入关键字
update 数据库中的修改关键字
delete 数据库中的删除关键字
where 数据库中的条件关键字
union 数据库中的联合查询关键字
drop 数据库中的删除数据库关键字
create 数据库中的创建数据库关键字
count 数据库中的返回匹配行数关键字
java.sql.Connection 与特定数据库的连接类
Statement 是 Java 执行数据库操作的重要接口
jdbcTemplate 最基本的Spring JDBC模板
PreparedStatement 预编译的 SQL 语句的对象
queryForInt 数据库查询方法关键字
queryForObject 数据库查询方法关键字
queryForMap 数据库查询方法关键字
getConnection 获取sql连接
outfile 数据库中把表数据导出关键字
load_file 数据库中导入数据的关键字

【一一帮助安全学习,所有资源一一】
①网络安全学习路线
②20份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥网络安全必备书籍
⑦100个漏洞实战案例
⑧安全大厂内部教程

1.3Sql注入漏洞危害

1 、 攻击者可以做到

  • 业务运营的所有数据被攻击
  • 对当前数据库用户拥有的所有表数据进行增、删、改、查等操作
  • 若当前数据库用户拥有file_priv权限,攻击者可通过植入木马的方式进一步控制DB所在服务器
  • 若当前数据库用户为高权限用户,攻击者甚至可以直接执行服务器命令从而通过该漏洞直接威胁整个内网系统

2、可能对业务造成的影响

① 用户信息被篡改

② 攻击者偷取代码和用户数据恶意获取

线上代码被非法篡改,并造成为恶意攻击者输送流量或其他利益的影响

1.4 Sql注入漏洞代码示例

Java 代码动态构建 SQL

Statement stmt = null;

ResultSet rs = null;

try{

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String sqlString = "SELECT * FROM t_item WHERE owner='" + userName + "' AND itemName='" + request.getParameter("itemName") + "'";

stmt = connection.createStatement();

rs = stmt.executeQuery(sqlString);

// ... result set handling

}

catch (SQLException se){

// ... logging and error handling

}

这里将查询字符串常量与用户输入进行拼接来动态构建SQL查询命令。仅当itemName不包含单引号时,这条查询语句的行为才会是正确的。如果一个攻击者以用户名wiley发起一个请求,并使用以下条目名称参数进行查询:

name' OR 'a' = 'a

那么这个查询将变成:

SELECT * FROM t_item WHERE owner = 'wiley' AND itemname = 'name' OR 'a'='a';

此处,额外的OR ‘a’='a’条件导致整个WHERE子句的值总为真。那么,这个查询便等价于如下非常简单的查询:

SELECT * FROM t_item

这个简化的查询使得攻击者能够绕过原有的条件限制:这个查询会返回items表中所有储存的条目,而不管它们的所有者是谁,而原本应该只返回属于当前已认证用户的条目。

在存储过程中动态构建SQL

Java代码:

CallableStatement = null

ResultSet results = null;

try

{

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

cs = connection.prepareCall("{call sp_queryItem(?,?)}");

cs.setString(1, userName);

cs.setString(2, itemName);

results = cs.executeQuery();

// ... result set handling

}

catch (SQLException se)

{

// ... logging and error handling

}

SQL Server存储过程:

CREATE PROCEDURE sp_queryItem

@userName varchar(50),

@itemName varchar(50)

AS

BEGIN

DECLARE @sql nvarchar(500);

SET @sql = 'SELECT * FROM t_item

WHERE owner = ''' + @userName + '''

AND itemName = ''' + @itemName + '''';

EXEC(@sql);

END

GO

在存储过程中,通过拼接参数值来构建查询字符串,和在应用程序代码中拼接参数一样,同样是有SQL注入风险的。

Hibernate 动态构建 SQL/HQL

原生SQL查询:

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

Query sqlQuery = session.createSQLQuery("select * from t_item where owner = '" + userName + "' and itemName = '" + itemName + "'");

List<Item> rs = (List<Item>) sqlQuery.list();

HQL查询:

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

Query hqlQuery = session.createQuery("from Item as item where item.owner = '" + userName + "' and item.itemName = '" + itemName + "'");

List<Item> hrs = (List<Item>) hqlQuery.list();

即使是使用Hibernate,如果在动态构建SQL/HQL查询时包含了不可信输入,同样也会面临SQL/HQL注入的问题。

HQL代码中,session.createQuery使用HQL语句将查询到的数据存到到list集合中,需要时在拿出来使用。而参数中itemName是通过request.getParameter直接获取。攻击者若在此处写入恶意语句,程序将恶意语句查询出来的数据存放在list集合中,再通过某处调用成功将数据显示在前台。

Mybatis注入分析

Mybatis框架下易产生SQL注入漏洞的情况主要分为以下三种:

1)模糊查询like

例如对人员姓名检索进行模糊查询,如果考虑安全编码规范问题,其对应的SQL语句如下:

Select * from user where name like '%#{name}%'

但由于这样写程序会报错,研发人员将SQL查询语句修改如下:

Select * from user where name like '%${name}%'

在这种情况下我们发现程序不再报错,但是此时产生了SQL语句拼接问题,如果java代码层面没有对用户输入的内容做处理势必会产生SQL注入漏洞。

2)in之后的参数

例如对人员姓名进行同条件多值检索的时候,如当用户输入001,002,003…时,如果考虑安全编码规范问题,其对应的SQL语句如下:

Select * from name where id in (#{id})

但由于这样写程序会报错,研发人员将SQL查询语句修改如下:

Select * from name where id in (${id})

修改SQL语句之后,程序停止报错,但是却引入了SQL语句拼接的问题,如果没有对用户输入的内容做过滤,势必会产生SQL注入漏洞。

3)order by之后(重点和区分点)

当根据姓名、id序号等信息用户进行排序的时候,如果考虑安全编码规范问题,其对应的SQL语句如下:

Select * from user where name = 'qihoo' order by #{id} desc

但由于发布时间id不是用户输入的参数,无法使用预编译。研发人员将SQL查询语句修改如下:

Select * from user where name = 'qihoo' order by ${id} desc

修改之后,程序未通过预编译,但是产生了SQL语句拼接问题,极有可能引发SQL注入漏洞。

1.5 .实战案例-OFCMS SQL注入漏洞分析

本文中使用ofcms进行SQL注入漏洞讲解,此CMS算是对新手学习代码审计比较友好的CMS。
网络安全必学SQL注入

上述为安装成功页面,如何安装CMS本章不在赘述。

后台页面:http://localhost:8080/ofcms-admin/admin/index.html

网络安全必学SQL注入

漏洞点:

ofcms-admin/src/main/java/com/ofsoft/cms/admin/controller/system/SystemGeneratrController.java

create方法

| 

/**

* 创建表

*/

public void create() {

try {

String sql = getPara("sql");

Db.update(sql);

rendSuccessJson();

} catch (Exception e) {

e.printStackTrace();

rendFailedJson(ErrorCode.get("9999"), e.getMessage());

}

}

上述代码中使用getpara获取sql的参数值,并update,跟进一下getpara和update方法。

跳转至 jfinal-3.2.jar/com/jfinal/core/controller.class

public String getPara(String name) {

return this.request.getParameter(name);

}

上述代码无特殊用意,就是获取参数值,继续跟进 Db.update 方法。

跳转至 jfinal-3.2.jar/com/jfinal/plugin/activerecord/Db.class

public static int update(String sql) {

return MAIN.update(sql);

}

发现调用 MAIN.update , 继续跟进。

跳转至 jfinal-3.2.jar/com/jfinal/plugin/activerecord/DbPro.class

public int update(String sql) {

return this.update(sql, DbKit.NULL_PARA_ARRAY);

}

继续跟进到最后,发现华点。

public int update(String sql, Object... paras) {

Connection conn = null;

int var4;

try {

conn = this.config.getConnection();//连接

var4 = this.update(this.config, conn, sql, paras);//调用update更新

} catch (Exception var8) {

throw new ActiveRecordException(var8);

} finally {

this.config.close(conn);

}

return var4;

}

重点:Object…

Object是所有类的基类,而 Object… 是不确定方法参数情况下的一种多态表现形式(可以传递多个参数)。

再继续跟进 update ,同文件代码

int update(Config config, Connection conn, String sql, Object... paras) throws SQLException {

PreparedStatement pst = conn.prepareStatement(sql);

config.dialect.fillStatement(pst, paras);

int result = pst.executeUpdate();

DbKit.close(pst);

return result;

}

上述代码执行SQL语句,并返回结果。

至此,整个功能流程结束,在我们跟进的过程中,代码中无任何过滤语句,获取参数值,调用update方法更新,更新成功后返回结果。

漏洞验证

网络安全必学SQL注入

漏洞点打上断点,网页中输入poc进行验证

update of_cms_topic set topic_url=updatexml(1,concat(0x7e,(user())),0) where topic_id = 1

网络安全必学SQL注入
网络安全必学SQL注入
网络安全必学SQL注入
网络安全必学SQL注入

根据如上截图可看出我们传入的SQL语句是被完整的接收,并未做任何过滤直接带入数据库执行,所以此处直接写入漏洞代码爆出当前数据库账户为 root。

上述为sqlmap工具跑出来的注入点。

1.6 漏洞修复方法

添加全局过滤器,过滤特殊字符

网络安全必学SQL注入

SQLFilter.java中:
网络安全必学SQL注入

PreparedStatement 参数化

如果使用参数化查询,则在SQL语句中使用占位符表示需在运行时确定的参数值。参数化查询使得SQL查询的语义逻辑被预先定义,而实际的查询参数值则等到程序运行时再确定。参数化查询使得数据库能够区分SQL语句中语义逻辑和数据参数,以确保用户输入无法改变预期的SQL查询语义逻辑。

在Java中,可以使用java.sql.PreparedStatement来对数据库发起参数化查询。在这个正确示例中,如果一个攻击者将itemName输入为name’ OR ‘a’ = ‘a,这个参数化查询将免受攻击,而是会查找一个itemName匹配name’ OR ‘a’ = 'a这个字符串的条目。

PreparedStatement stmt = null

ResultSet rs = null

try

{

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

// ...Ensure that the length of userName and itemName is legitimate

// ...

String sqlString = "SELECT * FROM t_item WHERE owner=? AND itemName=?";

stmt = connection.prepareStatement(sqlString);

stmt.setString(1, userName);

stmt.setString(2, itemName);

rs = stmt.executeQuery();

// ... result set handling

}

catch (SQLException se)

{

// ... logging and error handling

}

存储过程参数化

这个存储过程使用参数化查询,而未包含不安全的动态SQL构建。数据库编译此存储过程时,会生成一个SELECT查询的执行计划,只允许原始的SQL语义被执行。任何参数值,即使是被注入的SQL语句也不会被执行,因为它们不是执行计划的一部分。

CallableStatement = null

ResultSet results = null;

try

{

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

// ... Ensure that the length of userName and itemName is legitimate

// ...

cs = connection.prepareCall("{call sp_queryItem(?,?)}");

cs.setString(1, userName);

cs.setString(2, itemName);

results = cs.executeQuery();

// ... result set handling

}

catch (SQLException se)

{

// ... logging and error handling

}

Hibernate 参数化查询

Hibernate支持SQL/HQL参数化查询。为了防止SQL注入以及改善性能,以上这些示例使用了参数化绑定 的方式来设置查询参数。

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

Query hqlQuery = session.createQuery("from Item as item where item.owner = ? and item.itemName = ?");

hqlQuery.setString(1, userName);

hqlQuery.setString(2, itemName);

List<Item> rs = (List<Item>) hqlQuery.list();

HQL基于名称的参数化查询

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

Query hqlQuery = session.createQuery("from Item as item where item.owner = :owner and item.itemName = :itemName");

hqlQuery.setString("owner", userName);

hqlQuery.setString("itemName", itemName);

List<Item> rs = (List<Item>) hqlQuery.list();

原生参数化查询

String userName = ctx.getAuthenticatedUserName(); //this is a constant

String itemName = request.getParameter("itemName");

Query sqlQuery = session.createSQLQuery("select * from t_item where owner = ? and itemName = ?");

sqlQuery.setString(0, owner);

sqlQuery.setString(1, itemName);

List<Item> rs = (List<Item>) sqlQuery.list();

MyBatis框架的修复方案

尽量使用#描述参数,如果一定要使用$,则需要自己过滤用户输入

模糊查询like SQL注入修复建议

按照新闻标题对新闻进行模糊查询,可将SQL查询语句设计如下:

select * from news where name like concat(‘%’,#{name }, ‘%’)

采用预编译机制,避免了SQL语句拼接的问题,从根源上防止了SQL注入漏洞的产生。

in之后的参数SQL注入修复建议

在对新闻进行同条件多值查询的时候,可使用Mybatis自带循环指令解决SQL语句动态拼接的问题:

select * from news where id in<foreach collection="ids" item="item" open="("separator="," close=")">#{item} </foreach>

order by SQL注入修复建议

【一一帮助安全学习一一】
①网络安全学习路线
②20份渗透测试电子书
③安全攻防357页笔记
④50份安全攻防面试指南
⑤安全红队渗透工具包
⑥网络安全必备书籍
⑦100个漏洞实战案例
⑧安全大厂内部教程

在Java层面做映射预编译机制只能处理查询参数,其他地方还需要研发人员根据具体情况来解决。如前面提到的排序情景:

Select * from news where title =‘淘宝’ order by #{time} asc,

这里time不是查询参数,无法使用预编译机制,只能这样拼接:

Select * from news where title =‘淘宝’ order by ${time} asc

针对这种情况研发人员可以在java层面做映射来进行解决。如当存在发布时间time和点击量click两种排序选择时,我们可以限制用户只能输入1和2。

当用户输入1时,我们在代码层面将其映射为time,当用户输入2时,将其映射为click。而当用户输入1和2之外的其他内容时,我们可以将其转换为默认排序选择time(或者click)。文章来源地址https://www.toymoban.com/news/detail-437893.html

到了这里,关于网络安全必学SQL注入的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【网络安全】初探SQL注入漏洞

    要想玩SQL注入,一个简单的数据交互页面是需要的,故我们用PHP做一个简易网页,有登录、注册和首页三块内容。 登录需要输入账号密码,等待提交后进入系统; 注册需要输入名字,密码,手机号,照片,等待提交后进入系统; 首页需要利用PHP和数据库联动后的查询语句,

    2024年02月16日
    浏览(43)
  • 【网络安全】SQL注入漏洞的修复建议

    SQL注入是Web应用程序常见的安全漏洞之一,攻击者通过恶意构造的SQL查询语句,成功在应用程序的数据库中执行任意操作,导致数据泄露、篡改或其他安全问题。 本篇技术博客将详细介绍SQL注入漏洞的修复建议,包括过滤危险字符和使用预编译语句,通过具体的代码案例帮助

    2024年02月06日
    浏览(52)
  • 网络安全:Kali Linux 进行SQL注入与XSS漏洞利用

    目录 一、实验 1.环境 2.Kali Linux 进行SQL注入 3.Kali Linux 进行XSS漏洞利用 二、问题 1.XSS分类 2.如何修改beef-xss的密码 3.beef-xss 服务如何管理 4.运行beef报错 5.beef 命令的颜色有哪些区别 6.owasp-top-10 有哪些变化 (1)主机 表1  主机 系统 版本 IP 备注 Kali Linux 2022.4 192.168.204.154(动态

    2024年04月26日
    浏览(40)
  • 【网络安全---sql注入(2)】如何通过SQL注入getshell?如何通过SQL注入读取文件或者数据库数据?一篇文章告诉你过程和原理。

    分享一个非常详细的网络安全笔记,是我学习网安过程中用心写的,可以点开以下链接获取: 超详细的网络安全笔记 本篇博客主要是通过piakchu靶场来讲解如何通过SQL注入漏洞来写入文件,读取文件。通过SQL输入来注入木马来getshell等,讲解了比较详细的过程; 如果想要学习

    2024年02月07日
    浏览(54)
  • web安全漏洞-SQL注入攻击实验

    实验目的 学习sql显注的漏洞判断原理 掌握sqlmap工具的使用 分析SQL注入漏洞的成因 实验工具 sqlmap是用python写的开源的测试框架,支持MySQL,Oracle,PostgreSQL,Microsoft SQL Server,Microsoft Access,IBM DB2,SQLite,Firebird,Sybase,SAP,MAXDB并支持6种SQL注入手段。 实验内容 SQL注入(SQL I

    2024年02月06日
    浏览(56)
  • 6.1 安全漏洞与网络攻击

    数据参考:CISP官方  目录 安全漏洞及产生原因 信息收集与分析 网络攻击实施 后门设置与痕迹清除 什么是安全漏洞 安全漏洞也称脆弱性,是计算机系统存在的缺陷 漏洞的形式 安全漏洞以不同形式存在 漏洞数量逐年递增  漏洞产生的技术原因 内因: 软件复杂性使得漏洞不

    2024年02月13日
    浏览(48)
  • 【网络安全】SQL注入--堆叠注入

    堆叠注入就是可以同时执行多条语句,危害较大,利用此漏洞可以进行删库或者修改数据库信息 查询存在多少字段 使用联合查询获取表名 使用联合查询获取字段名称 使用堆叠注入添加账号密码

    2023年04月09日
    浏览(49)
  • 漏洞攻击中怎么去做最全面覆盖的sql注入漏洞攻击?表信息是如何泄露的?预编译就一定安全?最受欢迎的十款SQL注入工具配置及使用

    漏洞攻击中怎么去做最全面覆盖的sql注入漏洞攻击?表信息是如何泄露的?预编译就一定安全?最受欢迎的十款SQL注入工具配置及使用。 SQL注入是因为后台SQL语句拼接了用户的输入,而且Web应用程序对用户输入数据的合法性没有判断和过滤,前端传入后端的参数是攻击者可控

    2024年01月24日
    浏览(45)
  • 【网络安全】SQL注入--宽字节注入

    宽字节注入,在 SQL 进行防注入的时候,一般会开启 gpc,过滤特殊字符。 一般情况下开启 gpc 是可以防御很多字符串型的注入,但是如果数据库编码不 对,也可以导致 SQL 防注入绕过,达到注入的目的。如果数据库设置宽字节字 符集 gbk 会导致宽字节注入,从而逃逸 gpc 前提

    2023年04月13日
    浏览(60)
  • 【网络安全】SQL注入详解

    SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编写时的疏忽,通过SQL语句,实现无账号登录,甚至篡改数据库。 1:寻找到SQL注入的位置 2:判断服务器类型和后台数据库类型 3:针对不同的服务器和数据库特点进行SQL注入攻击

    2024年02月06日
    浏览(56)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包