在本文中,我们将讨论什么是SQL注入攻击。 以及它如何影响任何Web应用程序使用后端数据库。 在这里,我专注于Java Web应用程序。 开放Web应用程序安全项目(OWAP)列出了SQL注入是Web应用程序的主要漏洞攻击。 黑客将Web请求中的SQL代码注入Web应用程序并控制了后端数据库,即使后端数据库未直接连接到Internet也是如此。 我们将看到如何解决和防止Java Web Application中的SQL注入。
为此,我们需要1个工具。 这些工具是完全开源的。 SQL Map – SqlMap是一种开源渗透测试工具,可自动执行检测和利用SQL Injection的过程。 我们可以从这里得到。
SQL注入
SQL注入是通过Web应用程序提取数据库信息的技术。
场景:
我们有一台数据库服务器[MySQL]和Web应用程序服务器[Tomcat]。 考虑数据库服务器未连接到Internet。 但它与应用程序服务器连接。 现在我们将看到使用Web应用程序如何使用sql-injection方法提取信息。
在查看sql注入之前,我们创建了小型Web应用程序。 它包含单个jsp页面,像这样
<form action='userCheck'><input type='text' name='user' value=''/><input type='submit' value='Submit'/></form>
在userCheck中,Servlet接收用户输入字段并连接到数据库服务器,并根据用户输入触发sql查询,并接收ResultSet并将其迭代打印到网页中。
userCheck servlet
protected void processRequest(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {response.setContentType('text/html;charset=UTF-8');PrintWriter out = response.getWriter();try {String user = request.getParameter('user');Connection conn = null;String url = 'jdbc:mysql://192.168.2.128:3306/';String dbName = 'anvayaV2';String driver = 'com.mysql.jdbc.Driver';String userName = 'root';String password = '';try {Class.forName(driver).newInstance();conn = DriverManager.getConnection(url + dbName, userName, password);Statement st = conn.createStatement();String query = 'SELECT * FROM User where userId='' + user + ''';out.println('Query : ' + query);System.out.printf(query);ResultSet res = st.executeQuery(query);out.println('Results');while (res.next()) {String s = res.getString('username');out.println('\t\t' + s);}conn.close();} catch (Exception e) {e.printStackTrace();}} finally {out.close();}
当我们执行上面的代码时。 在正常的输入执行中,如下所示
当我们使用“ ramki”之类的正常值时,请点击“提交”按钮,然后像这样输出
在正常行为中,它是完全正确的。 当我在输入框中输入一些特殊字符或某些sql语句时会发生什么?
当我们单击提交按钮时,它将显示我的表格中的所有行,如下所示
这是我应用程序中的一个重大安全漏洞。 发生了什么……是一种SQL注入。
让我们看看发生什么了。
当我在输入框中输入正常值时,我的servlet接收并替换sql查询并执行它。
SELECT * FROM User where userId='ramki'
是正确的,我们得到了正确的输出。
当我放入sdfssd'或'1'='1时会发生什么
SELECT * FROM用户,其中userId =' sdfssd'或'1'='1 '
它的手段
SELECT * FROM User where userId ='sdfssd' or '1'='1'
像这样。 因此,我们的查询已更改。 现在新查询有2个条件。 第二条件始终为真。 第一个条件可能是正确的,也可能不是。 但是这两个条件与或逻辑相连。 因此where子句对于所有行始终为true。 结果是它们带来了表中的所有行。
这称为盲SQL注入。 如果您想了解更多有关SQL注入的详细信息,请点击此处
- http://www.unixwiz.net/techtips/sql-injection.html
- http://www.imperva.com/resources/glossary/sql_injection.html
- http://www.applicure.com/blog/owasp-top-10-2010
现在我们可以直接在输入框中输入sql语句
喜欢
ramki'UNION SELECT * FROM mysql.`user` u —
然后
SELECT * FROM User where userId =' ramki'UNION SELECT * FROM MySQL.`user` u — '
然后它的意思
SELECT * FROM User where userId ='ramki' UNION SELECT * FROM mysql.`user` u --'
在这里,他们不会使用*,因为它与第一个表不匹配。 因此,他们找到了多少列,然后将联合表与第二个表一起使用。他们想要的用户特定列。 结果,获取mysql数据库用户信息通过我们的Web应用程序公开。
sqlmap
它配备了强大的检测引擎,针对最终渗透测试仪的众多细分功能以及从数据库指纹识别到从数据库获取数据的广泛转换
在您的系统中安装sqlmap或使用BackTrack Linux
在这里,我使用了回溯Linux,因为它已经预先安装了许多应用程序,例如sqlmap。
在回溯中,sqlmap位于/ pentest / web / scanner / sqlmap中
sqlmap命令
检索所有数据库
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki --dbs
检索所有表
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test --tables
从特定表中检索所有列
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User --columns
转储特定表中所有值的列
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User --dump
转储特定表中某些值的列
./sqlmap.py -u http://localhost:8080/SQLInject/userCheck?user=ramki -D test -T User -C userId,password --dump
观看视频以获取完整的演示(高清观看):
http://www.youtube.com/watch?feature=player_embedded&v=C5PQ86nWMkM
如何防止SQL注入
- 在替代查询之前,我们需要进行验证。 删除ir可以避免使用特殊字符(如单引号),关键字(如select,Union)等。
- 与占位符一起使用准备好的语句
PreparedStatement preparedStatement=conn.prepareStatement('SELECT * FROM usercheck where username=?') ;
preparedStatement.setString(1, user);
setXXX()方法进行所有验证并转义特殊字符
现在,如果使用相同的盲注SQL注入
sdfssd'或'1'='1然后
SELECT * FROM User where userId='sdfssd\' or \'1\'=\'1'
在这里,所有特殊字符都被转义。当我们使用JPA类的ORM工具(例如Hibernate,EclipseLink,TopLink)时,也可能出现sqlinjection。
为了防止SQL注入,我们需要使用NamedQuery代替普通的Query。 因为NamedQuery在内部使用PreparedStement,但是普通查询在Java中使用norma Stement。
JPA中的普通查询
String q='SELECT r FROM User r where r.userId=''+user+''';
Query query=em.createQuery(q);
List users=query.getResultList();
所以不要使用普通查询,而是使用命名查询
Query query=em.createNamedQuery('User.findByUserId');
query.setParameter('userId', user);
List users=query.getResultList();
您可以从GitHub (或) Google代码下载演示代码
参考:在Ramki Java Blog博客上,请我们的JCG合作伙伴 Rama Krishnan 注意Java应用程序中的SQLInjection 。
翻译自: https://www.javacodegeeks.com/2012/11/sql-injection-in-java-application.html