为方便您的阅读,可点击下方蓝色字体,进行跳转↓↓↓
- 01 漏洞描述
- 02 审计要点
- 03 漏洞特征
- 04 漏洞案例
- 05 修复方案
01 漏洞描述
当应用程序将用户输入的内容,拼接到SQL语句中,一起提交给数据库执行时,就会产生SQL注入威胁。攻击者通过控制部分SQL语句,可以查询数据库中任何需要的数据,利用数据库的一些特性,甚至可以直接获取数据库服务器的系统权限。
简单来说就是用户输入的内容拼接到SQL语句中,当当前数据库权限为低权限时可以进行查数据,如果时高权限就可以根据数据库特点写文件、执行命令获取数据库服务器权限等。
02 审计要点
SQL注入漏洞发生的根本原因是"用户可控的"、”未经净化“的数据直接拼接至SQL语句中进行执行。“用户可控数据”可能来源于http请求、数据库、Http Header或cookie等。
当判断代码中是否存在SQL注入漏洞时,可从以下4点进行判断:
1、参数是否用户可控?如参数的来源是来自于用户输入的http请求,某功能点为检索功能,检索的关键字需要用户自行输入等。
2、是否使用了预编译?预编译是指在将数据传入SQL语句前明确指定传输数据的类型,以执行必要的转换。
在Java中预编译的调用方式为prepareStatement。在mybatis框架中,使用#{}进行预编译,在ibatis框架中使用#param#进行预编译。
3、是否存在SQL语句拼接?尤其注意某些特殊的查询难免用到SQL语句拼接,遇到这种情况,就需要检查拼接是否有可能导致注入。
4、是否存在全局参数过滤器?检查过滤器的配置,是否所有的SQL查询请求都经过过滤器处理,过滤器的过滤规则是否符合安全要求?
03 漏洞特征
SQL注入产生的根本原因就是将“未经净化”的数据“拼接”进入SQL语句中,然后提交进入数据库获得执行结果。
若参数可控,那么就可确定漏洞的存在,若参数不可控,那么拼接参数的SQL语句编写方式也会存在风险,属于不规范的编码,可进行风险提示。
Java
如下代码是根据用户名查询用户收支情况的一条数据库查询语句,存在SQL注入安全风险,其中user_name参数来自未经任何处理的HTTP请求:
String query = "SELECT account_balance FROM user_data WHERE user_name = ‘"
+ request.getParameter("customerName")+"’";
try {
Statement statement = connection.createStatement( … );
ResultSet results = statement.executeQuery( query );
}
攻击者通过控制http请求中的customerName参数值来对Web服务器进行SQL注入攻击。
Java(jdbc)
HttpServletRequest request, HttpServletResponse response) {
JdbcConnection conn = new JdbcConnection();
final String sql = "select * from product where pname like '%"
+ request.getParameter("pname") + "%'";
conn.execqueryResultSet(sql);
Java(ibatis)
<select id="unsafe" resultMap="myResultMap">
select * from table where name like '%$value$%'
</select>
UnSafeBean b = (UnSafeBean)sqlMap.queryForObject("value", request.getParameter("name"));
PHP
$sql = "select * from product where pname like '%"
.$_REQUEST["pname"] . "%'";
mysqli_query($link,$sql);
04 漏洞案例
在代码中搜索“select”或“from”或者“where”等字符,搜索出所有的与数据库操作相关的代码,查看是否存在拼接参数的情况。
搜索“from",分析SQL语句,对于拼凑SQL,疑似SQL注入的地方提高警惕。
查找相应类的相应方法调用,确定传入的id参数未经转义或任何过滤处理,可确定此处存在SQL注入。搭建环境,爆破用户名成功验证SQL注入漏洞真实存在,如下图所示:
05 修复方案
SQL注入产生的根本原因就是将“未经净化”的数据“拼接”进入SQL语句中,然后提交进入数据库获得执行结果。修复可以从以下几个方面去考虑:
1、对用户输入的特殊字符进行严格过滤,如’、”、<、>、/、*、;、+、-、&、|、(、)、and、or、select、union。
2、使用参数化查询(PreparedStatement),避免将未经过滤的输入直接拼接到SQL查询语句中。
3、Web应用中用于连接数据库的用户与数据库的系统管理员用户的权限有严格的区分(如不能执行drop等),并设置Web应用中用于连接数据库的用户不允许操作其他数据库。
4、设置Web应用中用于连接数据库的用户对Web目录不允许有写权限。