網(wǎng)站首頁 編程語言 正文
SQL注入
SQL注入是通過操作輸入來修改事先定義好的SQL語句,對用戶輸入的字符串進(jìn)行過濾,轉(zhuǎn)義,限制或處理不嚴(yán)謹(jǐn),導(dǎo)致用戶可以通過輸入精心構(gòu)造的字符串去非法獲取到數(shù)據(jù)庫中的數(shù)據(jù),以達(dá)到執(zhí)行代碼對服務(wù)器進(jìn)行攻擊的方法。
現(xiàn)有一個(gè)數(shù)據(jù)庫test中的表user,可以通過賬號name,密碼pass登錄,查看id
登錄代碼
package JDBCtest; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; import java.util.Scanner; /* * 用戶登錄 */ public class Demo4 { public static void main(String[] args) throws Exception { // 1.加載驅(qū)動 Class.forName("com.mysql.jdbc.Driver"); // 2.創(chuàng)建連接 String url = "jdbc:mysql:///test"; String username = "root"; String password = "1234"; Connection connection = DriverManager.getConnection(url, username, password); // 接收用戶名密碼 Scanner sc = new Scanner(System.in); String name = sc.next(); String pass = sc.next();// 3.sql語句 String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'"; // System.out.println(sql); // 4.獲取sql對象statement Statement statement = connection.createStatement(); // 5.執(zhí)行sql語句 ResultSet rs = statement.executeQuery(sql); // 6.登錄 if (rs.next()) { System.out.println("登錄成功"); } else { System.out.println("登錄失敗"); } // 7.釋放資源 statement.close(); connection.close(); } }
通過表中賬號密碼登錄成功
由于賬號或密碼錯(cuò)誤登錄失敗
以上可以正確登錄成功或失敗
注意!
如果此時(shí)我這樣輸入 【lihua 'or'1'='1
】,也成功登錄了,但是數(shù)據(jù)庫沒根本沒有這條數(shù)據(jù)
這是為什么呢?讓我們從代碼里找問題!
String sql = "Select * from user where name='" + name + "' and pass ='" + pass + "'";
為了調(diào)用數(shù)據(jù)庫,使用字符串拼接SQL語句
讓我們打印一下輸入 【lihua 'or'1'='1
】的sql語句一探究竟
select語句中的where條件可以看做兩組并列(注意and在前先執(zhí)行,or后執(zhí)行)
由于'1'='1'為TRUE,所以以上語句等價(jià)于肯定會登錄成功!
同理輸入【'or'1'='1'# xxx
】也能登陸成功
這是由于#在SQL中是注釋符號,以上語句等價(jià)于,于是就和上述情況一樣了。
附防止sql注入的一些建議
1. 代碼層防止sql注入攻擊的最佳方案就是sql預(yù)編譯
public ListorderList(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)); }
這樣我們傳進(jìn)來的參數(shù)?4 or 1 = 1
就會被當(dāng)作是一個(gè)student_id
,所以就不會出現(xiàn)sql注入了。
2. 確認(rèn)每種數(shù)據(jù)的類型,比如是數(shù)字,數(shù)據(jù)庫則必須使用int類型來存儲
3. 規(guī)定數(shù)據(jù)長度,能在一定程度上防止sql注入
4. 嚴(yán)格限制數(shù)據(jù)庫權(quán)限,能最大程度減少sql注入的危害
5. 避免直接響應(yīng)一些sql異常信息,sql發(fā)生異常后,自定義異常進(jìn)行響應(yīng)
6. 過濾參數(shù)中含有的一些數(shù)據(jù)庫關(guān)鍵詞
@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; //獲得所有請求參數(shù)名 Enumeration params = req.getParameterNames(); String sql = ""; while (params.hasMoreElements()) { // 得到參數(shù)名 String name = params.nextElement().toString(); // 得到參數(shù)對應(yīng)值 String[] value = req.getParameterValues(name); for (int i = 0; i < value.length; i++) { sql = sql + value[i]; } } if (sqlValidate(sql)) { throw new IOException("您發(fā)送請求中的參數(shù)中含有非法字符"); } else { chain.doFilter(servletRequest,servletResponse); } } /** * 關(guān)鍵詞校驗(yàn) * @param str * @return */ protected static boolean sqlValidate(String str) { // 統(tǒng)一轉(zhuǎn)為小寫 str = str.toLowerCase(); // 過濾掉的sql關(guān)鍵字,可以手動添加 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; } }
總結(jié)
原文鏈接:https://www.cnblogs.com/empolder-minoz/p/16040841.html
相關(guān)推薦
- 2022-05-18 ASP.NET?MVC授權(quán)過濾器用法_實(shí)用技巧
- 2022-03-01 show-overflow-tooltip實(shí)現(xiàn)表格列內(nèi)容過長顯示提示
- 2023-04-27 Redisson分布式限流的實(shí)現(xiàn)原理解析_Redis
- 2022-09-13 Android四大組件之Activity深入解讀生命周期_Android
- 2022-03-28 IPython?8.0?Python?命令行交互工具_(dá)python
- 2024-02-29 UNI-APP開發(fā)之插件安裝失敗,離線安裝
- 2022-11-15 一文詳解React?Redux使用方法_React
- 2022-06-17 C#關(guān)鍵字之重寫override介紹_C#教程
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細(xì)win安裝深度學(xué)習(xí)環(huán)境2025年最新版(
- Linux 中運(yùn)行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎(chǔ)操作-- 運(yùn)算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認(rèn)證信息的處理
- Spring Security之認(rèn)證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權(quán)
- redisson分布式鎖中waittime的設(shè)
- maven:解決release錯(cuò)誤:Artif
- restTemplate使用總結(jié)
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實(shí)現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務(wù)發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結(jié)構(gòu)-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標(biāo)對象命令
- Spring中的單例模式應(yīng)用詳解
- 聊聊消息隊(duì)列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠(yuǎn)程分支