Agent: Filechecker module: use flexible JSON syntax in module commands

This commit reworks the arguments passed to agent's modules as an
undefined interface{} in JSON format. It will allow complex commands
to be passed to the modules.
This commit is contained in:
Julien Vehent 2013-10-29 09:17:21 -04:00
Родитель 0b2bab7e7e
Коммит 2817bca128
4 изменённых файлов: 51 добавлений и 80 удалений

Просмотреть файл

@ -2,7 +2,13 @@
"Name": "MOZSYSCOMP_LOWENCCRED",
"Target": "linux",
"Check": "filechecker",
"Arguments":["/etc/shadow:contains=root:$1$"],
"Arguments": {
"MOZSYSCOMPLOWENCCRED1" : {
"Path": "/etc/shadow",
"Type": "contains",
"Value": "root:\\$6"
}
},
"RunDate": "immediate",
"Expiration": "30m"
}

Просмотреть файл

@ -1,3 +1,6 @@
// TODO
// * syntax check mig.Action.Arguments before exec()
package main
import (
@ -114,8 +117,7 @@ func main() {
go getCommands(msgChan, actionsChan, termChan)
}
go parseCommands(actionsChan, fCommandChan, termChan)
go runFilechecker(fCommandChan, alertChan, resultChan, termChan)
go raiseAlerts(alertChan, termChan)
go runFilechecker(fCommandChan, resultChan, termChan)
go sendResults(c, regMsg.QueueLoc, resultChan, termChan)
// All set, ready to keepAlive
@ -162,72 +164,36 @@ func parseCommands(commands <-chan []byte, fCommandChan chan mig.Command, termin
return nil
}
func runFilechecker(fCommandChan <-chan mig.Command, alertChan chan mig.Alert, resultChan chan mig.Command, terminate chan bool) error {
func runFilechecker(fCommandChan <-chan mig.Command, resultChan chan mig.Command, terminate chan bool) error {
for migCmd := range fCommandChan {
log.Printf("RunFilechecker: running with args '%s'", migCmd.Action.Arguments)
var cmdArg string
for _, arg := range migCmd.Action.Arguments {
cmdArg += arg
}
runCmd := exec.Command("./filechecker", cmdArg)
cmdout, err := runCmd.StdoutPipe()
// Arguments can contain anything. Syntax Check before feeding
// them to exec()
args, err := json.Marshal(migCmd.Action.Arguments)
if err != nil {
log.Fatal(err)
log.Fatal("runFilechecker json.Marshal(migCmd.Action.Arguments): ", err)
}
st := time.Now()
err = runCmd.Start()
s_args := fmt.Sprintf("%s", args)
log.Printf("runFilechecker: arguments %s", s_args)
runCmd := exec.Command("/opt/agent","-m","filechecker",s_args)
output, err := runCmd.CombinedOutput()
if err != nil {
log.Fatal(err)
log.Fatal("runFilechecker cmd.CombinedOutput(): ",
fmt.Sprint(err), " - ", string(output))
} else {
log.Println("runFilechecker cmd.CombinedOutput(): ",
string(output))
}
results := make(map[string]mig.FileCheckerResult)
err = json.NewDecoder(cmdout).Decode(&results)
err = json.Unmarshal([]byte(output), &migCmd.Results)
if err != nil {
log.Fatal(err)
}
cmdDone := make(chan error)
go func() {
cmdDone <- runCmd.Wait()
}()
select {
// kill the process when timeout expires
case <-time.After(30 * time.Second):
if err := runCmd.Process.Kill(); err != nil {
log.Fatal("failed to kill:", err)
}
log.Fatal("runFileChecker: command '%s' timed out", migCmd)
// exit normally
case err := <-cmdDone:
if err != nil {
log.Fatal(err)
}
}
for _, r := range results {
log.Println("runFileChecker: command", migCmd, "tested",
r.TestedFiles, "files in", time.Now().Sub(st))
if r.ResultCount > 0 {
for _, f := range r.Files {
alertChan <- mig.Alert{
Arguments: migCmd.Action.Arguments,
Item: f,
}
}
}
migCmd.FCResults = append(migCmd.FCResults, r)
log.Fatal("runFilechecker json.Unmarshal(): ", err)
}
// send the results back to the scheduler
resultChan <- migCmd
}
terminate <- true
return nil
}
func raiseAlerts(alertChan chan mig.Alert, terminate chan bool) error {
for a := range alertChan {
log.Printf("raiseAlerts: IOC '%s' positive match on '%s'",
a.Arguments, a.Item)
}
return nil
}
func sendResults(c *amqp.Channel, agtQueueLoc string, resultChan <-chan mig.Command, terminate chan bool) error {
rKey := fmt.Sprintf("mig.sched.%s", agtQueueLoc)
for r := range resultChan {

Просмотреть файл

@ -41,10 +41,10 @@ import (
"crypto/sha1"
"crypto/sha256"
"crypto/sha512"
"encoding/json"
"fmt"
"hash"
"io"
"encoding/json"
"os"
"regexp"
)
@ -69,16 +69,20 @@ const (
CheckSHA3_512
)
/* Representation of a File Check.
- Path is the file system path to inspect
- Type is the name of the type of check
- Value is the value of the check, such as a md5 hash
- CodeType is the type of check in integer form
- FilesCount is the total number of files inspected for each Check
- MatchCount is a counter of positive results for this Check
- Result is a boolean set to True when the Check has matched once or more
- Files is an slice of string that contains paths of matching files
*/
type Arguments struct {
Arg map[string]FileCheck
}
// Representation of a File Check.
// Path is the file system path to inspect
// Type is the name of the type of check
// Value is the value of the check, such as a md5 hash
// CodeType is the type of check in integer form
// FilesCount is the total number of files inspected for each Check
// MatchCount is a counter of positive results for this Check
// Result is a boolean set to True when the Check has matched once or more
// Files is an slice of string that contains paths of matching files
// Re is a regular expression
type FileCheck struct {
ID, Path, Type, Value string
CodeType, FilesCount, MatchCount int
@ -87,9 +91,9 @@ type FileCheck struct {
Re *regexp.Regexp
}
type CheckResult struct {
type Results struct {
TestedFiles, MatchCount int
Files []string
Files []string
}
/* Statistic counters:
@ -529,7 +533,7 @@ func GetDownThatPath(path string, ActiveCheckIDs []string, CheckBitMask int,
- nil on success, error on failure
*/
func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
Results := make(map[string]CheckResult)
res := make(map[string]Results)
FileHistory := make(map[string]int)
for _, check := range Checks {
if VERBOSE {
@ -553,7 +557,7 @@ func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
for f, _ := range check.Files {
listPosFiles = append(listPosFiles, f)
}
Results[check.ID] = CheckResult{
res[check.ID] = Results{
TestedFiles: check.FilesCount,
MatchCount: check.MatchCount,
Files: listPosFiles,
@ -569,7 +573,7 @@ func BuildResults(Checks map[string]FileCheck, Statistics *Stats) (string) {
Statistics.ChecksMatch, Statistics.UniqueFiles,
Statistics.TotalHits)
}
JsonResults, err := json.Marshal(Results)
JsonResults, err := json.Marshal(res)
if err != nil { panic(err) }
return string(JsonResults[:])
}

Просмотреть файл

@ -6,24 +6,19 @@ import(
type Action struct {
Name, Target, Check, RunDate, Expiration string
Arguments []string
Arguments interface{}
UniqID uint32
}
type Command struct {
AgentName, AgentQueueLoc string
Action Action
FCResults []FileCheckerResult
Results interface{}
UniqID uint32
}
type FileCheckerResult struct {
TestedFiles, ResultCount int
Files []string
}
type Alert struct {
Arguments []string
Arguments interface{}
Item string
}