Providers/Modules/Plugins/Antimalware/plugin/collectsophosinfo.rb (239 lines of code) (raw):
require "rexml/document"
require "cgi"
require 'digest'
require 'json'
require 'date'
require 'time'
require 'logger'
require_relative 'antimalwarecommon'
class Sophos
def self.detect()
begin
sophosPath = "/opt/sophos-av/bin/savdstatus"
if !File.file?('/opt/sophos-av/bin/savdstatus')
findSophosCmd = `readlink $(which savscan)`.lines.map(&:chomp)
if !$?.success? || findSophosCmd.nil? || findSophosCmd.empty?
return false
else
savscanPath = findSophosCmd[0].strip
sophosPathArray = savscanPath.split("/")
sophosPathArray[sophosPathArray.length-1] = "savdstatus"
sophosPath = sophosPathArray.join('/')
if !File.file?(sophosPath)
return false
end
end
end
detectioncmd = `#{sophosPath} --version 2>&1`.lines.map(&:chomp)
if !$?.success? || detectioncmd.nil? || detectioncmd.empty?
return false
else
sophosInfo = detectioncmd[1].split(" = ")
sophosName = sophosInfo[0].strip
sophosVersion = sophosInfo[1].strip
if sophosName != "Sophos Anti-Virus"
#puts "Sophos Name is not Sophos Anti-Virus"
return false
elsif sophosVersion.split(".")[0].to_i < 9
#puts "Sophos version is less than 9, please install latest Sophos"
return false
end
end
#puts "Sophos is detected on the machine at path " + sophosPath
return true
rescue => e
#puts "Getting exception when checking sophos is installed or not: " + e.message
return false
end
end
def self.getprotectionstatus()
ret = {}
sophosName = "Sophos Anti-Virus"
sophosVersion = "NA"
lastUpdate = "NA"
lastUpdateTime = "NA"
buildRevision = "NA"
threatDetectionEngine = "NA"
threatData = "NA"
threatCount = "NA"
threatDataRelease = "NA"
ondemandscan = "NA"
scheduledscan = "NA"
rmsstatus = "NA"
onaccessscan = "NA"
liveprotection = "NA"
scanDate = ""
protectionStatusDetails = ""
protectionStatusAlertArray = []
protectionStatusDetailsArray = []
error = ""
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::UnknownProtectionCode
($ThreatStatusRank, $ThreatStatus) = AntimalwareCommon::UnknownThreatCode
begin
sophosPath = "/opt/sophos-av/bin/savdstatus"
#if !File.file?('/opt/sophos-av/bin/savdstatus')
#findSophosCmd = `find / -iname savdstatus | grep /bin/savdstatus 2>&1`.lines.map(&:chomp)
#if !$?.success? || findSophosCmd.nil? || findSophosCmd.empty?
#error += "Getting issue when trying to find custmized sophos path, Sophos not detected; "
#else
#sophosPath = findSophosCmd[0]
#end
#end
if !File.file?('/opt/sophos-av/bin/savdstatus')
findSophosCmd = `readlink $(which savscan)`.lines.map(&:chomp)
if !$?.success? || findSophosCmd.nil? || findSophosCmd.empty?
error += "Getting issue when trying to find custmized sophos path, Sophos not detected; "
else
savscanPath = findSophosCmd[0].strip
sophosPathArray = savscanPath.split("/")
sophosPathArray[sophosPathArray.length-1] = "savdstatus"
sophosPath = sophosPathArray.join('/')
end
end
detectioncmd = `LANG=en_US.UTF-8 #{sophosPath} --version 2>&1`.lines.map(&:chomp)
if !$?.success? || detectioncmd.nil? || detectioncmd.empty?
error += "Getting issue when running sophos version cmd; "
else
sophosInfo = detectioncmd[1].split(" = ")
sophosVersion = sophosInfo[1].strip
buildRevision = detectioncmd[2].split(" = ")[1].strip
threatDetectionEngine = detectioncmd[3].split(" = ")[1].strip
threatData = detectioncmd[4].split(" = ")[1].strip
threatCount = detectioncmd[5].split(" = ")[1].strip
threatDataRelease = detectioncmd[6].split(" = ")[1].split("UTC")[0].strip
lastUpdate = detectioncmd[7].split(" = ")[1].split("UTC")[0].strip
#250
#signature date
#threat release date
lastUpdate = Time.strptime(lastUpdate, '%a %d %b %Y %I:%M:%S %p')
threatDataRelease = Time.strptime(threatDataRelease, '%a %d %b %Y %I:%M:%S %p')
protectionStatusDetailsArray.push("buildRevision: " + buildRevision)
protectionStatusDetailsArray.push("threatData: " + threatData)
protectionStatusDetailsArray.push("threatCount: " + threatCount)
#puts "threatDataRelease " + threatDataRelease.to_s
if (!threatDataRelease.nil? && threatDataRelease != "NA")
#if (threatDataRelease < (Time.now - 30*24*3600).utc)
#($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
#protectionStatusAlertArray.push("Threat Data Release Update out of 30 days: " + threatDataRelease.to_s)
#else
protectionStatusDetailsArray.push("Threat Data Release Update: " + threatDataRelease.to_s)
#end
else
error += "threat Data Release not found; "
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
protectionStatusAlertArray.push("Threat Data Release not found: " + threatDataRelease)
end
#puts "lastUpdate " + lastUpdate.to_s
if (!lastUpdate.nil? && lastUpdate != "NA")
if (lastUpdate < (Time.now - 7*24*3600).utc)
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
protectionStatusAlertArray.push("Last Update out of 7 days: " + lastUpdate.to_s)
else
protectionStatusDetailsArray.push("Last Update within 7 days: " + lastUpdate.to_s)
end
else
error += "Last Update not found, running lastupdate cmd; "
lutcmd = `LANG=en_US.UTF-8 #{sophosPath} --lastupdate 2>&1`.lines.map(&:chomp)
if !$?.success? || lutcmd.nil? || lutcmd.empty?
error += "Fail to run last update time cmd; "
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
protectionStatusAlertArray.push("Last Update not when running last update cmd: " + lastUpdateTime)
else
lastUpdateTime = lutcmd[0].split("UTC")[0].strip
if(lastUpdateTime == "NA") or (lastUpdateTime.include? "Never updated")
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
protectionStatusAlertArray.push("Last Update not found: " + lastUpdateTime)
else
lastUpdateTime = Time.strptime(lastUpdateTime, '%a %d %b %Y %I:%M:%S %p')
if (lastUpdateTime < (Time.now - 7*24*3600).utc)
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::SignaturesOutOfDateProtectionCode
protectionStatusAlertArray.push("Last Update out of 7 days: " + lastUpdateTime.to_s)
else
protectionStatusDetailsArray.push("Last Update within 7 days: " + lastUpdateTime.to_s)
end
end
end
end
end
#############################
#270
#on access scan
#live protection
#################################################
oascmd = `#{sophosPath} -v 2>&1`.lines.map(&:chomp)
if !$?.success? || oascmd.nil? || oascmd.empty?
error += "Fail to run On Access Scan cmd; "
else
onaccessscan = oascmd[0].strip + "; " + oascmd[1].strip
if(onaccessscan == "NA") or (onaccessscan.include? "On-access scanning is not running")
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::NoRealTimeProtectionProtectionCode
protectionStatusAlertArray.push("On Access Scan is not running: " + onaccessscan)
else
protectionStatusDetailsArray.push(onaccessscan)
end
end
###########################
sophosconfigpathArray = sophosPath.split("/")
sophosconfigpathArray[sophosconfigpathArray.length-1] = "savconfig"
sophosconfigpath = sophosconfigpathArray.join('/')
lpcmd = `#{sophosconfigpath} get LiveProtection 2>&1`.lines.map(&:chomp)
if !$?.success? || lpcmd.nil? || lpcmd.empty?
error += "live protection cmd failed; "
else
liveProtection = lpcmd[0].strip
if(liveProtection == "NA") or (liveProtection != "enabled")
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::NoRealTimeProtectionProtectionCode
protectionStatusAlertArray.push("liveProtection is not enabled: " + liveProtection)
else
protectionStatusDetailsArray.push("Live Protection is enabled")
end
end
#350
#find scan date
#rms not connected
#############################
rmscmd = `#{sophosPath} --rms 2>&1`.lines.map(&:chomp)
status = $?
if rmscmd.nil? || rmscmd.empty?
error += "Fail to run Remote Management status cmd; "
else
rmsstatus = rmscmd[0].strip
if(rmsstatus == "NA") or (rmsstatus.include? "inactive")
#($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::ActionRequiredProtectionCode
protectionStatusDetailsArray.push("Remote Management status is not active: " + rmsstatus)
else
protectionStatusDetailsArray.push(rmsstatus)
end
end
#############################
sophoslogArray = sophosPath.split("/")
sophoslogArray[sophoslogArray.length-1] = "savlog"
sophoslogpath = sophoslogArray.join('/')
scancmd = `LANG=en_US.UTF-8 #{sophoslogpath} --maxage=7 | grep "scan finished" | tail -1 2>&1`.lines.map(&:chomp)
if !$?.success? || scancmd.nil? || scancmd.empty?
error += "On demand scan cmd failed; "
else
ondemandscan = scancmd[0].split("UTC: savscan.log")[0].strip
if(ondemandscan == "NA" || ondemandscan.nil? || ondemandscan.empty? )
#puts "On demand scanDate within 7 days not found"
else
ondemandscan = Time.strptime(ondemandscan, '%a %d %b %Y %I:%M:%S %p')
end
end
#puts ondemandscan.to_s
#########################################
scheduleScancmd = `LANG=en_US.UTF-8 #{sophoslogpath} --maxage=7 | grep -i "Scheduled scan .* completed" | tail -1`.lines.map(&:chomp)
if !$?.success? || scheduleScancmd.nil? || scheduleScancmd.empty?
error += "Scheduled scan cmd failed; "
else
scheduledscan = scheduleScancmd[0].split("UTC: scheduled.scan.log")[0].strip
if(scheduledscan == "NA" || scheduledscan.nil? || scheduledscan.empty? )
#puts "scheduled scanDate within 7 days not found"
else
scheduledscan = Time.strptime(scheduledscan, '%a %d %b %Y %I:%M:%S %p ')
end
end
#puts scheduledscan.to_s
#############################
if (scheduledscan == "NA" && ondemandscan == "NA")
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::ActionRequiredProtectionCode
protectionStatusAlertArray.push("No On demand Scan or scheduled Scan found in past 7 days, please run an active scan")
else
if(ondemandscan != "NA")
scanDate = ondemandscan
protectionStatusDetailsArray.push("On Demand Scan Date: " + ondemandscan.to_s)
end
if(scheduledscan != "NA")
scanDate = scheduledscan
protectionStatusDetailsArray.push("Scheduled Scan Date: " + scheduledscan.to_s)
end
end
if protectionStatusAlertArray.length == 0
($ProtectionStatusRank, $ProtectionStatus) = AntimalwareCommon::RealTimeProtectionCode
protectionStatusDetails += "Sophos is running healthy. "
protectionStatusDetails += protectionStatusDetailsArray.join('; ')
else
protectionStatusDetails += protectionStatusDetailsArray.join('; ')
protectionStatusDetails += "; "
protectionStatusDetails += protectionStatusAlertArray.join('; ')
end
rescue => e
error += "Getting exception when trying to find Sophos health info: " + e.message + " " + e.backtrace.inspect
ret["Error"] = error
end
ret["ProtectionStatusRank"] = $ProtectionStatusRank
ret["ProtectionStatus"] = $ProtectionStatus
ret["ProtectionStatusDetails"] = protectionStatusDetails
ret["DetectionId"] = SecureRandom.uuid
ret["Threat"] = ""
ret["ThreatStatusRank"] = $ThreatStatusRank
ret["ThreatStatus"] = $ThreatStatus
ret["ThreatStatusDetails"] = "Threat Status is currently not supported in Linux Sophos"
ret["Signature"] = (threatDetectionEngine.nil? || threatDetectionEngine.empty? || threatDetectionEngine == "NA")? "Signature version not found" : threatDetectionEngine
ret["ScanDate"] = scanDate
ret["DateCollected"] = DateTime.now.strftime("%m/%d/%Y %H:%M")
ret["Tool"] = sophosName
ret["AMProductVersion"] = (sophosVersion.nil? || sophosVersion.empty? || sophosVersion == "NA")? "Sophos version not found" : sophosVersion
return ret
end
end