漏洞描述
HTTP響應(yīng)截?cái)嗍怯捎趹?yīng)用程序未對(duì)用戶(hù)提交的數(shù)據(jù)進(jìn)行嚴(yán)格過(guò)濾c檢測(cè)文件是否存在,當(dāng)用戶(hù)惡意提交包含 CR(回車(chē) , 即URL編碼%0d或r)和 LF(換行符,即URL編碼%0a或n)的HTTP請(qǐng)求 , 服務(wù)器可能會(huì)創(chuàng)建兩個(gè) HTTP 響應(yīng)c檢測(cè)文件是否存在,攻擊者可以控制第二個(gè)響應(yīng)并加載攻擊 。攻擊者可控制響應(yīng)的內(nèi)容構(gòu)造XSS攻擊,其中響應(yīng)中包含惡意的或其它代碼在用戶(hù)的瀏覽器中執(zhí)行,也有可能讓用戶(hù)重定向到攻擊者控制的Web內(nèi)容或在用戶(hù)的主機(jī)上執(zhí)行惡意操作 。
審計(jì)方法
檢查對(duì)響應(yīng)頭字段是否進(jìn)行安全處理 。
如果未對(duì)響應(yīng)頭進(jìn)行任何安全處理,則為確認(rèn):
//未對(duì)響應(yīng)頭做任何安全處理,審計(jì)時(shí)為確認(rèn)String data;if (data != null){ response.addHeader("Location", "/author.jsp?lang=" + data);}
再舉一例:
//同樣的未對(duì)響應(yīng)頭做任何安全處理,審計(jì)時(shí)為確認(rèn)String author = request.getParameter(AUTHOR_PARAMETER);// ...Cookie cookie = new Cookie("author", author);response.addCookie(cookie);
如果對(duì)響應(yīng)頭做了響應(yīng)的安全處理,則為誤報(bào):
//使用Refenence類(lèi)對(duì)環(huán)境變量值進(jìn)行編碼,剔除特殊字符,為誤報(bào)if (data != null){ String decode = Reference.decode(data); response.addHeader("Location", "/author.jsp?lang=" + decode);}
修復(fù)方案:
1、對(duì)用戶(hù)的輸入進(jìn)行合理驗(yàn)證 , 對(duì)特殊字符(如、’、”等)等進(jìn)行編碼 。
2、創(chuàng)建一份安全字符白名單,只接受完全由這些受認(rèn)可的字符組成的輸入出現(xiàn)在 HTTP 響應(yīng)頭文件中 。3、使用源代碼靜態(tài)分析工具,進(jìn)行自動(dòng)化的檢測(cè),可以有效的發(fā)現(xiàn)源代碼中的 HTTP 響應(yīng)截?cái)鄦?wèn)題 。
2. 硬編碼問(wèn)題
漏洞描述
硬編碼問(wèn)題,是指將敏感數(shù)據(jù)(包括口令和加密密鑰,部分賬號(hào)的密碼以及其他敏感信息等)硬編碼在程序中 。
審計(jì)步驟
1、看掃描出的硬編碼是否為常規(guī)單詞(或通讀代碼查看是否有硬編碼敏感文件)
2、如果是常規(guī)單詞,則為誤報(bào),如:
//fipAddress為硬編碼public class IPaddress{private String ipAddress = "172.16.254.1";public static void main(String[] args){//...}}
可以使用 javap -c命令來(lái)反編譯 class 來(lái)發(fā)現(xiàn)其中硬編碼的服務(wù)器 IP 地址,此處反
編譯器的輸出信息可以直接透漏服務(wù)器的明文 IP 地址為172.16.254.1
再舉一例:
//SECRET_PASSWORD為硬編碼private String SECRET_PASSWORD = "No fear in my heart!"; Properties props = new Properties(); props.put(Context.SECURITY_CREDENTIALS, "password");
3、如果是隨機(jī)字符串,則為確認(rèn)或待確認(rèn),如:
//1546272000000為硬編碼byte[] sr = hBaseClient.buildRowKey(devId, "1546272000000");
再舉一例:
//qafgshw1900wxxxx為硬編碼private String accessKeyId = "qafgshw1900wxxxx";
4、追蹤key值,如果key為硬編碼則為確認(rèn),如:
//key值為硬編碼byte[] key = {1, 2, 3, 4, 5, 6, 7, 8};SecretKeySpec spec = new SecretKeySpec(key, "AES");Cipher aes = Cipher.getInstance("AES");aes.init(Cipher.ENCRYPT_MODE, spec);return aesCipher.doFinal(secretData);
追蹤key值 , 如果追蹤不到或者為安全形式,則為誤報(bào),如
//無(wú)法再繼續(xù)追蹤key值 , 為誤報(bào)public static byte[] encryptByPrivateKey(byte[] data, String key) throws Exception {//key為密鑰byte[] keyBytes = decryptBASE64(key);PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());cipher.init(Cipher.ENCRYPT_MODE, privateKey);return cipher.doFinal(data);}
再來(lái)一栗:
//存儲(chǔ)密鑰 。KeyStore.getInstance("PKCS12")為密鑰庫(kù),為誤報(bào)try{KeyStore keyStore = KeyStore.getInstance("PKCS12");keyStore.load(null, null);KeyGenerator keyGen = KeyGenerator.getInstance("AES");keyGen.init(128);Key key = keyGen.generateKey();keyStore.setKeyEntry("secret", key, "password".toCharArray(), null);keyStore.store(new FileOutputStream("output.p12"), "password".toCharArray());} catch (Exception ex){ex.printStackTrace();}
修復(fù)方案
推薦使用配置文件或者通過(guò)配置中心來(lái)下發(fā)這些敏感配置 , 密碼和密鑰應(yīng)存儲(chǔ)在單獨(dú)的加密配置文件或密鑰庫(kù)中 。
3. SQL注入
漏洞描述
注入攻擊的本質(zhì),是程序把用戶(hù)輸入的數(shù)據(jù)當(dāng)做代碼執(zhí)行 。這里有兩個(gè)關(guān)鍵條件:
第一是用戶(hù)能夠控制輸入;
第二是用戶(hù)輸入的數(shù)據(jù)被拼接到要執(zhí)行的代碼中從而被執(zhí)行 。
sql 注入漏洞則是程序?qū)⒂脩?hù)輸入數(shù)據(jù)拼接到了 sql 語(yǔ)句中,從而攻擊者即可構(gòu)造、改變 sql 語(yǔ)義從而進(jìn)行攻擊 。
漏洞舉例
(1) 直接通過(guò)拼接 sql
@RequestMapping("/SqlInjection/{id}")public ModelAndView SqlInjectTest(@PathVariable String id){String mysqldriver = "com.mysql.jdbc.Driver";String mysqlurl = "jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&characterEncoding=utf8&autoReconnect=true";#直接通過(guò)拼接 sqlString sql = "select * from user where id=" + id;ModelAndView mav = new ModelAndView("test2"); try{Class.forName(mysqldriver);Connection conn = DriverManager.getConnection(mysqlurl);PreparedStatement pstt = conn.prepareStatement(sql);ResultSet rs = pstt.executeQuery();
再來(lái)一例:
//沒(méi)有做任何其他安全處理措施stmt = conn.createStatement();rs = stmt.executeQuery("select * from user where username = '" + username+"' and password='"+password+"'");
(2) 預(yù)編譯使用有誤
漏洞舉例:
//只使用了占位符@RequestMapping("/SqlInjection/{id}")public ModelAndView SqlInjectTest(@PathVariable String id){String mysqldriver = "com.mysql.jdbc.Driver";String mysqlurl = "jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&characterEncoding=utf8&autoReconnect=true";String sql = "select * from user where id= ?";ModelAndView mav = new ModelAndView("test2"); try{Class.forName(mysqldriver);Connection conn = DriverManager.getConnection(mysqlurl);PreparedStatement pstt = conn.prepareStatement(sql);//pstt.setObject(1, id); //一般使用有誤的是沒(méi)有用這一句,編碼者以為在上面的sql語(yǔ)句中直接使用占位符就可以了 。ResultSet rs = pstt.executeQuery();
審計(jì)步驟:查看預(yù)編譯的完整性 , 關(guān)鍵函數(shù)定位 ()、()、()、()關(guān)聯(lián)上下文搜索 set* 開(kāi)頭的函數(shù) 。
(3) %和_( 中模糊查詢(xún))問(wèn)題
@RequestMapping("/SqlInjection/{id}")public ModelAndView SqlInjectTest(@PathVariable String id){String mysqldriver = "com.mysql.jdbc.Driver";String mysqlurl = "jdbc:mysql://127.0.0.1:3306/test?user=root&password=123456&useUnicode=true&characterEncoding=utf8&autoReconnect=true";String sql = "select * from user where id= ?";ModelAndView mav = new ModelAndView("test2"); try{Class.forName(mysqldriver);Connection conn = DriverManager.getConnection(mysqlurl);PreparedStatement pstt = conn.prepareStatement(sql);pstt.setObject(1, id); //使用預(yù)編譯ResultSet rs = pstt.executeQuery();
審計(jì)步驟:定位相關(guān) sql 語(yǔ)句上下文 , 查看是否有顯式過(guò)濾機(jī)制 。
修復(fù)方案:上面的代碼片段即使這樣依然存在 sql 注入,原因是沒(méi)有手動(dòng)過(guò)濾% 。預(yù)編譯是不能處理這個(gè)符號(hào)的,以需要手動(dòng)過(guò)濾,否則會(huì)造成慢查詢(xún),造成 dos 。
(4) order by 問(wèn)題
String sql = “Select * from news where title =?”+ “order by ‘” + time + “’asc”
審計(jì)步驟:定位相關(guān) sql 語(yǔ)句上下文,查看是否有顯式過(guò)濾機(jī)制 。
修復(fù)方案:類(lèi)似上面的這種 sql 語(yǔ)句 order by 后面是不能用預(yù)編譯處理的只能通過(guò)拼接處理,所以需要手動(dòng)過(guò)濾 。
(5) 有關(guān)$符號(hào)的情況
#{}:相當(dāng)于jdbc中的,傳入的字符串,需要賦值后使用 , 可以有效防止sql注入
${}:是輸出變量的值,傳入的變量 , 直接在sql中執(zhí)行,無(wú)法防止sql注入 簡(jiǎn)單的說(shuō)就是#{}傳過(guò)來(lái)的參數(shù)帶單引號(hào)’' , 而${}傳過(guò)來(lái)的參數(shù)不帶單引號(hào) 。
但是是動(dòng)態(tài)SQL,只能用${},用#{}會(huì)多個(gè)’ '導(dǎo)致sql語(yǔ)句失效 。此外還有一個(gè)like 語(yǔ)句后也需要用${} 。
//需要轉(zhuǎn)義的字符串仍使用$delete from ${tableName}
修復(fù)方案:對(duì)于可以使用#{}的情況,直接使用#{}即可解決問(wèn)題對(duì)于不能使用#{}的情況(如),需要增加額外的過(guò)濾邏輯,以此判斷輸入內(nèi)容是否正常,如字段類(lèi)型、字段長(zhǎng)度等
4. maven不安全模塊
漏洞描述
Maven,是一個(gè)Java開(kāi)發(fā)比較常用的項(xiàng)目管理工具,可以對(duì)Java項(xiàng)目進(jìn)行構(gòu)建、依賴(lài)管理 。當(dāng)它配置一個(gè)不安全的模塊時(shí) , 即存在安全風(fēng)險(xiǎn) 。
審計(jì)方法
查看配置的版本是否屬于安全版本區(qū)間 。如果是,則確認(rèn):
【總結(jié)常見(jiàn)漏洞的代碼審計(jì)方法】//3.9版本是存在漏洞的版本 。安全版本是3.11以上com.hazelcasthazelcast-client3.9
修復(fù)方案
配置為安全版本即可(同時(shí)應(yīng)注意解決兼容性問(wèn)題)
5. 服務(wù)端請(qǐng)求偽造(SSRF)
漏洞描述
SSRF是攻擊者讓服務(wù)端發(fā)起指定的請(qǐng)求 , 攻擊的目標(biāo)一般是從外網(wǎng)無(wú)法訪問(wèn)的內(nèi)網(wǎng)系統(tǒng) 。SSRF形成的原因大都是由于代碼中提供了從其他服務(wù)器應(yīng)用獲取數(shù)據(jù)的功能但沒(méi)有對(duì)目標(biāo)地址做過(guò)濾與限制 。比如從指定URL鏈接獲取圖片、下載等 。一般利用http協(xié)議來(lái)探測(cè)端口,利用file協(xié)議讀取任意文件 。
利用場(chǎng)景
SSRF漏洞一般位于遠(yuǎn)程圖片加載與下載、圖片或文章收藏功能、URL分享、通過(guò)URL在線翻譯、轉(zhuǎn)碼等功能點(diǎn)處 。
關(guān)鍵詞/接口/類(lèi)包
// JavaHttpURLConnection.getInputStreamURLConnection.getInputStreamRequest.Get.executeRequest.Post.executeURL.openStreamImageIO.readOkHttpClient.newCall.executeHttpClients.executeHttpClient.execute
審計(jì)方法
1、內(nèi)網(wǎng)系統(tǒng)的SSRF直接為誤報(bào)(內(nèi)網(wǎng)系統(tǒng)之間互調(diào)互傳)
2、檢查請(qǐng)求的URL是否為外部可控 , 即由外部傳入
3、檢查請(qǐng)求的返回 , 是否對(duì)請(qǐng)求的返回?cái)?shù)據(jù)做了安全處理
漏洞示例
//請(qǐng)求URL為外部可控,返回?cái)?shù)據(jù)直接展示String url = request.getParameter("picurl");StringBuffer response = new StringBuffer();URL pic = new URL(url);HttpURLConnection con = (HttpURLConnection) pic.openConnection();con.setRequestMethod("GET");con.setRequestProperty("User-Agent", "Mozilla/5.0");//發(fā)起請(qǐng)求,觸發(fā)漏洞BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));String inputLine;while ((inputLine = in.readLine()) != null) { response.append(inputLine);}in.close();modelMap.put("resp",response.toString());return "getimg.htm";
再舉一例:
//HttpClients函數(shù)的SSRF漏洞代碼,審計(jì)時(shí)為確認(rèn):String url = request.getParameter("url");CloseableHttpClient client = HttpClients.createDefault();HttpGet httpGet = new HttpGet(url);HttpResponse httpResponse = client.execute(httpGet); //發(fā)起請(qǐng)求
修復(fù)方案
本文到此結(jié)束,希望對(duì)大家有所幫助 。
- 有哪些不常見(jiàn)卻很實(shí)用的電腦軟件?
- 多年經(jīng)驗(yàn)總結(jié)CAD技巧6
- 跑鞋怎么清洗
- 工控中最常見(jiàn)的7種PLC編程語(yǔ)言,據(jù)說(shuō)精通5種以上就可以月薪過(guò)萬(wàn)
- 技成周報(bào)38期 | SMART PLC Modbus通訊、組態(tài)、模擬量等常見(jiàn)問(wèn)題
- 怎么滅螞蟻
- 框架篇 java必背綜合知識(shí)點(diǎn)總結(jié)
- 常見(jiàn)Serialize技術(shù)探秘(XML、JSON、JDBC byte編碼、Pro
- 基于Docker的漏洞驗(yàn)證框架的設(shè)計(jì)與實(shí)現(xiàn)-AET
- 下 收藏丨電腦實(shí)用基礎(chǔ)知識(shí)與常見(jiàn)問(wèn)題解決方法匯總!
