1.XSS攻擊
????? 1.1什么是XSS攻擊手段
?????? XSS攻擊使用Javascript腳本注入進(jìn)行攻擊
??????? 例如在提交表單后,展示到另一個頁面闽铐,可能會受到XSS腳本注入蝶怔,讀取本地cookie遠(yuǎn)程? 發(fā)送給黑客服務(wù)器端。
alert('sss')
window.location.;
????? 對應(yīng)html源代碼: <script>alert('sss')</script>
?? 1.2.如何防御XSS攻擊
???? 將腳本特殊字符兄墅,轉(zhuǎn)換成html源代碼進(jìn)行展示踢星。
??? 步驟:編寫過濾器攔截所有g(shù)etParameter參數(shù),重寫httpservletwrapp方法
????? 將參數(shù)特殊字符轉(zhuǎn)換成html源代碼保存.
// 重寫HttpServletRequestWrapper
? 防止XSS攻擊
publicclassXssHttpServletRequestWrapperextendsHttpServletRequestWrapper {
privateHttpServletRequest request;
public XssHttpServletRequestWrapper(HttpServletRequest request) {
super(request);
this.request = request;
????? }
????? @Override
publicString? getParameter(String name) {
??????????? // 過濾getParameter參數(shù) 檢查是否有特殊字符
Stringvalue =super.getParameter(name);
System.out.println("value:" + value);
if(!StringUtils.isEmpty(value)) {
????????????????? // 將中文轉(zhuǎn)換為字符編碼格式隙咸,將特殊字符變?yōu)閔tml源代碼保存
???????????????? //這是common-lang依賴庫的工具類
value=? StringEscapeUtils.escapeHtml(value);
System.out.println("newValue:" + value);
??????????? }
returnvalue;
????? }
}
SpringBoot啟動加上@ServletComponentScan
@SpringBootApplication
@ServletComponentScan
publicclassApp {
publicstaticvoidmain(String[] args) {
SpringApplication.run(App.class, args);
????? }
}
2.sql注入攻擊
? 2.1什么是SQL注入
SQL注入:利用現(xiàn)有應(yīng)用程序沐悦,將(惡意)的SQL命令注入到后臺數(shù)據(jù)庫執(zhí)行一些惡意的工作。造成SQL注入的原因是因?yàn)槌绦驔]有有效過濾用戶的輸入五督,使攻擊者成功的向服務(wù)器提交惡意的SQL查詢代碼藏否,程序在接收后錯誤的將攻擊者的輸入作為查詢語句的一部分執(zhí)行,導(dǎo)致原始的查詢邏輯被改變充包,額外的執(zhí)行了攻擊者精心構(gòu)造的惡意代碼
? 2.2SQL注入防攻擊手段
不要使用拼接SQL語句方式副签、最好使用預(yù)編譯方式,在mybatis編寫sql語句的時候基矮,最好使用#傳參數(shù)方式淆储,不要使用$傳參數(shù),因?yàn)?傳參數(shù)方式家浇,可能會受到sql語句攻擊本砰。
演示案例:
http://127.0.0.1:8080/login?userName='liusi'&password='123'
http://127.0.0.1:8080/login?userName='liusi'&password='123'? or 1=1
整體意思為mybatis框架中配置文件mapper中一般采用#{}方式因?yàn)檫@種代表采用預(yù)編譯方式,不管調(diào)用者傳怎么樣的值都會只當(dāng)成內(nèi)容
3.Http請求防盜鏈
? 3.1什么是防盜鏈
??? 比如A網(wǎng)站有一張圖片钢悲,被B網(wǎng)站直接通過img標(biāo)簽屬性引入点额,直接盜用A網(wǎng)站圖片展示。
防盜鏈
?? 3.2如何實(shí)現(xiàn)防盜鏈(底層原理)
? ?? 判斷http請求頭Referer域中的記錄來源的值莺琳,如果和當(dāng)前訪問的域名不一致的情況下还棱,說明該圖片可能被其他服務(wù)器盜用。
? 3.3使用過濾器判斷請求頭Referer記錄請求來源
?? @WebFilter(filterName = "imgFilter", urlPatterns = "/imgs/*")
publicclassImgFilterimplementsFilter {
????? @Value("${domain.name}")//獲取域名
privateString domainName;
publicvoidinit(FilterConfig filterConfig)throwsServletException {
????? }
publicvoiddoFilter(ServletRequest request, ServletResponse response,
FilterChain chain)throwsIOException, ServletException {
??????????? HttpServletRequestreq = (HttpServletRequest) request;
??????????? Stringreferer = req.getHeader("Referer");
if(StringUtils.isEmpty(referer)) {//為空
????????????????? request.getRequestDispatcher("/imgs/error.png").forward(request, response);
return;
??????????? }
??????????? Stringdomain = getDomain(referer);
if(!domain.equals(domainName)) {//和傳過來的進(jìn)行對比
????????????????? request.getRequestDispatcher("/imgs/error.png").forward(request, response);
return;
??????????? }
??????????? chain.doFilter(request, response);//放行
????? }
????? /**
????? ?*獲取url對應(yīng)的域名
????? ?*
*@paramurl
*@return
????? ?*/
publicString getDomain(String url) {//只要域名芦昔,不要http以及雙斜杠那些所以截取
??????????? Stringresult = "";
intj = 0, startIndex = 0, endIndex = 0;
for(inti = 0; i < url.length();? i++) {
if(url.charAt(i) == '/') {
??????????????????????? j++;
if(j == 2)
????????????????????????????? startIndex = i;
elseif(j == 3)
????????????????????????????? endIndex = i;
????????????????? }
??????????? }
??????????? result = url.substring(startIndex + 1, endIndex);
returnresult;
????? }
}
對于springboot項目記得啟動類加上@ServletComponentScan
否則識別不了攔截器注解
現(xiàn)在比較高級的一般采用黑名單诱贿,白名單方式來設(shè)定是否可以訪問資源(不僅圖片)
黑名單,白名單
4.CSRF攻擊
4.1CSRF攻擊產(chǎn)生的原因
(Cross
SiteRequest Forgery, 跨站域請求偽造)是一種網(wǎng)絡(luò)的攻擊方式咕缎,它在 2007 年曾被列為互聯(lián)網(wǎng) 20
大安全隱患之一,也被稱為“OneClick Attack”或者Session
Riding珠十,通常縮寫為CSRF或者XSRF凭豪,是一種對網(wǎng)站的惡意利用也就是人們所知道的釣魚網(wǎng)站焙蹭。盡管聽起來像跨站腳本(XSS),但它與XSS非常不同嫂伞,并且攻擊方式幾乎相左孔厉。XSS利用站點(diǎn)內(nèi)的信任用戶拯钻,而CSRF則通過偽裝來自受信任用戶的請求來利用受信任的網(wǎng)站。與XSS攻擊相比撰豺,CSRF攻擊往往不大流行(因此對其進(jìn)行防范的資源也相當(dāng)稀少)和難以防范粪般,所以被認(rèn)為比XSS更具危險性。
簡單說明即多次重復(fù)性發(fā)送請求
4.2如何解決CSRF以及防止偽造token
可以通過驗(yàn)證碼污桦,短信校驗(yàn)亩歹,以及人臉識別等技術(shù),進(jìn)而判斷是真人操作凡橱,而不是機(jī)器人在模擬發(fā)送小作,nginx限流,配置黑名單稼钩,白名單顾稀,當(dāng)然沒有百分百能夠完全保證沒有問題
5.忘記密碼漏洞
? 黑客使用抓包工具分析Http請求,在忘記密碼找回時坝撑,需要發(fā)送一套短信驗(yàn)證碼静秆,如果驗(yàn)證碼數(shù)字比較短的話,很容易使用暴力破解方式攻擊破绍载。
防御手段:
忘記密碼驗(yàn)證碼最好在6-8位诡宗。
一旦頻繁調(diào)用接口驗(yàn)證時滔蝉,應(yīng)該使用圖形驗(yàn)證碼攔截击儡,防止機(jī)器模擬。
使用黑名單和白名單機(jī)制蝠引,防御攻擊阳谍。
如何防止密碼被破解
6.上傳文件漏洞
? 6.1漏洞描述
上傳漏洞這個顧名思義,就是攻擊者通過上傳木馬文件螃概,直接得到WEBSHELL矫夯,危害等級超級高,現(xiàn)在的入侵中上傳漏洞也是常見的漏洞吊洼。
?導(dǎo)致該漏洞的原因在于代碼作者沒有對訪客提交的數(shù)據(jù)進(jìn)行檢驗(yàn)或者過濾不嚴(yán)训貌,可以直接提交修改過的數(shù)據(jù)繞過擴(kuò)展名的檢驗(yàn)。
? 6.2 漏洞危害
??? 1)可以得到WEBSHELL
??? 2)上傳木馬文件冒窍,可以導(dǎo)致系統(tǒng)癱瘓
原理和方式
例如上圖递沪,我知道別人項目上傳的資源在upload下,那我上傳一個jsp或者可以操作項目的文件综液,比如一個jsp款慨,里面是刪除資源的代碼,我就可以在上傳之后谬莹,直接訪問upload里面上傳的jsp就可以執(zhí)行jsp操作完成里面的功能檩奠,甚至還有一些病毒等等
? 6.3修復(fù)方案
??? 1)對文件格式限制桩了,只允許某些格式上傳
????? 2)對文件格式進(jìn)行校驗(yàn),前端跟服務(wù)器都要進(jìn)行校驗(yàn)(前端校驗(yàn)擴(kuò)展名埠戳,服務(wù)器校驗(yàn)擴(kuò)展名井誉、Content_Type等)例如例如常見的class文件,exe文件整胃,js文件送悔,jsp文件等等都要進(jìn)行限制上傳,或者驗(yàn)證
????? 3)將上傳目錄防止到項目工程目錄之外爪模,當(dāng)做靜態(tài)資源文件路徑欠啤,并且對文件的權(quán)限進(jìn)行設(shè)定,禁止文件下的執(zhí)行權(quán)限屋灌。
另外如圖也要注意
限制
6.4限定為圖片洁段,以后可以模擬以及百度限制為其他方案
/**
????? ?*文件上傳
????? ?*/
protectedvoiddoPost(HttpServletRequest request,
? ? ? ?? HttpServletResponse response) {
??????????? Stringroot = request.getServletContext().getRealPath("/upload");
DiskFileItemFactoryfactory =newDiskFileItemFactory();
ServletFileUploadupload =newServletFileUpload(factory);
try{
????????????????? Listlist = upload.parseRequest(request);
for(FileItem? it : list) {
??????????????????????? // 如果是file文件類型
if(!it.isFormField())
? {
FileTypefileType=getFileType(it.getInputStream());
if(fileType ==null) {
??????????????????????????????????? // 非圖片格式
??????????????????????????????????? response.getWriter().write("fail");
return;
????????????????????????????? }
????????????????????????????? StringimgValue = fileType.getValue();
System.out.println("imgValue:" + imgValue);
????????????????????????????? // 是圖片格式
it.write(newFile(root + "/" + it.getName()));
????????????????????????????? response.getWriter().write("success");
??????????????????????? }
????????????????? }
}catch(Exception e) {
try{
??????????????????????? response.getWriter().write("exception");
}catch(IOException e1) {
??????????????????????? e1.printStackTrace();
????????????????? }
????????????????? e.printStackTrace();
??????????? }
????? }
????? // 判斷文件是圖片格式
publicstaticFileType getFileType(InputStream is)throwsIOException {
byte[] src =newbyte[28];
??????????? is.read(src, 0, 28);
StringBuilderstringBuilder =newStringBuilder("");
if(src ==null|| src.length <= 0)
? {
returnnull;
??????????? }
for(inti = 0; i < src.length; i++) {
intv = src[i] & 0xFF;
Stringhv= Integer.toHexString(v).toUpperCase();
if(hv.length() < 2) {
??????????????????????? stringBuilder.append(0);
????????????????? }
????????????????? stringBuilder.append(hv);
??????????? }
FileType[]fileTypes= FileType.values();
for(FileType? fileType : fileTypes) {
if(stringBuilder.toString().startsWith(fileType.getValue()))
? ? ? ? ? ? ?? {
returnfileType;
????????????????? }
??????????? }
returnnull;
????? }
7.API接口冪等性設(shè)計
?7.1什么是冪等:保證數(shù)據(jù)的唯一性袱瓮,不允許有重復(fù)
?7.2出現(xiàn)場景:例如表單重復(fù)性提交免绿,網(wǎng)絡(luò)延遲重復(fù)提交
7.3解決方案
? Token機(jī)制,防止頁面重復(fù)提交
???? 業(yè)務(wù)要求:頁面的數(shù)據(jù)只能被點(diǎn)擊提交一次
?????? 發(fā)生原因:由于重復(fù)點(diǎn)擊或者網(wǎng)絡(luò)重發(fā),或者 nginx 重發(fā)等情況會導(dǎo)致數(shù)據(jù)被重復(fù)提交
?????? 解決辦法:
????????????? 集群環(huán)境:采用 token 加 redis(redis 單線程的嘶伟,處理需要排隊)
?????????????? 單 JVM 環(huán)境:采用 token 加 redis 或token 加 jvm 內(nèi)存
????????????? 處理流程:
????????????? 數(shù)據(jù)提交前要向服務(wù)的申請token除嘹,token 放到 redis 或 jvm 內(nèi)存写半,token 有效時間
???????????????? 提交后后臺校驗(yàn) token,同時刪除 token尉咕,生成新的 token 返回
????????????? token 特點(diǎn):要申請叠蝇,一次有效性,可以限流
???????????? 基于Token方式防止API接口冪等
??????????????? 客戶端每次在調(diào)用接口的時候,需要在請求頭中年缎,傳遞令牌參數(shù)悔捶,每次令牌只能用一次。一旦使用之后单芜,就會被刪除蜕该,這樣可以有效防止重復(fù)提交。
簡單代碼洲鸠,可以自己封裝
BaseRedisService封裝Redis
???? @Component
??? publicclassBaseRedisService{
????? @Autowired
privateStringRedisTemplate stringRedisTemplate;
publicvoidsetString(String key, Object data, Long timeout) {
if(datainstanceofString) {
????????????????? Stringvalue = (String) data;
????????????????? stringRedisTemplate.opsForValue().set(key, value);
??????????? }
if(timeout !=null) {
????????????????? stringRedisTemplate.expire(key, timeout,
TimeUnit.SECONDS);
??????????? }
????? }
publicObject? getString(String key) {
returnstringRedisTemplate.opsForValue().get(key);
????? }
publicvoiddelKey(String key) {
??????????? stringRedisTemplate.delete(key);
????? }
}
RedisTokenUtils工具類
@Component
publicclassRedisTokenUtils {
privatelongtimeout = 60 * 60;
????? @Autowired
privateBaseRedisService baseRedisService;
????? // 將token存入在redis
publicStringgetToken() {
Stringtoken = "token"+ System.currentTimeMillis();
??????????? baseRedisService.setString(token, token, timeout);
returntoken;
????? }
publicbooleanfindToken(String tokenKey) {
??????????? Stringtoken = (String) baseRedisService.getString(tokenKey);
if(StringUtils.isEmpty(token)) {
returnfalse;
??????????? }
??????????? // token
? 獲取成功后 刪除對應(yīng)tokenMapstoken
??????????? baseRedisService.delKey(token);
returntrue;
????? }
}
可以在controller中調(diào)用工具類驗(yàn)證token堂淡,如果成功則進(jìn)行表單提交,提交完就刪除當(dāng)前token扒腕,當(dāng)網(wǎng)絡(luò)延遲或者重復(fù)提交表單時由于之前已經(jīng)刪除了token再去判斷此時的token值則不存在了所以就不會再次提交绢淀,這樣就保證了不會重復(fù)性提交(重點(diǎn):redis保證了安全性,單線程機(jī)制袜匿,如果網(wǎng)絡(luò)延遲還沒有執(zhí)行到刪除token值更啄,他會等待上一個提交結(jié)束后在完成下一個提交,形成隊列模式居灯,所以不用怕token沒有刪除祭务,如果確實(shí)為了以防萬一内狗,可以可方法上面添加synchronized加鎖機(jī)制)