
Ein Werkzeug für Pentester, um köstliche Süßigkeiten zu finden, von @l0ss und @Sh3r4 ( Twitter: @/mikeloss und @/sh3r4_hax )

Snaffler ist ein Werkzeug für Pentester und Red Teamer, um dabei zu helfen, leckere Bonbonnadeln (meistens Creds, aber es ist flexibel) in einem Haufen schrecklich langweiliger Heuhaufen (einer riesigen Windows/AD-Umgebung) zu finden.
Es könnte auch für andere Leute nützlich sein, die andere Sachen machen, aber es ist ausdrücklich NICHT als "Audit"-Tool gedacht.
Ugh, na gut. Aber wir sind nicht verantwortlich für die Ergebnisse. Wir haben all das andere Zeug für euch geschrieben, aber das ist okay. Wir sind nicht wütend, nur enttäuscht.
snaffler.exe -s -o snaffler.log
Im Großen und Ganzen – es holt eine Liste von Windows-Computern aus Active Directory, breitet dann seine schnüffeligen Anhängsel auf alle aus, um herauszufinden, welche Dateifreigaben haben und ob man sie lesen kann.
Dann schnüffeln NOCH MEHR Anhängsel alle Dateien in diesen Freigaben durch und nutzen GELERNTE KÜNSTLICHE INTELLIGENZ für MASCHINEN, um herauszufinden, welche ein schmutziger kleiner Hacker wie du vielleicht haben möchte.
Eigentlich macht es keine ML-Sachen, denn das richtig zu machen würde Trainingsdaten erfordern, und das würde eine enorme Menge Zeit in Anspruch nehmen, die wir nicht haben. Stattdessen, wie alle guten "ML"-Projekte, verwendet es einfach einen Haufen if-Anweisungen und Regexen.
So!
Wenn du "einfach nur die EXE auf einem der Domäne beigetretenen Rechner im Kontext eines Domänenbenutzers ausführst" (wie die Leute angewiesen wurden, es mit Grouper2 zu tun, unmittelbar bevor sie es mit allen Verbose/Debug-Schaltern laufen ließen, sodass es mehrere hundert Megabyte Stacktraces schrie) wird es im Grunde nichts tun. Das ist unsere Idee eines StreichsTM an Leuten, die keine README-Dateien lesen, weil wir Monster sind.
JEDOCH... wenn du die richtigen Beschwörungen hinzufügst, wird es das erwähnte L.A.I.M. aktivieren und die Dateipfade, in denen Süßigkeiten gefunden werden könnten, werden herausfallen.
Die wichtigsten Beschwörungen sind:
-o Aktiviert die Ausgabe der Ergebnisse in eine Datei. Das willst du wahrscheinlich, wenn du kein -s verwendest. z.B. -o C:\users\thing\snaffler.log
-s Aktiviert die Ausgabe der Ergebnisse auf stdout, sobald sie gefunden werden. Das willst du wahrscheinlich, wenn du kein -o verwendest.
-v Steuert die Ausführlichkeitsstufe. Optionen sind Trace (ausführlichste), Degub (weniger ausführlich, weniger Gubs), Info (noch weniger ausführlich, Standard) und Data (nur Ergebnisse). z.B -v debug
-m Aktiviert und weist ein Ausgabeverzeichnis zu, damit Snaffler automatisch eine Kopie (oder einen Snaffle... wenn man so will) aller gefundenen Dateien erstellt, die es mag.
-l Maximale Größe der Dateien (in Bytes) zum Snafflen. Standard ist 10000000, was etwa 10MB entspricht.
-i Deaktiviert die Computer- und Freigabeerkennung; erfordert einen Pfad zu einem Verzeichnis, in dem die Dateierkennung durchgeführt werden soll.
-n Deaktiviert die Computererkennung; nimmt eine kommagetrennte Liste von Hosts oder eine Eingabedatei, um die Freigabe- und Dateierkennung durchzuführen. Hinweis: Bei Angabe einer Datei muss die Eingabe ein Pfad sein, also z.B. C:\targets.txt oder .\targets.txt.
-y Formatiert die Ausgabe im TSV-Format.
-b Überspringt die LAIM-Regeln, die weniger interessante Dinge finden; stelle es mit einer Zahl zwischen 0 und 3 ein.
-f Beschränkt Snaffler auf das Auffinden von Dateifreigaben über DFS (Distributed File System) – das sollte deutlich heimlicher sein als die Standardeinstellung, während es immer noch die größten Dateifreigaben in vielen Organisationen abdeckt.
-a Überspringt die Dateiaufzählung; gibt dir nur eine Liste der auflistbaren Freigaben auf den Zielhosts.
-u Lässt Snaffler eine Liste von Kontonamen aus AD abrufen, die interessantesten auswählen und sie dann in einer Suchregel verwenden.
-d Domäne, in der nach Computern gesucht werden soll, um nach Freigaben zu suchen, in denen nach Dateien gesucht werden soll. Einfach.
-c Domänencontroller, der für die Liste der Domänencomputer abgefragt werden soll.
-r Die maximale Größe einer Datei (in Bytes), die nach interessanten Zeichenketten durchsucht werden soll. Standard ist 500k.
-j Wie viele Bytes Kontext auf jeder Seite der gefundenen Zeichenketten in Dateien angezeigt werden sollen, z.B. -j 200
-z Pfad zu einer Konfigurationsdatei, die all das und noch viel mehr definiert! Siehe unten für weitere Details. Gib -z generate ein, um eine Beispielkonfigurationsdatei namens .\default.toml zu generieren.
-t Art des Logs, das du ausgeben möchtest. Derzeit unterstützte Optionen sind plain und JSON. Standard ist plain.
-x Maximale Anzahl von Threads, die verwendet werden sollen. Setze es nicht unter 4, sonst geht etwas kaputt.
-p Pfad zu einem Verzeichnis voller .toml-formattierter Regeln. Snaffler lädt alle diese anstelle des Standardregelsatzes.```toml
[[ClassifierRules]]
EnumerationScope = "DirectoryEnumeration" # This defines which phase of the discovery process we're going to apply the rule.
# In this case, we're looking at directories.
# Valid values include ShareEnumeration, DirectoryEnumeration, FileEnumeration, ContentsEnumeration
RuleName = "DiscardLargeFalsePosDirs" # This can be whatever you want. We've been following a rough naming scheme, but you can call it "Stinky" if you want. ¯_(ツ)_/¯
MatchAction = "Discard"# What to do with things that match the rule. In this case, we want to discard anything that matches this rule.
# Valid options include: Snaffle (keep), Discard, Relay (example of this below), and CheckForKeys (example below)
Description = "File paths that will be skipped entirely." # Not used in the code, just a place for notes really.
MatchLocation = "FilePath" # What part of the file/dir/share to look at to check for a match. In this case we're looking at the whole path.
# Valid options include: ShareName, FilePath, FileName, FileExtension, FileContentAsString, FileContentAsBytes,
# although obviously not all of these will apply in all EnumerationScopes.
WordListType = "Contains" # What matching logic to apply, valid options are: Exact, Contains, EndsWith, StartsWith, or Regex.
# Under the hood these all get turned into regexen one way or another.
MatchLength = 0
WordList = [
"\\\\puppet\\\\share\\\\doc",
"\\\\lib\\\\ruby",
"\\\\lib\\\\site-packages",
"\\\\usr\\\\share\\\\doc",
"node_modules",
"vendor\\\\bundle",
"vendor\\\\cache",
"\\\\doc\\\\openssl",
"Anaconda3\\\\Lib\\\\test",
"WindowsPowerShell\\\\Modules",
"Python27\\\\Lib"
] Triage = "Green" # If we find a match, what severity rating should we give it. Valid values are Black, Red, Yellow, Green. This value is ignored for Discard MatchActions.
Diese Regel hingegen betrachtet die Dateierweiterungen und verwirft sofort alle, die uns nicht gefallen.
In diesem Fall verwerfe ich hauptsächlich Schriftarten, Bilder, CSS usw.```toml
[[ClassifierRules]]
EnumerationScope = "FileEnumeration" # We're looking at the actual files, not the shares or dirs or whatever.
RuleName = "DiscardExtExact" # just a name
MatchAction = "Discard" # We're discarding these
MatchLocation = "FileExtension" # This time we're only looking at the file extension part of the file's name.
WordListType = "Exact" # and we only want exact matches.
WordList = [".bmp", ".eps", ".gif", ".ico", ".jfi", ".jfif", ".jif", ".jpe", ".jpeg", ".jpg", ".png", ".psd", ".svg", ".tif", ".tiff", ".webp", ".xcf", ".ttf", ".otf", ".lock", ".css", ".less"] # list of file extensions.
Hier ist ein Beispiel für eine wirklich einfache Regel für Dinge, die wir mögen und behalten wollen.```toml [[ClassifierRules]] EnumerationScope = "FileEnumeration" # Still looking at files RuleName = "KeepExtExactBlack" # Just a name MatchAction = "Snaffle" # This time we are 'snaffling' these. This usually just means send it to the output, # but if you turn on the appropriate option it will also grab a copy. MatchLocation = "FileExtension" # We're looking at file extensions again WordListType = "Exact" # With Exact Matches WordList = [".kdbx", ".kdb", ".ppk", ".vmdk", ".vhdx", ".ova", ".ovf", ".psafe3", ".cscfg", ".kwallet", ".tblk", ".ovpn", ".mdf", ".sdf", ".sqldump"] # and a bunch of fun file extensions. Triage = "Black" # these are all big wins if we find them, so we're giving them the most severe rating.
Dieser hier ist im Grunde derselbe, aber wir betrachten den gesamten Dateinamen. Einfach!```toml
[[ClassifierRules]]
EnumerationScope = "FileEnumeration"
RuleName = "KeepFilenameExactBlack"
MatchAction = "Snaffle"
MatchLocation = "FileName"
WordListType = "Exact"
WordList = ["id_rsa", "id_dsa", "NTDS.DIT", "shadow", "pwd.db", "passwd"]
Triage = "Black"
Dieses hier ist ein bisschen raffiniert, schau dir das an...```toml [[ClassifierRules]] EnumerationScope = "FileEnumeration" # we're looking for files... RuleName = "KeepCertContainsPrivKeyRed" MatchLocation = "FileExtension" # specifically, ones with certain file extensions... WordListType = "Exact" WordList = [".der", ".pfx"] # specifically these ones... MatchAction = "CheckForKeys" # and any that we find, we're going to parse them as x509 certs, and see if the file includes a private key! Triage = "Red" # cert files aren't very sexy, and you'll get huge numbers of them in most wintel environments, but this check gives us a way better SNR!
OK, hier kommt das mächtige Zeug ins Spiel. Wir haben hier ein Paar Regeln in einer Kette.
Dateien mit Erweiterungen, die der ersten Regel entsprechen, werden an die zweite Regel gesendet, die sie per „grep“ (also String.Contains()) auf Begriffe aus einer bestimmten Wortliste durchsucht.
Du kannst diese Verkettung beliebig fortsetzen, auch wenn ich denke, dass es zu Leistungsproblemen kommen dürfte, wenn du zu sehr in die Inception-Ebene abtauchst.```toml
[[ClassifierRules]]
EnumerationScope = "FileEnumeration" # this one looks at files...
RuleName = "ConfigGrepExtExact"
MatchLocation = "FileExtension" # specifically the extensions...
WordListType = "Exact"
WordList = [".yaml", ".xml", ".json", ".config", ".ini", ".inf", ".cnf", ".conf"] # these ones.
MatchAction = "Relay" # Then any files that match are handed downstream...
RelayTargets = ["KeepConfigGrepContainsRed"] # To the rule with this RuleName! This can also be an array of RuleNames if you want to get real wild and start writing branching rulesets.
[[ClassifierRules]]
RuleName = "KeepConfigGrepContainsRed" # Anyway, this is the target rule. Following a naming convention really helps to make sure you're using the right targets.
EnumerationScope = "ContentsEnumeration" # this one looks at file content!
MatchAction = "Snaffle" # it keeps files that match
MatchLocation = "FileContentAsString" # it's looking at the contents as a string (rather than a byte array)
WordListType = "Contains" # it's using simple matching
WordList = ["password=", " connectionString=\"", "sqlConnectionString=\"", "validationKey=", "decryptionKey=", "NVRAM config last updated"]
Triage = "Red"
Hoffentlich vermittelt das die Idee. Ich empfehle, einige der Standardregeln zu nehmen und damit herumzuspielen, bis du das Gefühl hast, dass du einen guten Überblick hast.
Viele Leute wollten die Möglichkeit, in Dateiformate hineinzuschauen, die nicht nur einfacher Text sind, wie Word-Dokumente, PDFs, .eml usw. Leider hat die einfachste Bibliothek zur Implementierung dieser Funktionalität die endgültige Dateigröße von Snaffler.exe um etwa 1200 % aufgebläht, was für eine Reihe beliebter In-Memory-Ausführungstechniken, die Obergrenzen für die Größe der verwendbaren Dateien haben, schlecht war.
Die Lösung war UltraSnaffler, das einfach eine zweite .sln-Datei ist, die die benötigte Bibliothek und den entsprechenden Code aktiviert. Baue UltraSnaffler.sln, erhalte UltraSnaffler.
WARNUNG: Die Standardregeln von Snaffler enthalten keine, die in Office-Dokumente oder PDFs hineinschauen, weil wir es als sehr schwierig empfanden, Regeln zu schreiben, die nicht einfach Jahre brauchen würden, um einen Durchlauf in einer typischen Unternehmensumgebung abzuschließen. Sei gewarnt, das Hineinschauen in diese Dokumente ist viel langsamer als das Hineinschauen in altmodische Textdateien, und eine typische Umgebung wird einen absoluten Berg von minderwertigen Office-Dokumenten und PDFs enthalten.
Das ist meiner Meinung nach wirklich genial.
Wenn du -z generate an das Ende einer Snaffler-Befehlszeile anhängst, serialisiert Snaffler das Konfigurationsobjekt (einschließlich der Aspekte der Konfiguration, die durch deine Argumente festgelegt wurden) in eine .toml-Konfigurationsdatei, die du dann recht einfach (oder auch nicht) von Hand bearbeiten und nach Belieben wiederverwenden kannst.
Zum Beispiel, wenn du Folgendes ausführst:
Snaffler.exe -s -o C:\mydir\snaffler.log -v trace -i \\host.lol.domain\share -p C:\users\someguy\myrules -z generate
wird Snaffler all deine vielen Argumente parsen, sie in ein Konfigurationsobjekt umwandeln, dieses Konfigurationsobjekt in die folgende .toml-Konfigurationsdatei serialisieren:```toml
PathTargets = ["\\host.lol.domain\share"]
ComputerTargetsLdapFilter = "(objectClass=computer)"
ScanSysvol = true
ScanNetlogon = true
ScanFoundShares = true
InterestLevel = 0
DfsOnly = false
DfsShareDiscovery = false
DfsNamespacePaths = []
CurrentUser = "l0sslab\l0ss"
RuleDir = "C:\users\someguy\myrules"
MaxThreads = 60
ShareThreads = 20
TreeThreads = 20
FileThreads = 20
MaxFileQueue = 200000
MaxTreeQueue = 0
MaxShareQueue = 0
LogToFile = true
LogFilePath = "C:\mydir\snaffler.log"
LogType = "Plain"
LogTSV = false
Separator = 32
LogToConsole = true
LogLevelString = "trace"
ShareFinderEnabled = false
LogDeniedShares = false
DomainUserRules = false
DomainUserMinLen = 6
DomainUserNameFormats = ["sAMAccountName"]
DomainUserMatchStrings = ["sql", "svc", "service", "backup", "ccm", "scom", "opsmgr", "adm", "adcs", "MSOL", "adsync", "thycotic", "secretserver", "cyberark", "configmgr"]
DomainUsersWordlistRules = ["KeepConfigRegexRed"]
MaxSizeToGrep = 1000000
Snaffle = false
MaxSizeToSnaffle = 10000000
MatchContextBytes = 200
Du wirst vielleicht bemerken, dass es viele Einträge gibt, für die du keine Argumente übergeben hast. Diese Werte sind die Standardkonfigurationseinträge, von denen einige nur einfach in der Quelle oder über eine Konfigurationsdatei bearbeitet werden können, meist weil es sich nicht lohnte, ein Argument dafür hinzuzufügen.
## Das ist beschissen, habt ihr vor, es weniger beschissen zu machen?
Nein, ist es nicht, du bist beschissen.
Außerdem, ja, haben wir.
Wir werden außerdem:
- Hinzufügen des Parsens von Archivdateien, idealerweise behandeln wir sie wie ein weiteres Verzeichnis, das wir nach Schätzen durchsuchen.
- Weiter verfeinern der Regeln und Regexen. **Mehr Wörter für die Wortlisten! `string[]`s für den `string`-Thron!**

## Von wem hast du den Code geklaut?
Die Share-Enumerationsteile wurden von SharpShares geschnappt (siehst du, was ich da gemacht habe?), geschrieben vom äußerst nützlichen Dwight Hohnstein. (https://github.com/djhohnstein/SharpShares/)
Dwights GitHub-Profil ist wie dieser erstaunliche hintere Gang in einem Baumarkt, der eine ganze Reihe von Werkzeugen hat, bei denen du denkst 'oh Mann, ich kann es kaum erwarten, eine Ausrede zu haben, um dieses hier mal richtig auszuprobieren...' und du solltest es dir unbedingt ansehen.
Obwohl kein Code übernommen wurde (hauptsächlich weil es Ruby ist lol), haben wir eine Reihe von netten Ideen von `plunder2` geklaut (http://joshstone.us/plunder2/)
Wortlisten wurden auch aus denen in einigen anderen ähnlichen Tools wie trufflehog, shhgit, gitrobber und graudit zusammengestellt.
## Ist es OPSEC-sicher? (Was auch immer das zur Hölle bedeutet)
Pffft, nein. Es ist verdammt laut.
Schau, sagen wir es so... Wenn es die Art von Umgebung ist, in der du dich sicher fühlst, BloodHound im Standardmodus auszuführen, dann uhhh, ja Mann... Es ist wirklich unauffällig.
## Ich dachte, du hast dieses Ding bei Red-Team-Einsätzen benutzt?
*seufz*
OK, ich gebe dir die echte Antwort.
Im Standardmodus sieht Snaffler in vielerlei Hinsicht wie SharpHound aus. Es redet eine Menge LDAP mit AD, dann geht es los und versucht, mit jedem Windows-Rechner in der Domäne SMB zu sprechen. Diese Art von Verhalten bringt dich so gut wie sicher in Schwierigkeiten in einer Organisation, die auch nur ansatzweise ihre Angelegenheiten im Griff hat.
Allerdings...
Die gezielteren Optionen von Snaffler (insbesondere `-i`) lösen mit *viel* geringerer Wahrscheinlichkeit Detektionen aus.
Ich bin besonders begeistert davon, `Snaffler.exe -s -i C:\` auf einem frisch kompromittierten Server oder einer Workstation auszuführen, und ich habe noch nicht erlebt, dass dieses Verhalten erkannt wurde.
Bisher.
## Wie kann ich helfen oder Hilfe bekommen?
Wenn du über Slack diskutieren möchtest, kannst du uns (@l0ss oder @Sh3r4) im BloodHound Slack anpingen, erreichbar unter https://bloodhoundgang.herokuapp.com/, oder mit einer Gruppe von Mitwirkenden im #snaffler-Kanal chatten.
You can also ping us on Twitter - @mikeloss and @sh3r4_hax
Ansonsten erstelle ein Issue; wir werden es versuchen.