注射式攻擊的原理
SQL注射能使攻擊者繞過認證機制,完全控制遠程服務器上的數據庫。SQL是結構化查詢語言的簡稱,它是訪問數據庫的事實標准。目前,大多數Web應用都使用SQL數據庫來存放應用程序的數據。幾乎所有的Web應用在后台都使用某種SQL數據庫。跟大多數語言一樣,SQL語法允許數據庫命令和用戶數據混雜在一起的。如果開發人員不細心的話,用戶數據就有可能被解釋成命令,這樣的話,遠程用戶就不僅能向Web應用輸入數據,而且還可以在數據庫上執行任意命令了。
看下面的代碼:
public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); System.out.println("賬號:"); String uid = sc.nextLine(); System.out.println("密碼:"); String pwd = sc.nextLine(); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?characterEncoding=GBK","root",""); Statement state = conn.createStatement(); String sql = "select * from users where user ='"+uid+"' and password ='"+pwd+"' "; ResultSet rs = state.executeQuery(sql); boolean ok = rs.next(); if(ok){ System.out.println("歡迎"+rs.getString(3)+"回來"); } else{ System.out.println("您輸入的賬號密碼錯誤"); } conn.close(); }
我們正常輸入賬號密碼是運行正確的,但是當我們賬號輸入:kjaskj' or 1=1 # 密碼輸入:klkjl; 就會出現以下的結果:
歡迎張三回來
這里,關鍵在 賬號里面的那個單引號 “ ‘ ’”和后面 or 1=1以及#號(我們這里用的是mysql,oracle后面用 --)。這樣查詢語句就變成了:
select * from users where user ='kjaskj'or1=1#' and password ='"+pwd+"'
該雙划符號#告訴SQL解析器,右邊的東西全部是注釋,所以不必理會。這樣,查詢字符串相當於:
select * from users where user =''OR1=1. 這樣輸出的就是ture。 就能不用賬號密碼直接進入。
當然這里也有辦法阻止此類事件的發生。
在代碼中間插入一個替換一句,將該方法中所有的單引號替換成雙引號,就不會發生類似的事情。代碼如下:
public static void main(String[] args) throws Exception { Scanner sc = new Scanner(System.in); System.out.println("賬號:"); String uid = sc.nextLine(); System.out.println("密碼:"); String pwd = sc.nextLine(); Class.forName("com.mysql.jdbc.Driver"); Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb?characterEncoding=GBK","root",""); Statement state = conn.createStatement(); uid=uid.replace("\'", "\"");//替換單雙引號 String sql = "select * from users where user ='"+uid+"' and password ='"+pwd+"' "; ResultSet rs = state.executeQuery(sql); boolean ok = rs.next(); if(ok){ System.out.println("歡迎"+rs.getString(3)+"回來"); } else{ System.out.println("您輸入的賬號密碼錯誤"); } conn.close(); }