在現今網路環境中,主動監控系統日誌並即時偵測入侵行為至關重要。本文介紹如何結合 tail、egrep 等指令,搭配自定義的入侵指標(IOCs)檔案,建立輕量級的入侵檢測系統。除了 Linux 系統的日誌監控,也涵蓋 Windows 系統的日誌監控方法,並提供 Shell 指令碼範例,示範如何模擬 tail -f 功能。此外,文章也說明瞭如何產生即時直方圖,將日誌活動視覺化,更直觀地掌握系統狀態。更進一步,我們將探討如何開發網路服務變更偵測工具,監控系統開放連線埠的變化,並結合排程任務實作自動化監控和郵件通知,提升資安防護的效率。
即時日誌監控與入侵檢測系統
在資安領域中,日誌監控是一項至關重要的任務。透過監視系統或應用程式的日誌,可以即時發現潛在的安全威脅或異常行為。本文將介紹如何利用 tail 和 egrep 指令來建立一個輕量級的入侵檢測系統(IDS),並進一步探討如何在 Windows 環境中監控日誌以及如何產生即時直方圖。
根據日誌的入侵檢測
要建立一個根據日誌的入侵檢測系統,首先需要定義一些已知的安全威脅模式,也就是所謂的「入侵指標」(Indicators of Compromise, IOCs)。這些 IOCs 可以是特定的字串或正規表示式,用於匹配日誌中的可疑活動。
建立 IOCs 檔案
首先,建立一個名為 ioc.txt 的檔案,並在其中加入已知的 IOCs,例如:
\.\./
etc/passwd
etc/shadow
cmd\.exe
/bin/sh
/bin/bash
這些模式對應不同的安全威脅,例如目錄遍歷攻擊、未授權存取敏感檔案、反向 Shell 等。
使用 tail 和 egrep 監控日誌
接下來,可以使用以下指令來監控 Apache2 的存取日誌,並輸出匹配 IOCs 的日誌條目:
tail -f /var/logs/apache2/access.log | egrep -i -f ioc.txt
若要同時將匹配結果輸出到螢幕和儲存到檔案中,可以使用 tee 指令:
tail -f /var/logs/apache2/access.log | egrep --line-buffered -i -f ioc.txt | tee -a interesting.txt
監控 Windows 日誌
在 Windows 環境中,可以使用 wevtutil 指令來存取 Windows 事件日誌。然而,wevtutil 並沒有像 tail 一樣的功能來即時監控日誌。因此,需要撰寫一個簡單的 bash 指令碼來模擬 tail 的功能。
wintail.sh 指令碼
#!/bin/bash -
WINLOG="Application"
LASTLOG=$(wevtutil qe "$WINLOG" //c:1 //rd:true //f:text)
while true
do
CURRENTLOG=$(wevtutil qe "$WINLOG" //c:1 //rd:true //f:text)
if [[ "$CURRENTLOG" != "$LASTLOG" ]]
then
echo "$CURRENTLOG"
echo "
---
-
---
-
---
-
---
-
---
-
---
-
---
-
---
---
"
LASTLOG="$CURRENTLOG"
fi
done
這個指令碼會不斷檢查指定的 Windows 日誌是否有新的條目,並將新的條目輸出到螢幕上。
產生即時直方圖
若要計算一段時間內新增的日誌條目數量,可以結合 tail -f 和訊號(signal)機制來實作。
使用訊號進行程式間通訊
首先,需要定義兩個指令碼:一個用於計數日誌條目,另一個用於定時傳送訊號。
looper.sh 指令碼
#!/bin/bash -
trap 'echo "Count: $COUNT"; COUNT=0' SIGUSR1
COUNT=0
tail -f "$1" | while read line
do
((COUNT++))
done
這個指令碼會對輸入的日誌檔案進行計數,並在接收到 SIGUSR1 訊號時輸出計數結果。
使用訊號通知計數結果
另一個指令碼可以用來定時傳送 SIGUSR1 訊號給 looper.sh 指令碼,以觸發計數結果的輸出。
動態監控日誌檔案更新的 Shell 指令碼實作
在資安維運與系統監控領域,實時監控日誌檔案的更新對於及時發現系統異常至關重要。本文將深入解析一個利用 Bash Shell 實作的日誌檔案監控指令碼,並詳細闡述其設計思路、技術細節及應用場景。
實作原理與指令碼架構
該監控指令碼主要由兩個部分組成:looper.sh 和 tailcount.sh。looper.sh 負責持續監控指定的日誌檔案,並統計單位時間內的日誌行數;tailcount.sh 則控制 looper.sh 的執行,並定期傳送訊號使其匯報統計結果。
looper.sh:日誌監控與統計指令碼
#!/bin/bash -
# 定義 interval 函式,用於匯報統計結果
function interval() {
echo $(date '+%y%m%d %H%M%S') $cnt
cnt=0
}
declare -i cnt=0
trap interval SIGUSR1
shopt -s lastpipe
# 持續監控日誌檔案更新
tail -f --pid=$$ ${1:-log.file} | while read aline; do
let cnt++
done
內容解密:
interval函式:當接收到SIGUSR1訊號時被呼叫,輸出當前時間戳和已統計的日誌行數$cnt,然後重置$cnt為 0。trap interval SIGUSR1:設定當接收到SIGUSR1訊號時,執行interval函式。shopt -s lastpipe:啟用lastpipe選項,使管道中的最後一個命令在當前 Shell 行程中執行,而非子 Shell。這樣可以確保$cnt的值在主行程中被更新。tail -f --pid=$$ ${1:-log.file}:持續監控指定的日誌檔案(預設為log.file)。當當前 Shell 行程結束時,tail命令也會終止。
tailcount.sh:控制指令碼
#!/bin/bash -
# 清理函式,用於結束背景行程
function cleanup() {
[[ -n $LOPID ]] && kill $LOPID
}
trap cleanup EXIT
# 在背景執行 looper.sh
bash looper.sh $1 &
LOPID=$!
# 等待 looper.sh 初始化
sleep 3
# 每隔 5 秒傳送 SIGUSR1 訊號給 looper.sh
while true; do
kill -SIGUSR1 $LOPID
sleep 5
done >&2
內容解密:
cleanup函式:當tailcount.sh結束時,傳送SIGTERM訊號給looper.sh的行程,以清理背景行程。bash looper.sh $1 &:在背景啟動looper.sh,並傳遞檔名引數。while true迴圈:每隔 5 秒向looper.sh傳送SIGUSR1訊號,使其匯報統計結果。
livebar.sh:動態水平條形圖生成指令碼
#!/bin/bash -
function pr_bar() {
local raw maxraw scaled
raw=$1
maxraw=$2
((scaled = (maxbar * raw) / maxraw))
((scaled == 0)) && scaled = 1 # 保證最小長度
for ((i = 0; i < scaled; i++)); do
printf '#'
done
printf '\n'
}
maxbar = 60 # 最大條形長度
MAX = 60
while read dayst timst qty; do
if ((qty > MAX)); then
let MAX = $qty + $qty / 4 # 調整最大刻度
echo " **** rescaling: MAX=$MAX"
fi
printf '%6.6s %6.6s %4d:' $dayst $timst $qty
pr_bar $qty $MAX
done
內容解密:
pr_bar函式:根據輸入值和最大刻度,列印對應長度的#條形。- 動態調整最大刻度:當輸入值超過當前最大刻度時,自動調整最大刻度並重新縮放條形。
使用方法與應用場景
- 啟動監控:執行
bash tailcount.sh | bash livebar.sh,即可啟動日誌監控並動態顯示統計結果的水平條形圖。 - 應用場景:此指令碼組合可用於實時監控系統日誌、網路流量或其他需要動態統計的場景,幫助維運人員快速掌握系統狀態。
網路監控工具:偵測網路服務變更
在網路安全領域中,早期偵測敵對活動是關鍵。監控網路中新或未預期的網路服務(即開放的連線埠)是一種有效的偵測技術。這可以完全透過命令列實作。
建立網路監控工具
本章節中,我們將建立一個工具來監控網路中系統開放連線埠的變化。該工具的需求如下:
- 讀取包含 IP 位址或主機名稱的檔案
- 對檔案中的每個主機進行網路連線埠掃描,以確定開放的連線埠
- 將連線埠掃描的輸出儲存到以目前日期命名的檔案中
- 當指令碼再次執行時,將進行連線埠掃描,然後將結果與上次儲存的結果進行比較,並將任何變更顯示在螢幕上
- 自動化指令碼以每天執行一次,如果發生任何變更,則向系統管理員傳送電子郵件
使用的命令
本章節中,我們介紹 crontab 和 schtasks 命令。
crontab
crontab 命令允許您編輯 Linux 系統上的 cron 表。cron 表用於排程任務以在特定時間或間隔執行命令。
常見的命令選項:
-e:編輯 cron 表-l:列出目前的 cron 表-r:刪除目前的 cron 表
schtasks
schtasks 命令允許您在 Windows 環境中排程任務以在特定時間或間隔執行命令。
常見的命令選項:
/Create:排程新的任務/Delete:刪除排程的任務/Query:列出所有排程的任務
步驟 1:建立連線埠掃描器
建立連線埠掃描器的第一步是讀取包含 IP 位址或主機名稱的檔案。對於檔案中的每個主機,您將嘗試連線到主機上的連線埠範圍。如果連線成功,您就知道該連線埠是開放的。
範例 9-1:scan.sh
#!/bin/bash -
# 網路安全操作與 bash
# scan.sh
# 描述:
# 對指定的主機進行連線埠掃描
# 用法:./scan.sh <輸出檔案>
# <輸出檔案> 儲存結果的檔案
function scan() {
host=$1
printf '%s' "$host"
for ((port=1; port<1024; port++)) {
# 重定向的順序很重要,有兩個原因
echo >/dev/null 2>&1 < /dev/tcp/${host}/${port}
if (($? == 0)); then printf ' %d' "${port}"; fi
}
echo # 或 printf '\n'
}
# 主迴圈
# 從標準輸入讀取每個主機名稱
# 並掃描開放的連線埠
# 將結果儲存到檔案中
# 其名稱作為引數提供
# 或預設為根據今天日期的名稱
printf -v TODAY 'scan_%(%F)T' -1 # 例如,scan_2017-11-27
OUTFILE=${1:-$TODAY}
while read HOSTNAME; do
scan $HOSTNAME
done > "$OUTFILE"
內容解密:
function scan()定義了一個名為scan的函式,用於對指定的主機進行連線埠掃描。for ((port=1; port<1024; port++))迴圈遍歷從 1 到 1023 的連線埠號。echo >/dev/null 2>&1 < /dev/tcp/${host}/${port}試圖建立到指定主機和連線埠的 TCP 連線。如果連線成功,則該連線埠是開放的。if (($? == 0)); then printf ' %d' "${port}"; fi如果連線成功(傳回狀態為 0),則輸出開放的連線埠號。while read HOSTNAME; do scan $HOSTNAME; done > "$OUTFILE"從標準輸入讀取主機名稱,對每個主機進行連線埠掃描,並將結果儲存到指定的輸出檔案中。
本章節介紹瞭如何使用 bash 指令碼建立一個簡單的網路監控工具,用於偵測網路服務的變更。透過結合 crontab 或 schtasks 命令,可以實作自動化的網路監控和變更通知。指令碼首先讀取包含 IP 位址或主機名稱的檔案,然後對每個主機進行連線埠掃描,將結果儲存到檔案中,並與之前的結果進行比較,以檢測任何變更。
網路掃描與比較工具的實作細節
網路連線測試的關鍵步驟
在網路掃描工具的實作中,實際建立網路連線是至關重要的步驟。以下程式碼片段展示瞭如何使用bash shell實作對特定主機和埠的連線測試:
echo >/dev/null 2>&1 < /dev/tcp/${host}/${port}
內容解密:
- 重定向操作:這行程式碼利用了bash的特殊檔案名稱
/dev/tcp/host/port來嘗試建立網路連線。 - 輸入重定向:
< /dev/tcp/${host}/${port}將標準輸入重定向到指定的網路連線。 - 輸出丟棄:
>/dev/null 2>&1將標準輸出和標準錯誤輸出都重定向到/dev/null,有效地丟棄了輸出結果。 - 邏輯判斷:
echo命令本身不讀取輸入,但嘗試開啟指定的網路檔案。如果成功,表示連線建立;否則,表示連線失敗。
日期與輸出檔名的處理
在掃描工具中,使用printf函式來格式化輸出日期和時間,並將結果儲存於變數中,以作為預設的輸出檔名。
TODAY=$(printf "%(%F)T" -1)
內容解密:
printf格式控制:%(%F)T指定了輸出的日期格式為ISO 8601(年-月-日)。-1引數:表示使用目前的時間作為輸出值。- 變數儲存:將格式化後的日期字串儲存於
TODAY變數中,用於後續的檔名生成。
掃描結果的比較邏輯
比較兩個掃描結果檔案,以找出主機開放埠的變化,是檢測網路變化的關鍵步驟。
while true; do
read aline <&4 || break
read bline <&5 || break
# 比較alog與bline的內容
done 4< ${1:-day1.data} 5< ${2:-day2.data}
內容解密:
- 檔案描述符的使用:使用檔案描述符4和5來同時讀取兩個檔案。
read命令:從指定的檔案描述符讀取一行內容,若到達檔案結尾則傳回錯誤並跳出迴圈。- 比較邏輯:對比兩行內容,若不同則進一步解析埠變化。
埠變化檢測的實作
在比較邏輯中,進一步解析主機和埠資訊,以檢測埠的開啟或關閉狀態。
HOSTA=${aline%% *}
PORTSA=( ${aline#* } )
HOSTB=${bline%% *}
PORTSB=( ${bline#* } )
for porta in ${PORTSA[@]}; do
LOOKFOR=$porta NotInList ${PORTSB[@]} && echo " closed: $porta"
done
for portb in ${PORTSB[@]}; do
LOOKFOR=$portb NotInList ${PORTSA[@]} && echo " new: $portb"
done
內容解密:
- 主機與埠的解析:使用引數擴充套件來提取主機名稱和埠列表。
NotInList函式呼叫:檢查某個埠是否出現在對方的列表中,若不存在則輸出相應的狀態變化訊息。
網路監控工具的自動化與排程
在前面的章節中,我們介紹了一個用於監控網路變化的指令碼工具。為了提高該工具的實用性,我們將進一步探討如何實作自動化執行以及如何設定排程任務,以便定期執行指令碼並在發現變化時通知使用者。
自動化執行與通知
手動執行指令碼雖然可行,但更理想的方式是能夠定期自動執行並在檢測到變化時通知使用者。autoscan.sh 指令碼結合了 scan.sh 和 fd2.sh,能夠掃描網路並輸出變化。
autoscan.sh 指令碼解析
#!/bin/bash -
# 網路安全營運使用 bash
# autoscan.sh
# 描述:
# 自動執行埠掃描(使用 scan.sh),
# 比較輸出與之前的結果,並透過電子郵件通知使用者
# 假設 scan.sh 位於當前目錄。
# 用法:./autoscan.sh
./scan.sh < hostlist
FILELIST=$(ls scan_* | tail -2)
FILES=( $FILELIST )
TMPFILE=$(tempfile)
./fd2.sh ${FILES[0]} ${FILES[1]} > $TMPFILE
if [[ -s $TMPFILE ]] # 非空
then
echo "郵寄今天的埠差異到 $USER"
mail -s "今天的埠差異" $USER < $TMPFILE
fi
# 清理
rm -f $TMPFILE
#### 內容解密:
./scan.sh < hostlist:執行scan.sh指令碼並從hostlist檔案中讀取主機列表進行掃描。FILELIST=$(ls scan_* | tail -2):列出所有以scan_開頭的檔案,並取得最新的兩個檔名稱。FILES=( $FILELIST ):將檔案列表轉換為陣列,方便後續操作。TMPFILE=$(tempfile):建立一個臨時檔案,用於存放比較結果。./fd2.sh ${FILES[0]} ${FILES[1]} > $TMPFILE:比較最新的兩個掃描結果,並將差異輸出到臨時檔案中。if [[ -s $TMPFILE ]]:檢查臨時檔案是否非空,如果非空,表示有變化。mail -s "今天的埠差異" $USER < $TMPFILE:將變化內容透過電子郵件傳送給使用者。
在 Linux 中排程任務
要在 Linux 中排程任務,首先列出現有的 cron 檔案:
$ crontab -l
no crontab for paul
然後,使用 -e 選項建立和編輯新的 cron 檔案:
$ crontab -e
在 cron 檔案中新增一行,使 autoscan.sh 每天早上 8:00 執行:
0 8 * * * /home/paul/autoscan.sh
#### 內容解密:
0 8 * * *指定了執行時間為每天的 8:00 AM。/home/paul/autoscan.sh是要執行的指令碼路徑。
在 Windows 中排程任務
要在 Windows 中排程任務,需要透過 schtasks 命令來實作。由於 autoscan.sh 是 Bash 指令碼,需要透過 Git Bash 來執行:
schtasks //Create //TN "網路掃描器" //SC DAILY //ST 08:00 //TR "C:\Users\Paul\AppData\Local\Programs\Git\git-bash.exe C:\Users\Paul\autoscan.sh"
#### 內容解密:
//Create表示建立一個新的任務。//TN "網路掃描器"指定任務名稱。//SC DAILY設定排程頻率為每天。//ST 08:00指定開始時間為早上 8:00。//TR後面跟著要執行的命令和指令碼路徑。