|
3ce55c6994101faec00b5b7c2fee494f
git commit -a . && git push github master
$ mig file -path / -name "^\.boto$" -content "abcdef123456" -size "<1k" -maxdepth 5
all loosely connected only when needed
Visibility | too many systems doing too many things in too many ways. Need to see them all. |
Reachability | we don't have accounts or network accesses to all systems. |
Heterogeneity | every snowflake system is investigated in its own special way. |
- "Hey Systems, seen that <file|ip|process|user> lately?".
- "Nope"
- "Nope"
- "Nope"
- "Oh yeah, just yesterday!" <--- OMG DEFCON 1!!!
Massively Distributed means Fast.
Simple to deploy and Cross-Platform.
Secure! Don't trust until you verify.
Don't spy on data, respect Privacy.
Central platform only passes messages around.
Investigation & computation is done on the agents.
Small infrastructure footprint
means easier to deploy and operate.
One static binary, no dependencies.
Configuration is built-in or deployed via provisioning.
{
"name": "locate bad actor",
"target": "mode='daemon'",
"validfrom": "2015-05-27T00:29:29.038012Z",
"expireafter": "2015-05-27T00:30:59.038012Z",
"operations": [
{ "module": "file",
"parameters": {
"searches": { "s1": { "paths": ["/etc/cron.d"],
"contents": ["badpassword"]
}}}}
],
"pgpsignatures": ["wsBcBAABCAAQBQJVZRAlCRCj1lIXO3..."],
"syntaxversion": 2
}
Doing forensics without full access to all data is hard, but not impossible. Agents do the work and return answers without raw data. |
REST API receives signed JSON messages
distributed to agents via RabbitMQ
and stored in a Postgres database.
+-------+ [ - - - - - - A G E N T - - - - - - - - - - - - ] |command|+---->(listener) +-------+ |(2) ^ V |(1) (parser) | + [ m o d u l e s ] +---------+ | (3)|----------> op1 +----------------+ |SCHEDULER|+---+ |------------> op2 +--------------| | |<---+ |--------------> op3 +------------| +---------+ | +----------------> op4 +----------+ | V(4) |(6) (receiver) | | | V(5) + (publisher) +-------+ / |results|<----------------------------------------- +-------+
Agent only runs something if these conditions are met:
multiple signatures required to run sensitive modules
var AGENTACL = [...]string{
`{ "file": { "minimumweight": 2,
"investigators": {
"Alice": { "fingerprint": "E60892BB..", "weight": 2 },
"Bob": { "fingerprint": "AD595634..", "weight": 2 } } }
}`,
`{ "memory": { "minimumweight": 3,
"investigators": {
"Alice": { "fingerprint": "E60892BB..", "weight": 2 },
"Eve": { "fingerprint": "F6D781AE..", "weight": 1 } } } }
}`,
}
The weights of each investigator providing a valid signature are summed, and if the total weight is equal or higher than the minimum weight, the operation is considered valid.
TotalWeight = Weight[Alice} + Weight[Bob] if TotalWeight >= MinimumWeight { run module }
REST API, uses IdFix PGP Token authentication
curl -H 'X-PGPAUTHORIZATION: 1;2015-05-28T15:04:05Z;111;owEBYQGe/pANAwAIAaP...' https://api.mig.example.net/api/v1/
PGP already needed to sign actions
A PGP Token avoids needing another username/password.
Typical PostgreSQL protections (TLS, credentials, GRANTs)
Minimalistic attack surface:
Complex code path to move messages around BUT:
Most exposed component (public).
Requires AMQP over TLS with client certs and credentials.
Tightly controlled RabbitMQ ACLs, but hard to write/audit.
many samples at
https://github.com/mozilla/mig/tree/master/actions
Example: Shellshock IOCs
{
"name": "Shellshock IOCs (nginx and more)",
"target": "environment->>'os' IN ('linux','darwin') AND mode='daemon'",
"operations": [
{
"module": "file",
"parameters": {
"searches": {
"iocs": {
"paths": [
"/usr/bin",
"/usr/sbin",
"/bin",
"/sbin",
"/tmp",
"/var/tmp"
],
"sha256": [
"73b0d95541c84965fa42c3e257bb349957b3be626dec9d55efcc6ebcba6fa489",
"ae3b4f296957ee0a208003569647f04e585775be1f3992921af996b320cf520b",
"2d3e0be24ef668b85ed48e81ebb50dce50612fb8dce96879f80306701bc41614",
"2ff32fcfee5088b14ce6c96ccb47315d7172135b999767296682c368e3d5ccac",
"1f5f14853819800e740d43c4919cc0cbb889d182cc213b0954251ee714a70e4b",
"2bc9a2f7374308d9bb97b8d116177d53eaca060b562f6f66f5dd1af71c9d7a66"
],
"contents": [
"/bin/busybox;echo -e '\\\\147\\\\141\\\\171\\\\146\\\\147\\\\164'",
"legend.rocks"
],
"names": [
"legend.txt"
]
}
}
}
},
{
"module": "netstat",
"parameters": {
"connectedip": [
"108.162.197.26",
"162.253.66.76",
"89.238.150.154",
"198.46.135.194",
"166.78.61.142",
"23.235.43.31",
"54.228.25.245",
"23.235.43.21",
"23.235.43.27",
"198.58.106.99",
"23.235.43.25",
"23.235.43.23",
"23.235.43.29",
"108.174.50.137",
"201.67.234.45",
"128.199.216.68",
"75.127.84.182",
"82.118.242.223",
"24.251.197.244",
"166.78.61.142",
"119.110.98.93",
"2.0.1.5"
]
}
}
],
"description": {
"author": "Julien Vehent",
"email": "ulfr@mozilla.com",
"revision": 201410031030
},
"syntaxversion": 2
}
{
"module": "file",
"parameters": {
"searches": {
"checkforverboselogging": {
"paths": [
"/etc/ssh/sshd_config"
],
"contents": [
"(?i)^loglevel verbose$"
]
},
"checkpasswordusageisoff": {
"paths": [
"/etc/ssh/sshd_config"
],
"contents": [
"(?i)^passwordauthentication no$"
]
}
}
}
}
{
"name": "checkpasswordusageisoff",
"description": "compliance check for ssh",
"target": "server1.mydomain.example.net",
"utctimestamp": "2015-02-19T02:59:30.203004Z",
"compliance": true,
"location": "/etc/ssh/sshd_config",
"ref": "syslowremote1",
"check": {
"test": {
"type": "file",
"value": "(?i)^passwordauthentication no$"
}
"tags": {
"operator": "IT"
},
"link": "https://api.mig.example.net/api/v1/command?commandid=1424314751392165120",
"policy": {
"url": "https://wiki.example.net/ComplianceDoc/IT+System+security+guidelines",
"name": "system",
"level": "low"
}
}
}
## ## _.---._ .---.
# # # /-\ ---|| | /\ __...---' .---. '---'-. '.
# #| | / || | /--\ .-''__.--' _.'( | )'. '. '._ :
# # \_/ ---| \_ \_/ \ .'__-'_ .--'' ._'---'_.-. '. '-'.
### ~ -._ -._''---. -. '-._ '.
# |\ |\ /---------| ~ -.._ _ _ _ ..-_ '. '-._''--.._
# | \| \ / |- |__ | | -~ -._ '-. -. '-._''--.._.--''.
###| \ \/ ---__| | | ~ ~-.__ -._ '-.__ '. '.
##### ~~ ~---...__ _ ._ .' '.
# /\ --- /-\ |--|---- ~ ~--.....--~
# ### /--\ | | ||-\ //
#####/ \ | \_/ | \//__