在本文中,我們將討論什么是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