Malware

如何獲取有關最近一次惡意軟體掃描的電子郵件報告?

  • December 24, 2019

maldet / Rfxn Linux MalDetect 文件為獲取電子郵件報告提供了此功能,即使沒有發現任何內容:

-e, --report SCANID email
   View scan report of most recent scan or of a specific SCANID and optionally
   e-mail the report to a supplied e-mail address
   e.g: maldet --report
   e.g: maldet --report list
   e.g: maldet --report 050910-1534.21135
   e.g: maldet --report SCANID user@domain.com

一切都非常簡單,但我不確定如何在此處將電子郵件地址作為第二個參數傳遞,同時允許第一個參數(掃描 ID)回退到其預設值,以便 maldet 將最新報告的任何內容髮送給此自定義電子郵件地址。我希望能夠使用它(例如在 cron 中)定期檢查 Maldet 是否正在掃描並能夠按預期發送電子郵件報告。

我已經嘗試maldet --report "" user@domain.com基於在 bash 中傳遞空變數的標準方法,但它會忽略它並將看起來像空報告的內容輸出到控制台中。

我也嘗試過類似的東西maldet --report 0 user@domain.commaldet --report " " user@domain.com但它會響應{report} no report found, aborting

如果相關,環境是 Centos。

要麼的作者maldet沒有提供這種可能性,要麼忽略了記錄它。從外面是不可能猜到的。最好的方法是UTSL:在程序原始碼中查找它如何處理-e選項以及是否有辦法啟動“最近掃描”分支並同時啟動電子郵件選項。

很抱歉復活了一個老問題。我在每次掃描後嘗試讓 maldet 通過電子郵件發送報告時遇到了同樣的問題。我按照@Tilman 的建議深入研究了原始碼。負責發送報告郵件的函式 view_report() 可以在/usr/local/maldetect/internals/functionsv1.6.4 的第 645-706 行找到。具體查看負責的程式碼(第 681-696 行),我們看到只有在儲存為 的 SCANID$rid是後綴時才會發送郵件,即190429-0343.31494,對應於報告的文件/usr/local/maldetect/sess/session.190429-0343.31494

if [ -f "$sessdir/session.$rid" ] && [ ! -z "$(echo $2 | grep '\@')" ]; then
   if [ -f "$mail" ]; then
       cat $sessdir/session.$rid | $mail -s "$email_subj" "$2"
   elif [ -f "$sendmail" ]; then
       if ! grep -q "SUBJECT: " "$sessdir/session.$rid"; then
           echo -e "SUBJECT: $email_subj\n$(cat $sessdir/session.$rid)" > $sessdir/session.$rid
       fi
       cat $sessdir/session.$rid | $sendmail -t "$2"
   else
       eout "{scan} no \$mail or \$sendmail binaries found, e-mail alerts disabled."
       exit
   fi

   eout "{report} report ID $rid sent to $2" 1
   exit
fi

處理空 SCANID 的程式碼緊隨其後(第 697-705 行):

if [ "$rid" == "" ] && [ -f "$sessdir/session.last" ]; then
   rid=`cat $sessdir/session.last`
   $EDITOR $sessdir/session.$rid
elif [ -f "$sessdir/session.$rid" ]; then
   $EDITOR $sessdir/session.$rid
else
   echo "{report} no report found, aborting."
   exit
fi

我原以為處理空 SCANID 的程式碼會簡單地抓取最新的並通過電子郵件發送。它實際上所做的是查看/usr/local/maldetect/sess/session.lastmaldet 儲存最新SCANID 的位置。並且由於某種原因,它會在終端編輯器中打開相應的報告,而不僅僅是列印出來。請注意,實際上沒有任何工作程式碼可以通過電子郵件發送最新報告。

– 更新修復 - 2019 年 5 月 5 日–

由於阻止 LMD 執行我最初修復中要求的完整性檢查是一個潛在的安全風險,因此我使用 LMD 的 custom.cron 創建了一個替代解決方案。好處是完整性檢查仍然存在,並且電子郵件腳本應該通過更新保持不變。您無需接觸 LMD 內部文件或 maldet 每日 cron。

確保$email_alert="1"$email_addr=設置為至少一個正確的電子郵件地址/usr/local/maldetect/conf.maldet。然後添加以下內容/usr/local/maldetect/cron/custom.cron,它將在 maldet 每日 cron 結束時自動執行:

##
# Please use this file for preservation of custom LMD execution code for the daily cronjob.
# NOTE: scripts in this file are called at the end of maldet daily cron as $custom_cron_exec
##

# log_cron="1" enable logging, log_cron="0" disable logging 
# applies only to the code in this file
log_cron="1"

# logging function borrowed from /maldetect/internals/functions
eout() {
   if [ "$log_cron" == "1" ]; then
       msg="$1"
       stdout="$2"
       appn=maldet
       if [ ! -d "$logdir" ]; then
           mkdir -p $logdir ; chmod 700 $logdir
       fi
       if [ ! -f "$maldet_log" ]; then
           touch $maldet_log
       fi
       log_size=`$wc -l $maldet_log | awk '{print$1}'`
       if [ "$log_size" -ge "20000" ]; then
           trim=1000
           printf "%s\n" "$trim,${log_size}d" w | ed -s $maldet_log 2> /dev/null
       fi
       if [ ! "$msg" == "" ]; then
           echo "$(date +"%b %d %H:%M:%S") $(hostname -s) $appn($$): $msg" >> $maldet_log
           if [ ! -z "$stdout" ]; then
               echo "$appn($$): $msg"
           fi
       fi
   fi
}

eout "{cron} running $cron_custom_exec"

##
# LMD Daily Email v1.0.0
# Author: kdub Email: kdubdev@gmail.com Date: May 5th, 2019
# https://github.com/kdubdev/linux-malware-detect/blob/master/files/cron/custom.cron
# Script to send email of newest report after daily scan. More info:
# https://serverfault.com/questions/805158/how-to-get-an-email-report-of-whatever-the-most-recent-maldet-scan-is
# #
de_version='v1.0.0'
eout "{cron} starting LMD Cron Email $de_version"
eout "{cron} $intcnf shows email_alert=$email_alert email_addr=$email_addr"

# Default email subject defined in /usr/local/maldetect/internals/internals.conf
# is email_subj="maldet alert from $(hostname)"
# comment this line to use the default email_subj or change to what you want
printf -v email_subj '[%s] %s: Scan Report' "$(hostname)" "$appn($$)"

# uncomment email_addr below to override recipients. Separate multiple emails with ,
# use $email_addr to include recipient defined in /usr/local/maldetect/conf.maldet
# email_addr="$email_addr,second@domain.tld,third@domain.tld"

# this is the email text inserted before the report
body_intro="Here are the results of the latest LMD scan:"
# this is the email text inserted after the report
printf -v body_footer "Email provided by LMD Cron Email %s\nCron file: %s\nLog file: %s" "$de_version" "$cron_custom_exec" "$maldet_log"

# this is a very weak email validation, just looking for @
if [ "$email_alert" == "1" ] && [ ! -z "$(echo $email_addr | grep '\@')" ]; then
# email_alert is true and email provided, send newest report
   if [ -f "$sessdir/session.last" ]; then    
       # Get most recent scan id
       rid=$(cat "$sessdir/session.last")
       if [ ! -z "$rid" ]; then
           # session.list contains something
           if [ -f "$sessdir/session.$rid" ]; then
               # report exists, get contents
               body=$(cat "$sessdir/session.$rid")
               eout "{cron} reading report $sessdir/session.$rid"
           else
               # report doesn't exist   
               body="{cron} unable to find report $sessdir/session.$rid."
           fi
           if [ -z "$body" ]; then
               # report file exists but is empty
               body="{cron} report $sessdir/session.$rid is empty."
           fi          
       else
           # session.last is empty  
           body="{cron} $sessdir/session.last is empty."
       fi
   else    
       # session.last doesn't exist
       body="{cron} unable to find $sessdir/session.last."
   fi
   # log if body starts with {cron} ie there's a problem reading report
   if [[ $body == '{cron}'* ]]; then
       eout "$body"
   fi

   # add intro and footer to body
   body=$(printf "%s\n\n%s\n\n%s\n\n" "$body_intro" "$body" "$body_footer")

   if [ -f "$mail" ]; then
       printf "%s" "$body" | $mail -s "$email_subj" "$email_addr"
       eout "{cron} mail sent using $mail to $email_addr, subject: $email_subj."
   elif [ -f "$sendmail" ]; then
       printf "%s\n%s" "$email_subj" "$body" | $sendmail -t "$email_addr"
       eout "{cron} mail sent using $sendmail to $email_addr, subject: $email_subj."
   fi
fi
eout "{cron} mail latest report finished."
eout "{cron} done running $cron_custom_exec"

您也可以在此處檢查更新https://github.com/kdubdev/linux-malware-detect/blob/master/files/cron/custom.cron

在腳本中,您可以禁用日誌記錄、覆蓋電子郵件主題和/或收件人,以及自定義電子郵件正文介紹和頁腳。該腳本有大量註釋,因此您可以跟進或進行更改。

我歡迎任何回饋或改進建議。

– 下面的原始修復 –

為了解決這個問題並添加其他改進,我修改了 view_report() 並進行了以下更改:

  • 添加選項“最新”作為別名--report--report ""允許$ maldet --report newest user@domain.com
  • 使用時正確通過電子郵件發送最新報告$ maldet --report newest user@domain.com$ maldet --report "" user@domain.com
  • 從不必要地使用編輯器來查看報告,而不是簡單地列印到終端
  • 改進的日誌記錄

**首先:**您需要設置autoupdate_version_hashed="0"/usr/local/maldetect/conf.maldet防止 LMD 在執行更新檢查時自動覆蓋您所做的任何更改。請注意,這是一個潛在的安全問題:

# This controls validating the LMD executable MD5 hash with known
# good upstream hash value. This allows LMD to replace the the
# executable / force a reinstallation in the event the LMD executable
# is tampered with or corrupted. If you intend to make customizations
# to the LMD executable, you should disable this feature.
# [0 = disabled, 1 = enabled]
autoupdate_version_hashed="0"

**第二:**將您的目前view_report() /usr/local/maldetect/internals/functions(第 645-706 行)替換為:

view_report() {
   # $1 is first arg passed from command line ex. $ maldet --report $1 $2
   rid="$1"
   # $ maldet --report list
   if [ "$rid" == "list" ]; then
       tmpf="$tmpdir/.areps$$"
       for file in `ls $sessdir/session.[0-9]* 2> /dev/null`; do
           SCANID=`cat $file | grep "SCAN ID" | sed 's/SCAN ID/SCANID/'`
           FILES=`cat $file | grep "TOTAL FILES" | sed 's/TOTAL //'`
           HITS=`cat $file | grep "TOTAL HITS" | sed 's/TOTAL //'`
           CLEAN=`cat $file | grep "TOTAL CLEANED" | sed 's/TOTAL //'`
           TIME=`cat $file | grep -E "^TIME|^STARTED" | sed -e 's/TIME: //' -e 's/STARTED: //' | awk '{print$1,$2,$3,$4}'`
           TIME_U=`date -d "$TIME" "+%s" 2> /dev/null`
                       ETIME=`cat $file | grep "ELAPSED" | awk '{print$1,$2}' | sed 's/ELAPSED/RUNTIME/'`
           if [ -z "$ETIME" ]; then
               ETIME="RUNTIME: unknown"
           fi
           if [ ! -z "$SCANID" ] && [ ! -z "$TIME" ]; then
               clean_zero=`echo $CLEAN | awk '{print$2}'`
               if [ -z "$clean_zero" ]; then
                   CLEAN="CLEANED:  0"
               fi
               echo "$TIME_U | $TIME | $SCANID | $ETIME | $FILES | $HITS | $CLEAN" >> $tmpf
           fi
       done
       if [ -f "$tmpf" ]; then
           if [ "$OSTYPE" == "FreeBSD" ]; then
               cat $tmpf | sort -k1 -n | cut -d'|' -f2-7 | column -t | more
           else
               cat $tmpf | sort -k1 -n | tac | cut -d'|' -f2-7 | column -t | more
           fi
           rm -f $tmpf 2> /dev/null
           exit 0
       else
           eout  "{list} unable to find report data for list, check \$sessdir"
           exit 1
       fi
   fi
   # If no SCANID is provided or "recent" then set $rid to most recent. 
   # $ maldet --report "" or $maldet --report newest
   if { [ "$rid" == "" ] || [ "$rid" == "newest" ]; } && [ -f "$sessdir/session.last" ]; then
       rid=`cat $sessdir/session.last`
   fi
   # make sure report exists
   if [ -f "$sessdir/session.$rid" ]; then
       # if email is provided, then send the report and exit
       if [ ! -z "$(echo $2 | grep '\@')" ]; then
           if [ -f "$mail" ]; then
               cat $sessdir/session.$rid | $mail -s "$email_subj" "$2"
           elif [ -f "$sendmail" ]; then
               if ! grep -q "SUBJECT: " "$sessdir/session.$rid"; then
                   echo -e "SUBJECT: $email_subj\n$(cat $sessdir/session.$rid)" > $sessdir/session.$rid
               fi
               cat $sessdir/session.$rid | $sendmail -t "$2"
           else
               # eout is an internal function to log to maldet_log and echo
               eout "{scan} no \$mail or \$sendmail binaries found, e-mail alerts disabled."
               exit
           fi
           eout "{report} report ID $rid sent to $2" 1
           exit        
       # no email is provided so show report and exit
       else
           printf '%b\n' "$(cat $sessdir/session.$rid)"
           exit
       fi
   # can't find requested report so log & echo error
   else
       eout "{report} unable to find report session.\$rid, aborting."
       exit
   fi
}

/usr/local/maldetect/internals/functions您也可以在此處的拉取請求中找到整個更新的文件: https ://github.com/kdubdev/linux-malware-detect/blob/patch-1/files/internals/functions

最後:/etc/cron.daily/maldet如果您希望在每次每日掃描後收到電子郵件 ,請將 以下行添加到末尾:$inspath/maldet --report newest user@domain.com

注意:如果不清楚,您可以使用-e--report互換。

引用自:https://serverfault.com/questions/805158