共計 3262 個字符,預計需要花費 9 分鐘才能閱讀完成。
自動寫代碼機器人,免費開通
如何有效防止 sql 注入?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面丸趣 TV 小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
@RestController
public class Controller {
@Autowired
SqlInject sqlInject;
@GetMapping(list)
public List Course courseList(@RequestParam( studentId) String studentId){ List Course orders = sqlInject.orderList(studentId);
return orders;
}
}
@Service
public class SqlInject {
@Autowired
private JdbcTemplate jdbcTemplate;
public List Course orderList(String studentId){
String sql = select id,course_id,student_id,status from course where student_id = + studentId;
return jdbcTemplate.query(sql,new BeanPropertyRowMapper(Course.class));
}
}
二 注入攻擊演示
1. 正常情況下查詢一個學生所選課程及完成情況只需要傳入 student_id,便可以查到相關數據。
根據響應結果,我們很快便能寫出對應的 sql,如下:
select id,course_id,student_id,status
from course
where student_id = 4
2. 如果我們想要獲取這張表的所有數據,只需要保證上面這個 sql 的 where 條件恒真就可以了。
select id,course_id,student_id,status
from course
where student_id = 4
or 1 = 1
請求接口的時候將 studendId 設置為 4 or 1 = 1,這樣這條 sql 的 where 條件就恒真了。sql 也就等同于下面這樣
select id,course_id,student_id,status
from course
請求結果如下,我們拿到了這張表的所有數據
3. 查詢 mysql 版本號,使用 union 拼接 sql
union select 1,1,version(),1
4. 查詢數據庫名
union select 1,1,database(),1
5. 查詢 mysql 當前用戶的所有庫
union select 1,1, (SELECT GROUP_CONCAT(schema_name) FROM information_schema.schemata) schemaName,1
看完上面這些演示后,你害怕了嗎?你所有的數據配置都完全暴露出來了,除此之外,還可以完成很多操作,更新數據、刪庫、刪表等等。
三 如何防止 sql 注入
1. 代碼層防止 sql 注入攻擊的最佳方案就是 sql 預編譯
public List Course orderList(String studentId){
String sql = select id,course_id,student_id,status from course where student_id = ?
return jdbcTemplate.query(sql,new Object[]{studentId},new BeanPropertyRowMapper(Course.class));
}
這樣我們傳進來的參數 4 or 1 = 1 就會被當作是一個 student_id,所以就不會出現 sql 注入了。
2. 確認每種數據的類型,比如是數字,數據庫則必須使用 int 類型來存儲
3. 規定數據長度,能在一定程度上防止 sql 注入
4. 嚴格限制數據庫權限,能最大程度減少 sql 注入的危害
5. 避免直接響應一些 sql 異常信息,sql 發生異常后,自定義異常進行響應
6. 過濾參數中含有的一些數據庫關鍵詞
@Component
public class SqlInjectionFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException { HttpServletRequest req=(HttpServletRequest)servletRequest;
HttpServletRequest res=(HttpServletRequest)servletResponse;
// 獲得所有請求參數名
Enumeration params = req.getParameterNames();
String sql =
while (params.hasMoreElements()) {
// 得到參數名
String name = params.nextElement().toString();
// 得到參數對應值
String[] value = req.getParameterValues(name);
for (int i = 0; i value.length; i++) { sql = sql + value[i];
}
}
if (sqlValidate(sql)) {
throw new IOException( 您發送請求中的參數中含有非法字符
} else { chain.doFilter(servletRequest,servletResponse);
}
}
/**
* 關鍵詞校驗
* @param str
* @return
*/
protected static boolean sqlValidate(String str) {
// 統一轉為小寫
str = str.toLowerCase();
// 過濾掉的 sql 關鍵字,可以手動添加
String badStr = |and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate| +
char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like |and|exec|execute|insert|create|drop| +
table|from|grant|use|group_concat|column_name| +
information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*| +
chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#
String[] badStrs = badStr.split( \\|
for (int i = 0; i badStrs.length; i++) { if (str.indexOf(badStrs[i]) = 0) {
return true;
}
}
return false;
}
}
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注丸趣 TV 行業資訊頻道,感謝您對丸趣 TV 的支持。
向 AI 問一下細節