Skip to content

Commit

Permalink
Merge pull request #6 from FalconForceTeam/dev
Browse files Browse the repository at this point in the history
Added new data source and endpoint
  • Loading branch information
olafhartong authored Dec 5, 2023
2 parents 6cd8353 + 94fb704 commit 9fe80eb
Show file tree
Hide file tree
Showing 19 changed files with 450 additions and 37 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ actionsTEST/*
falconhound
dist/*
.goreleaser.yaml
cache.db
cache.db
.idea/*
24 changes: 23 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ The Sentinel Watchlists target will write the results of the query to a Sentinel
WatchlistName: FH_MDE_Exploitable_Machines
DisplayName: MDE Exploitable Machines
SearchKey: DeviceName
Overwrite: true
Overwrite: true
```

The `WatchlistName` field is the name of the watchlist. The `DisplayName` field is the display name of the watchlist.
Expand All @@ -240,6 +240,15 @@ Like Sentinel, Splunk will write the results of the query to a Splunk index. The
- Name: Splunk
Enabled: true
```
#### Azure Data Explorer

Like Sentinel, Splunk will write the results of the query to a ADX table. The data from the query will be added to the EventData field. The EventID will be the action ID and the Description will be the action name.

```yaml
- Name: ADX
Enabled: true
Table: "name"
```

### Extensions to the graph

Expand All @@ -264,6 +273,8 @@ FalconHound will add the following properties to nodes in the graph:
Computer:
- 'exploitable': true/false
- 'exploits': list of CVEs
- 'exposed': true/false
- 'ports': list of ports accessible from the internet
- 'alertids': list of alert ids

## Credential management
Expand Down Expand Up @@ -309,12 +320,23 @@ Neo4jPassword
GraphTenantID
GraphAppID
GraphAppSecret
AdxTenantID
AdxAppID
AdxAppSecret
AdxClusterURL
AdxDatabase
SplunkUrl
SplunkApiToken
SplunkIndex
SplunkApiPort
SplunkHecToken
SplunkHecPort
BHUrl
BHTokenID
BHTokenKey
LogScaleUrl
LogScaleToken
LogScaleRepository
```
Once configured you can add the `-keyvault` parameter while starting FalconHound.
Expand Down
5 changes: 4 additions & 1 deletion actions/02-MDE/mde_exploitable_hosts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ Targets:
WatchlistName: FH_MDE_Exploitable_Machines
DisplayName: MDE Exploitable Machines
SearchKey: DeviceName
Overwrite: true
Overwrite: true
- Name: ADX
Enabled: false
Table: FalconHound
28 changes: 28 additions & 0 deletions actions/05-LogScale/fls_new_sessions.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
Name: Get new logon sessions
ID: FLS_New_Sessions
Description: Gets all logon events from Falcon LogScale and sends them to Neo4j
Author: FalconForce
Version: '1.0'
Info: |
Gets all logon events from LogScale, filters out non-user logons, and creates a relationship between the computer and the user in Neo4j,
with the timestamp of the first logon event.
Active: true # Enable to run this action
Debug: false # Enable to see query results in the console
SourcePlatform: LogScale # Sentinel, Watchlist, Neo4j, CSV, MDE, Graph, Splunk
Query: | # Splunk index can be hardcoded or a variable set in the config.yml file
"@collect.source_name" = "windows_events"
| windows.EventID = 4624
| windows.EventData.TargetUserSid = "S-1-5-21-*"
| windows.EventData.LogonType!=3
| table([@timestamp,windows.EventData.TargetUserSid,windows.Computer])
| rename(field=[[windows.EventData.TargetUserSid, TargetUserSid], [windows.Computer, Computer], [@timestamp, Timestamp]])
Targets: # Targets are the platforms that this action will push to (CSV, Neo4j, Sentinel, Wachlist, Slack, Teams, Splunk, Markdown)
- Name: Neo4j
Enabled: true
Query: |
WITH toUpper($Computer) as Computer, toUpper($TargetUserSid) as TargetUserSid, $Timestamp as Timestamp
MATCH (x:Computer {name:Computer}) MATCH (y:User {objectid:TargetUserSid}) MERGE (x)-[r:HasSession]->(y) SET r.since=Timestamp SET r.source='falconhound'
Parameters:
Computer: Computer
TargetUserSid: TargetUserSid
Timestamp: Timestamp
2 changes: 1 addition & 1 deletion actions/10-Neo4j/n4j_ad_kerberoastable_users.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Debug: false # Enable to see query results in the console
SourcePlatform: Neo4j
Query: |
MATCH (n:User) WHERE n.hasspn=true
RETURN {Name: n.name, LastPasswordSet: n.pwdlastset, HighValue: n.highvalue, Sensitive: n.sensitive }
RETURN {Name: n.name, LastPasswordSet: n.pwdlastset, HighValue: n.highvalue, Sensitive: n.sensitive, Sid: n.objectid }
Targets:
- Name: CSV
Enabled: false
Expand Down
7 changes: 5 additions & 2 deletions actions/10-Neo4j/n4j_exploitable_device_to_high_value.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Query: |
MATCH (y:Group {objectid:ObjectID})
MATCH (u:Computer {exploitable:true})
WITH Name, COUNT(shortestPath((u)-[]->(y))) as Direct, COUNT(shortestPath((u)-[*1..]->(y))) as Nested, nodes(shortestPath((u)-[]->(y))) as DirectNames, nodes(shortestPath((u)-[*1..]->(y))) as NestedNames
WHERE Nested <> 0 and Direct <> 0
WHERE Nested <> 0 or Direct <> 0
RETURN {Name: Name, Direct: Direct, DirectNames: [node in DirectNames | node.name],Nested: Nested, NestedNames: [node in NestedNames | node.name]} as info
Targets:
- Name: CSV
Expand All @@ -28,4 +28,7 @@ Targets:
WatchlistName: FH_Exploitable_Device_to_HighValue
DisplayName: Exploitable Device to HighValue
SearchKey: Name
Overwrite: true
Overwrite: true
- Name: ADX
Enabled: false
Table: FalconHound
2 changes: 1 addition & 1 deletion actions/10-Neo4j/n4j_exposed_device_to_high_value.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Query: |
MATCH (y:Group {objectid:ObjectID})
MATCH (u:Computer {exposed:true})
WITH Name, COUNT(shortestPath((u)-[]->(y))) as Direct, COUNT(shortestPath((u)-[*1..]->(y))) as Nested, nodes(shortestPath((u)-[]->(y))) as DirectNames, nodes(shortestPath((u)-[*1..]->(y))) as NestedNames
WHERE Nested <> 0 and Direct <> 0
WHERE Nested <> 0 or Direct <> 0
RETURN {Name: Name, Direct: Direct, DirectNames: [node in DirectNames | node.name],Nested: Nested, NestedNames: [node in NestedNames | node.name]} as info
Targets:
- Name: CSV
Expand Down
2 changes: 1 addition & 1 deletion actions/10-Neo4j/n4j_owned_device_to_high_value.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Query: |
MATCH (y:Group {objectid:ObjectID})
MATCH (u:Computer {owned:true})
WITH Name, COUNT(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession]->(y))) as Direct, COUNT(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession*1..]->(y))) as Nested, nodes(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession]->(y))) as DirectNames, nodes(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession*1..]->(y))) as NestedNames
WHERE Nested <> 0 and Direct <> 0
WHERE Nested <> 0 or Direct <> 0
RETURN {Name: Name, Direct: Direct, DirectNames: [node in DirectNames | node.name],Nested: Nested, NestedNames: [node in NestedNames | node.name]} as info
Targets:
- Name: CSV
Expand Down
2 changes: 1 addition & 1 deletion actions/10-Neo4j/n4j_owned_user_to_high_value.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Query: |
MATCH (y:Group {objectid:ObjectID})
MATCH (u:User {owned:true})
WITH Name, COUNT(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession]->(y))) as Direct, COUNT(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession*1..]->(y))) as Nested, nodes(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession]->(y))) as DirectNames, nodes(shortestPath((u)-[:MemberOf|HasSession|AdminTo|AllExtendedRights|AddMember|ForceChangePassword|GenericAll|GenericWrite|Owns|WriteDacl|WriteOwner|CanRDP|ExecuteDCOM|AllowedToDelegate|ReadLAPSPassword|Contains|GPLink|AddAllowedToAct|AllowedToAct|WriteAccountRestrictions|SQLAdmin|ReadGMSAPassword|HasSIDHistory|CanPSRemote|SyncLAPSPassword|DumpSMSAPassword|AZMGGrantRole|AZMGAddSecret|AZMGAddOwner|AZMGAddMember|AZMGGrantAppRoles|AZNodeResourceGroup|AZWebsiteContributor|AZLogicAppContributo|AZAutomationContributor|AZAKSContributor|AZAddMembers|AZAddOwner|AZAddSecret|AZAvereContributor|AZContains|AZContributor|AZExecuteCommand|AZGetCertificates|AZGetKeys|AZGetSecrets|AZGlobalAdmin|AZHasRole|AZManagedIdentity|AZMemberOf|AZOwns|AZPrivilegedAuthAdmin|AZPrivilegedRoleAdmin|AZResetPassword|AZUserAccessAdministrator|AZAppAdmin|AZCloudAppAdmin|AZRunsAs|AZKeyVaultContributor|AZVMAdminLogin|AZVMContributor|AZLogicAppContributor|AddSelf|WriteSPN|AddKeyCredentialLink|DCSync|HadSession*1..]->(y))) as NestedNames
WHERE Nested <> 0 and Direct <> 0
WHERE Nested <> 0 or Direct <> 0
RETURN {Name: Name, Direct: Direct, DirectNames: [node in DirectNames | node.name],Nested: Nested, NestedNames: [node in NestedNames | node.name]} as info
Targets:
- Name: CSV
Expand Down
33 changes: 31 additions & 2 deletions actions/action_schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@
"Neo4j",
"BloodHound",
"MSGraph",
"Splunk"
"Splunk",
"LogScale"
]
},
"Version": {
Expand All @@ -54,7 +55,9 @@
"Splunk",
"Watchlist",
"BloodHound",
"BHSession"
"BHSession",
"LogScale",
"ADX"
]
},
"Enabled": {
Expand Down Expand Up @@ -143,6 +146,32 @@
"additionalProperties": false
}
},
{
"if": {
"properties": {
"Name": {
"const": "AXD"
}
}
},
"then": {
"properties": {
"BHQuery" : {
"type": "string"
},
"Name" : {
"type": "string"
},
"Table" : {
"type": "string"
},
"Enabled": {
"type": "boolean"
}
},
"additionalProperties": false
}
},
{
"if": {
"properties": {
Expand Down
35 changes: 35 additions & 0 deletions cmd/adxinit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package cmd

import (
"context"
"falconhound/internal"
"github.com/Azure/azure-kusto-go/kusto"
"log"
)

func AdxInitTable(creds internal.Credentials) error {

kustoConnectionStringBuilder := kusto.NewConnectionStringBuilder(creds.AdxClusterURL)
kustoConnectionString := kustoConnectionStringBuilder.WithAadAppKey(creds.AdxAppID, creds.AdxAppSecret, creds.AdxTenantID)

client, err := kusto.New(kustoConnectionString)
if err != nil {
log.Fatalf("failed to create Kusto client: %s", err)
return err
}

// Create a context
ctx := context.Background()
const command = (".create table FalconHound (Name: string, Description: string, EventID: string, BHQuery: string, EventData: dynamic, Timestamp: datetime)")

// Execute the control command
_, err = client.Mgmt(ctx, creds.AdxDatabase, kusto.NewStmt(command))
//_, err = client.Mgmt(ctx, creds.AdxDatabase, command)
if err != nil {
log.Fatalf("Failed to execute the control command: %s", err)
return err
}

LogInfo("[+] Table FalconHound created successfully, ready for ingestion.")
return nil
}
22 changes: 21 additions & 1 deletion config.yml-sample
Original file line number Diff line number Diff line change
Expand Up @@ -65,4 +65,24 @@ splunk:
hecport: 8088
hectoken: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
apiport: 8089
apitoken:
apitoken:

################################################
# Add your LogScale / Humio connection information here
################################################
logscale:
url: https://cloud.community.humio.com
token:
repository:

################################################
# Add your Azure Data Explorer connection information here
# This can be the same app as Sentinel or a different one
################################################
adx:
clusterUrl: https://xxx.westeurope.kusto.windows.net
database: enrichments
table: FalconHound
tenantID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
appID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
appSecret: xxxxxxxxxxxxxx
Loading

0 comments on commit 9fe80eb

Please sign in to comment.