1 背景
京東SRC( )收錄大量外部白帽子提交的sql注入漏洞,漏洞發(fā)生的原因多為sql語句拼接和使用不當(dāng)導(dǎo)致。
2 手工檢測2.1 前置知識
.0以上版本中存在一個(gè)重要的系統(tǒng)數(shù)據(jù)庫,通過此數(shù)據(jù)庫可訪問mysql中存在的數(shù)據(jù)庫名、表名、字段名等元數(shù)據(jù)。中有三個(gè)表成為了sql注入構(gòu)造的關(guān)鍵。
1).:2).).
SQL注入常用SQL函數(shù)
2.2 注入類型2.2.1 參數(shù)類型分類2.2.2 注入方式分類2.3 手動檢測步驟(字符型注入為例)
// sqli vuln code
Statement statement = con.createStatement();
String sql = "select * from users where username = '" + username + "'";
logger.info(sql);
ResultSet rs = statement.executeQuery(sql);
// fix code 如果要使用原始jdbc,請采用預(yù)編譯執(zhí)行
String sql = "select * from users where username = ?";
PreparedStatement st = con.prepareStatement(sql);
使用未預(yù)編譯原始jdbc作為democ添加數(shù)據(jù)到數(shù)據(jù)庫,注意此demo中sql語句參數(shù)采用單引號閉合。
2.3.1 確定注入點(diǎn)
對于字符類型注入,通常先嘗試單引號,判斷單引號是否被拼接到SQL語句中。推薦使用瀏覽器擴(kuò)展作為手工測試工具。
正常頁面應(yīng)該顯示如下:
admin后加單引號導(dǎo)致無信息回顯,原因是后端sql執(zhí)行報(bào)錯(cuò),說明引號被拼接至SQL語句中
select * from users where username = 'admin' #正常sql
select * from users where username = 'admin'' #admin'被帶入sql執(zhí)行導(dǎo)致報(bào)錯(cuò)無法顯示信息
2.3.2 判斷字段數(shù)
mysql中使用order by 進(jìn)行排序,不僅可以是字段名也可以是字段序號。所以可以用來判斷表中字段數(shù),order by 超過字段個(gè)數(shù)的數(shù)字就會報(bào)錯(cuò)。
判斷字段數(shù)
當(dāng)order by 超過4時(shí)會報(bào)錯(cuò),所以此表共四個(gè)字段。
后端所執(zhí)行的sql語句
select * from users where username = 'admin' order by 1-- '
此處我們將原本的值admin替換為admin’ order by 1 —+,其中admin后的單引號用于閉合原本sql語句中的前引號,—+用于注釋sql語句中的后引號。—后的+號主要作用是提供一個(gè)空格,sql語句單行注釋后需有空格,+會被解碼為空格。
2.3.3 確定回顯位置
主要用于定位后端sql字段在前端顯示的位置,采用聯(lián)合查詢的方式確定。注意聯(lián)合查詢前后字段需一致,這也就是我們?yōu)槭裁醋龅诙降脑颉?/p>
通過下圖可知,后端查詢并回顯的字段位置為2,3位。
聯(lián)合查詢后的字段可以隨意c添加數(shù)據(jù)到數(shù)據(jù)庫,本次采用的是數(shù)字1到4直觀方便。
2.3.4 利用庫實(shí)現(xiàn)注入
()函數(shù)用于將查詢結(jié)果拼接為字符串。
3 自動化檢測3.1 使用
兼容和,可以自動化檢測各類注入和幾乎所有數(shù)據(jù)庫類型。
3.1.1 常用命令
-u 可能存在注入的url鏈接
-r讀取http數(shù)據(jù)包
--data 指定post數(shù)據(jù)
--cookie 指定cookie
--headers 指定http頭 如采用token認(rèn)證的情況下
--threads 指定線程數(shù)
--dbms 指定后端的數(shù)據(jù)庫

--os 指定后端的操作系統(tǒng)類型
--current-user 當(dāng)前用戶
--users 所有用戶
--is-dba 是否是dba
--sql-shell 交互式的sqlshell
-p指定可能存在注入點(diǎn)的參數(shù)
--dbs 窮舉系統(tǒng)存在的數(shù)據(jù)庫
-D指定數(shù)據(jù)庫
--tables 窮舉存在的表
-T指定表
--column 窮舉字段
-C指定字段
--dump dump數(shù)據(jù)
直接檢測
其中—用于指定,—batch 自動化執(zhí)行,—dbms指定數(shù)據(jù)庫類型
檢測結(jié)果
讀取系統(tǒng)中存在數(shù)據(jù)庫
—dbs讀取當(dāng)前用戶下的數(shù)據(jù)庫
讀取指定庫下的表
-D —
dump users表數(shù)據(jù)
-D -T users —dump
4 進(jìn)階4.1 注入1)$錯(cuò)誤使用導(dǎo)致注入
//采用#不會導(dǎo)致sql注入,mybatis會使用預(yù)編譯執(zhí)行
@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);
//采用$作為入?yún)⒖蓪?dǎo)致sql注入
@Select("select * from users where username = '${username}'")
List findByUserNameVuln01(@Param("username") String username);
2)模糊查詢拼接
//錯(cuò)誤寫法
//正確寫法
3)order by 注入
order by 后若使用#{}會導(dǎo)致報(bào)錯(cuò),因?yàn)?{}默認(rèn)添加引號會導(dǎo)致找不到字段從而報(bào)錯(cuò)。
//錯(cuò)誤寫法
//正確寫法 id指字段id 此表字段共四個(gè) 所以id為1-4