Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#ide stuff
*.idea
.idea/

# Binaries for programs and plugins
*.exe
*.exe~
Expand Down
Empty file modified embed/linux/triage/firewall.sh
100644 → 100755
Empty file.
43 changes: 40 additions & 3 deletions triage/firewall_linux.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,44 @@
package triage

import "github.com/UT-CTF/landschaft/util"
import (
"fmt"
"os"
"os/exec"
"strings"

func runFirewallTriage() {
util.RunAndPrintScript("triage/firewall.sh")
"github.com/UT-CTF/landschaft/util"
)

func runFirewallTriage() string {
result := util.RunAndPrintScript("triage/firewall.sh")
result = strings.ReplaceAll(result, "\n", " ")
result = strings.ReplaceAll(result, "\r", "")
result = strings.Join(strings.Fields(result), " ")
result = strings.ReplaceAll(result, "=", "")
result += "\t"

if strings.Contains(result, "No supported firewall") {
result = "No Firewall!\t"
}

result += getDomainInfo() + "\t"

return result
}

func getDomainInfo() string {
// Check 1: sssd.conf
content, err := os.ReadFile("/etc/sssd/sssd.conf")
if err == nil {
fmt.Println("sssd.conf")
return strings.TrimSpace(string(content))
}

// Check 2: realm list (if available)
out, err := exec.Command("realm", "list").Output()
if err == nil && len(out) > 0 {
return strings.TrimSpace(string(out))
}

return "Not Domain Jointed"
}
104 changes: 102 additions & 2 deletions triage/firewall_windows.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,109 @@
package triage

import (
"fmt"
"os/exec"
"strings"

"github.com/UT-CTF/landschaft/util"
)

func runFirewallTriage() {
util.RunAndPrintScript("triage/firewall.ps1")
func runFirewallTriage() string {
result := parseFirewall(util.RunAndPrintScript("triage/firewall.ps1")) + "\t"
result += getDomainStatus() + "\t"
return result
}

func parseFirewall(result string) string {
lines := strings.Split(result, "\n")

type iface struct {
name string
alias string
category string
}

var interfaces []iface
profileEnabled := make(map[string]bool)
profileState := make(map[string]string)
profilePolicy := make(map[string]string)
currentProfile := ""

for _, line := range lines {
Comment thread
thankgod4rob marked this conversation as resolved.
trimmed := strings.TrimSpace(line)

if strings.HasPrefix(trimmed, "Name") || strings.HasPrefix(trimmed, "----") || trimmed == "" || strings.HasPrefix(trimmed, "Interfaces:") {
continue
}

fields := strings.Fields(trimmed)

if strings.HasPrefix(trimmed, "Profile:") {
parts := strings.Split(trimmed, " - ")
profileName := strings.TrimSpace(strings.TrimPrefix(parts[0], "Profile:"))
if len(parts) > 1 {
profileEnabled[profileName] = strings.TrimSpace(parts[1]) == "Enabled"
}
continue
}

if strings.HasSuffix(trimmed, "Profile Settings:") {
currentProfile = strings.TrimSuffix(trimmed, " Profile Settings:")
continue
}

if currentProfile != "" {
if strings.HasPrefix(trimmed, "State") {
profileState[currentProfile] = strings.TrimSpace(strings.TrimPrefix(trimmed, "State"))
continue
}
if strings.HasPrefix(trimmed, "Firewall Policy") {
profilePolicy[currentProfile] = strings.TrimSpace(strings.TrimPrefix(trimmed, "Firewall Policy"))
continue
}
}

// interface line - last field is category, second to last is alias, rest is name
if len(fields) >= 3 {
category := fields[len(fields)-1]
alias := fields[len(fields)-2]
name := strings.Join(fields[:len(fields)-2], " ")
interfaces = append(interfaces, iface{name, alias, category})
}
}

var parts []string
for _, i := range interfaces {
enabled := "Disabled"
if profileEnabled[i.category] {
enabled = "Enabled"
}
state := profileState[i.category]
policy := profilePolicy[i.category]
parts = append(parts, fmt.Sprintf("%s - %s - %s (%s; State %s; Firewall Policy: %s)",
i.name, i.alias, i.category, enabled, state, policy))
}

return strings.Join(parts, "; ")
}

func getDomainStatus() string {
Comment thread
thankgod4rob marked this conversation as resolved.
Outdated
out, err := exec.Command("wmic", "computersystem", "get", "domain").Output()
if err != nil {
return "Not Domain Joined"
}

lines := strings.Split(strings.TrimSpace(string(out)), "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if line == "" || line == "Domain" {
continue
}
if line == "WORKGROUP" {
return "Not Domain Joined"
}
return line
}

return "Not Domain Joined"
}
63 changes: 59 additions & 4 deletions triage/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,72 @@ package triage

import (
"fmt"
"os"
"path/filepath"
"runtime"
"strings"

"github.com/UT-CTF/landschaft/util"
)

func Run() {
file, err := os.Create("triage.tsv")
if err != nil {
fmt.Println("Error creating csv file:", err)
}

fmt.Println(util.TitleColor.Render("Network"))
runNetworkTriage()

if _, err := file.Write([]byte(runNetworkTriage())); err != nil {
// ignore error
}

fmt.Println(util.TitleColor.Render("Users & Groups"))
runUsersTriage()

if _, err := file.Write([]byte(runUsersTriage())); err != nil {
// ignore error
}

fmt.Println(util.TitleColor.Render("OS Version"))
runOSVersionTriage()

if _, err := file.Write([]byte(runOSVersionTriage())); err != nil {
// ignore error
}

fmt.Println(util.TitleColor.Render("Firewall"))
runFirewallTriage()

if _, err := file.Write([]byte(runFirewallTriage())); err != nil {
// ignore error
}

errF := file.Close()
if errF != nil {

}

printCopyInstructions()

}

func printCopyInstructions() {
sshConn := os.Getenv("SSH_CONNECTION")
fields := strings.Fields(sshConn)
serverUser := os.Getenv("USER")
serverIP := "<ip>"
if len(fields) >= 3 {
serverIP = fields[2]
}

exePath, _ := os.Executable()
tsvPath := filepath.Join(filepath.Dir(exePath), "triage.tsv")

catCmd := "cat"
if runtime.GOOS == "windows" {
catCmd = "type"
serverUser = os.Getenv("USERNAME")
}

fmt.Println("To copy to clipboard:")
fmt.Printf("\tIf your host is linux: ssh %s@%s \"%s %s\" | xclip -selection clipboard\n", serverUser, serverIP, catCmd, tsvPath)
fmt.Printf("\tIf your host is windows: ssh %s@%s \"%s %s\" | clip.exe\n\n\n", serverUser, serverIP, catCmd, tsvPath)
}
Loading