紀錄檔案
About 25% of the activity is 200-OK大約 25% 的活動是 200-OK
我發現我的網站伺服器已經將一些日誌檔案保存了一年,有的保存了一個月。 我研究了三種類型的日誌文件,其中包含有關伺服器訪客的信息(還有其他文件似乎不太有趣)。 以下是一些典型範例:
這驗證日誌(IP 已更改)
Oct 23 06:02:24 server1 sshd[20172]: Failed password for invalid user admin from 192.168.1.1 port 64721 ssh2
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session opened for user root by (uid=0)
Oct 23 06:09:01 server1 CRON[20181]: pam_unix(cron:session): session closed for user root
Oct 23 06:10:35 server1 sshd[20195]: Did not receive identification string from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: Invalid user admin from 192.168.1.1
Oct 23 06:10:40 server1 sshd[20196]: input_userauth_request: invalid user admin [preauth]
Oct 23 06:10:41 server1 sshd[20196]: pam_unix(sshd:auth): check pass; user unknown
Web 伺服器上的授權嘗試代表登入嘗試,無論是我自己、屬於我的伺服器上的軟體(CRON,上面),還是其他人或電腦(某人嘗試使用 admin 使用者 ID,上面)。 管理員屬於「壞人」類別。
這訪問日誌(Apache 伺服器)(IP 已更改)
192.168.2.2 - - [30/Aug/2016:08:30:29 -0400] "GET / HTTP/1.1" 200 1714 "-" "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /hndUnblock.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /cgi/common.cgi HTTP/1.0" 404 496 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET /stssys.htm HTTP/1.0" 404 492 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:53 -0400] "GET / HTTP/1.0" 200 1714 "-" "Wget(linux)"
192.168.1.1 - - [30/Aug/2016:08:51:54 -0400] "POST /command.php HTTP/1.0" 404 493 "-" "Wget(linux)"
192.168.3.3 - - [30/Aug/2016:09:09:01 -0400] "GET /?feed=rss2 HTTP/1.1" 200 794 "-" "Feedly/1.0 (+http://www.feedly.com/fetcher.html; like FeedFetcher-Google)"
訪問日誌條目表示從伺服器取得網頁的嘗試。 上面的第一行代表網路爬蟲的有效請求(百度,一個中文搜尋引擎)。 get 請求針對 / 這是主頁。 200 表示頁面服務正常。 接下來的六行都有 404(找不到)結果。 這是一名駭客試圖找到配置錯誤的網路伺服器。 經過幾次嘗試後,監控軟體(Fail2Ban)注意到發生了什麼事並將他鎖在門外。 我曾經認為 Fail2Ban 非常重要(現在仍然如此!),但後來我發現了 UFW,簡單的防火牆,以及更大的威脅。
這是UFW日誌:
Oct 9 04:35:21 server1 kernel: [5110701.311961] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.9.9.9 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53848 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:24 server1 kernel: [5110704.311558] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.8.8.8 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=40 ID=53849 DF PROTO=TCP SPT=10651 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:35:36 server1 kernel: [5110715.912365] [UFW BLOCK] IN=venet0 OUT= MAC= src=112.7.7.7 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=32234 PROTO=TCP SPT=60061 DPT=23 WINDOW=16244 RES=0x00 SYN URGP=0
Oct 9 04:35:46 server1 kernel: [5110726.213736] [UFW BLOCK] IN=venet0 OUT= MAC= src=67.6.6.6 DST=192.168.1.1 LEN=44 TOS=0x00 PREC=0x40 TTL=239 ID=7084 PROTO=TCP SPT=57510 DPT=23 WINDOW=14600 RES=0x00 SYN URGP=0
Oct 9 04:37:02 server1 kernel: [5110802.146865] [UFW BLOCK] IN=venet0 OUT= MAC= src=139.5.5.5 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=39 ID=33753 PROTO=TCP SPT=6885 DPT=23 WINDOW=9693 RES=0x00 SYN URGP=0
Oct 9 04:37:53 server1 kernel: [5110853.056320] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.4.4.4 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61204 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:37:56 server1 kernel: [5110856.056659] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.3.3.3 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61205 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:38:02 server1 kernel: [5110862.056195] [UFW BLOCK] IN=venet0 OUT= MAC= src=87.2.2.2 DST=192.168.1.1 LEN=60 TOS=0x00 PREC=0x00 TTL=54 ID=61206 DF PROTO=TCP SPT=47013 DPT=23 WINDOW=5808 RES=0x00 SYN URGP=0
Oct 9 04:39:04 server1 kernel: [5110924.610656] [UFW BLOCK] IN=venet0 OUT= MAC= src=175.1.1.1 DST=192.168.1.1 LEN=40 TOS=0x00 PREC=0x00 TTL=43 ID=16953 PROTO=TCP SPT=35941 DPT=23 WINDOW=41293 RES=0x00 SYN URGP=0
UFW BLOCK 行的每一行都代表對伺服器的另一種攻擊:尋找配置錯誤的連接埠。 所有這些行都在測試 DPT=23,即遠端登入,一種古老的協議。 請注意,這種情況至少每分鐘發生一次。 整天。 每天。
將資料載入到資料表中
每個文件的格式不同,日期可能不包含當前年份,欄位可能具有名稱=值或只是位置。 我將所有檔案從 Linux 伺服器移至 Windows 計算機,並使用 FilesInDirectory 取得 JSL 中的檔案名稱清單。 然後我編寫了一組模式來有效地解析這三種類型的檔案。 選擇資料表列來表示我想要從每個文件中捕獲的資料:
Columns in table表中的列
ipaddr32 是一個公式列,用於將 1.2.3.4 轉換為圖形上連續軸的 1<<24 + 2<<16 + 3<<8 + 4。稍後將查找 ipname。 kind2 是一個將所有不同的使用者 ID 簡化為「登入」的公式。
path = "f:/logs/";
list = Files In Directory( path, "recursive" );
global:dt = New Table( "logData",
New Column( "datetime", Numeric, "Continuous", Format( "ddMonyyyy:h:m:s", 18, 0 ), Input Format( "ddMonyyyy:h:m:s", 0 )),
New Column( "ipaddr", Character, "Nominal" ),
New Column( "kind", Character, "Nominal" ),
New Column( "detail1", Character, "Nominal" ),
New Column( "detail2", Character, "Nominal" )
);
高效解析
為了獲得大檔案的最大速度,JSL 解析需要在單一 PatMatch 函數呼叫中完成。 每次調用 PatMatch 都會產生一些開銷,如果您進行多次調用,那麼您也可能會在調用時切割輸入字串,這會增加更多開銷。 因此,讓每個日誌檔案使用一個 PatMatch 來完成此操作。 鍵是兩個模式匹配函數:PatRepeat 和 PatTest。 PatRepeat 將使文件中的每一行重複該模式。 PatTest 會讓模式在比賽期間運行一些 JSL(名義上是為了測試條件,但我們的測試結果將始終為「true」)。 一些輔助模式,然後進入好東西...
ipPattern = patRegex("(\d{1,3}[-.]\d{1,3}[-.]\d{1,3}[-.]\d{1,3})|([a-fA-F0-9:]+)"); // approximation
ipMonth=patRegex("Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec");
datePattern1 = "[" + patregex("\d{2}")>>day + "/" + ipMonth>>month + "/" + patregex("\d{4}")>>year + ":" + patregex("\d\d:\d\d:\d\d")>>time + patregex(" [-+]\d{4}") +"]"; // [18/Sep/2016:06:14:25 -0400]
datePattern2 = ipMonth>>month + patspan(" ") + patregex("\d{1,2}")>>day + " " + patregex("\d\d:\d\d:\d\d")>>time + pattest(year="2016";1); //vs Oct 16 04:54:31 the unknown year is 2016 for these logs
quote = "\!"";
quotepattern = quote + patrepeat(patbreak(quote||"\") +(("\"+(quote|""))|"")) + quote; // allows \" escaped embedded quotation marks
兩個日期模式與兩種日期格式相符。 >> 運算子將左側符合的文字放入右側的變數中。 PatTest(year="2016";1) 在將 2016 分配給年份後始終傳回 true;這是針對沒有明確年份的日誌檔案。 我使用模式和正規表示式的混合搭配來建立越來越大的模式。 這是 Apache access.log 模式:
apachePat = ipPattern>>ip+" "+patbreak(" ")+" "+patbreak(" ")+" "
+datePattern1+" "
+quotePattern>>request+" "
+patbreak(" ")>>code+" "
+patbreak(" ")>>length+" "+patbreak(" ")+" "
+(quotePattern|patbreak("\!n\!r"))>>browser
+pattest(
dt1<<ADDROWS></ADDROWS>
將其作用與 access.log 中的一行進行比較
192.168.1.1 - - [30/Aug/2016:08:51:52 -0400] "GET /tmUnblock.cgi HTTP/1.0" 404 495 "-" "Wget(linux)"
並注意最後的 pattest(...) ;它會向表 dt1 新增一行,並使用剛剛解析的值填入列。
還有 UFW 和 auth 模式。 這是解析文件的函數:
global:skipPattern = (patbreak("\!n\!r") + patlen(1))>> unknown + pattest(show(filename,unknown);stop();1);
global:whitespace = patregex("\s*");
parser = Function( {filename, pattern, dt1}, {Default Local},
txt = Load Text File( filename );
rc = Pat Match( //
txt, //
Pat Pos( 0 ) //
+ Pat Repeat( ((global:whitespace + pattern + global:whitespace) | global:skipPattern) + Pat Fence() ) //
+ Pat R Pos( 0 ) //
); //
);
該函數從檔案名稱載入日誌並使用模式參數對其進行解析並將結果儲存在 dt1 中。 PatMatch 函數建立一個交替模式,允許跳過無法辨識的行。 PatFence() 是另一種針對大文件的最佳化;這意味著“如果你已經走到這一步,就沒有必要備份並嘗試不同的東西”,它既可以加快比賽速度,又可以減少所需的內存。 最後,這是該函數的驅動程式:
While( N Items( file = Remove From( list, 1 ) ) == 1, //
file = file[1];//
If(//
!Is Missing( Regex( file, "ssl_access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "other_vhosts_access.log" ) ), //
0//parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "access.log" ) ), //
parser( path || file, apachePat, global:dt );//
, // else
!Is Missing( Regex( file, "ufw.log" ) ),
parser( path || file, ufwPat, global:dt );//
, // else
!Is Missing( Regex( file, "auth.log" ) ), //
parser( path || file, authPat, global:dt );//
);//
);//
興趣點
Raspberry PI 電腦似乎吸引了大量使用使用者名稱 PI 的攻擊。 PHP 腳本肯定經常被錯誤配置;對於某些 PHP“管理”文件有很多檢查。 找到一個有弱點的開放連接埠一定非常有價值;絕大多數攻擊都是測試連接埠。 如果您管理 Web 伺服器並且不使用fail2ban 和防火牆規則(如 UFW),則應考慮安裝和設定它們。 您可以透過每天允許嘗試幾次而不是每秒嘗試多次來減慢暴力攻擊的速度。
Dashboard view of web traffic網路流量的儀表板視圖