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 | 数据库中导入数据的关键字 |
1.3Sql注入漏洞危害1 、 攻击者可以做到 - 业务运营的所有数据被攻击
- 对当前数据库用户拥有的所有表数据进行增、删、改、查等操作
- 若当前数据库用户拥有file_priv权限,攻击者可通过植入木马的方式进一步控制DB所在服务器
- 若当前数据库用户为高权限用户,攻击者甚至可以直接执行服务器命令从而通过该漏洞直接威胁整个内网系统
2、可能对业务造成的影响 ① 用户信息被篡改 ② 攻击者偷取代码和用户数据恶意获取 线上代码被非法篡改,并造成为恶意攻击者输送流量或其他利益的影响 1.4Sql注入漏洞代码示例Java 代码动态构建 SQLStatement stmt = null;
ResultSet rs = null;
try{
String userName = ctx.getAuthenticatedUserName();
String sqlString = "SELECT * FROM t_item WHERE owner='" + userName + "' AND itemName='" + request.getParameter("itemName") + "'";
stmt = connection.createStatement();
rs = stmt.executeQuery(sqlString);
}
catch (SQLException se){
}
这里将查询字符串常量与用户输入进行拼接来动态构建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();
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();
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集合中,再通过某处调用成功将数据显示在前台。
声明:文章版权归原作者所有 部分文章转自互联网 如有侵权请联系
[邮箱地址] 删除
|