mirror of
https://github.com/BishopFox/cloudfox.git
synced 2026-11-09 01:29:32 -10:00
190 lines
5.4 KiB
Go
190 lines
5.4 KiB
Go
package aws
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"os"
|
|
"runtime"
|
|
"strings"
|
|
|
|
"github.com/BishopFox/cloudfox/internal"
|
|
"github.com/aws/aws-sdk-go-v2/aws"
|
|
"github.com/aws/aws-sdk-go-v2/service/sts"
|
|
"github.com/fatih/color"
|
|
)
|
|
|
|
var cyan = color.New(color.FgCyan).SprintFunc()
|
|
var red = color.New(color.FgRed).SprintFunc()
|
|
var yellow = color.New(color.FgRed).SprintFunc()
|
|
var blue = color.New(color.FgBlue).SprintFunc()
|
|
var magenta = color.New(color.FgMagenta).SprintFunc()
|
|
var green = color.New(color.FgGreen).SprintFunc()
|
|
var AWSRegions = []string{"us-east-1", "us-east-2", "us-west-1", "us-west-2", "af-south-1", "ap-east-1", "ap-south-1", "ap-northeast-3", "ap-northeast-2", "ap-southeast-1", "ap-southeast-2", "ap-northeast-1", "ca-central-1", "eu-central-1", "eu-west-1", "eu-west-2", "eu-south-1", "eu-west-3", "eu-north-1", "me-south-1", "sa-east-1"}
|
|
var sharedLogger = internal.TxtLogger()
|
|
|
|
func GetIamSimResult(SkipAdminCheck bool, roleArnPtr *string, iamSimulatorMod IamSimulatorModule, localAdminMap map[string]bool) (string, string) {
|
|
var adminRole, canRolePrivEsc string
|
|
canRolePrivEsc = "Skipping, no pmapper data"
|
|
if !SkipAdminCheck {
|
|
var isRoleAdminBool bool
|
|
// If we've seen the function before, skip the isRoleAdmin function and just pull the value from the localAdminMap
|
|
|
|
if aws.ToString(roleArnPtr) == "" {
|
|
return "", ""
|
|
}
|
|
roleArn := aws.ToString(roleArnPtr)
|
|
|
|
if val, ok := localAdminMap[roleArn]; ok {
|
|
if val {
|
|
// we've seen it before and it's an admin
|
|
adminRole = "YES"
|
|
} else {
|
|
// we've seen it before and it's NOT an admin
|
|
adminRole = "No"
|
|
}
|
|
} else {
|
|
isRoleAdminBool = isRoleAdmin(iamSimulatorMod, roleArnPtr)
|
|
|
|
if isRoleAdminBool {
|
|
adminRole = "YES"
|
|
localAdminMap[roleArn] = true
|
|
} else {
|
|
adminRole = "No"
|
|
localAdminMap[roleArn] = false
|
|
}
|
|
}
|
|
|
|
if isRoleAdminBool {
|
|
adminRole = "YES"
|
|
} else {
|
|
adminRole = "No"
|
|
}
|
|
|
|
} else {
|
|
adminRole = "Skipped"
|
|
canRolePrivEsc = "Skipped"
|
|
}
|
|
return adminRole, canRolePrivEsc
|
|
}
|
|
|
|
func isRoleAdmin(iamSimMod IamSimulatorModule, principal *string) bool {
|
|
adminCheckResult := iamSimMod.isPrincipalAnAdmin(principal)
|
|
if adminCheckResult {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
|
|
}
|
|
|
|
func InitPmapperGraph(Caller sts.GetCallerIdentityOutput, AWSProfile string, Goroutines int, PmapperDataBasePath string) (PmapperModule, error) {
|
|
pmapperMod := PmapperModule{
|
|
Caller: Caller,
|
|
AWSProfile: AWSProfile,
|
|
Goroutines: Goroutines,
|
|
PmapperDataBasePath: PmapperDataBasePath,
|
|
}
|
|
err := pmapperMod.initPmapperGraph()
|
|
if err != nil {
|
|
return pmapperMod, err
|
|
}
|
|
return pmapperMod, nil
|
|
|
|
}
|
|
|
|
func generatePmapperDataBasePaths(accountId *string) (string, string) {
|
|
var edgesPath, nodesPath string
|
|
|
|
if runtime.GOOS == "darwin" {
|
|
dir, err := os.UserHomeDir()
|
|
if err != nil {
|
|
log.Fatal("Could not get homedir")
|
|
}
|
|
edgesPath = fmt.Sprintf("%s/Library/Application Support/com.nccgroup.principalmapper/%s/graph/edges.json", dir, aws.ToString(accountId))
|
|
nodesPath = fmt.Sprintf("%s/Library/Application Support/com.nccgroup.principalmapper/%s/graph/nodes.json", dir, aws.ToString(accountId))
|
|
|
|
} else if runtime.GOOS == "linux" || runtime.GOOS == "freebsd" || runtime.GOOS == "openbsd" {
|
|
xdg, ok := os.LookupEnv("XDG_DATA_HOME")
|
|
if ok {
|
|
edgesPath = fmt.Sprintf("%s%s/graph/edges.json", xdg, aws.ToString(accountId))
|
|
nodesPath = fmt.Sprintf("%s%s/graph/nodes.json", xdg, aws.ToString(accountId))
|
|
} else {
|
|
dir, err := os.UserHomeDir()
|
|
if err == nil {
|
|
edgesPath = fmt.Sprintf("%s/.local/share/principalmapper/%s/graph/edges.json", dir, aws.ToString(accountId))
|
|
nodesPath = fmt.Sprintf("%s/.local/share/principalmapper/%s/graph/nodes.json", dir, aws.ToString(accountId))
|
|
} else {
|
|
log.Fatal("Could not homedir.")
|
|
}
|
|
}
|
|
|
|
} else if runtime.GOOS == "windows" {
|
|
dir, err := os.UserConfigDir()
|
|
if err != nil {
|
|
log.Fatal("Could not get userconfigdir")
|
|
}
|
|
edgesPath = fmt.Sprintf("%s\\principalmapper%s\\graph\\edges.json", dir, aws.ToString(accountId))
|
|
nodesPath = fmt.Sprintf("%s\\principalmapper%s\\graph\\nodes.json", dir, aws.ToString(accountId))
|
|
|
|
}
|
|
|
|
return edgesPath, nodesPath
|
|
}
|
|
|
|
func pmapperIsRoleAdmin(pmapperMod PmapperModule, principal *string) bool {
|
|
return pmapperMod.DoesPrincipalHaveAdmin(aws.ToString(principal))
|
|
|
|
}
|
|
|
|
func pmapperHasPathToAdmin(pmapperMod PmapperModule, principal *string) bool {
|
|
return pmapperMod.DoesPrincipalHavePathToAdmin(aws.ToString(principal))
|
|
|
|
}
|
|
|
|
func GetPmapperResults(SkipAdminCheck bool, pmapperMod PmapperModule, roleArn *string) (string, string) {
|
|
var adminRole, canRolePrivEsc string
|
|
|
|
var isRoleAdminBool bool
|
|
var canPrivEscBool bool
|
|
if !SkipAdminCheck {
|
|
|
|
if aws.ToString(roleArn) == "" {
|
|
return "", ""
|
|
}
|
|
isRoleAdminBool = pmapperIsRoleAdmin(pmapperMod, roleArn)
|
|
canPrivEscBool = pmapperHasPathToAdmin(pmapperMod, roleArn)
|
|
if canPrivEscBool {
|
|
canRolePrivEsc = "YES"
|
|
} else {
|
|
canRolePrivEsc = "No"
|
|
}
|
|
|
|
if isRoleAdminBool {
|
|
adminRole = "YES"
|
|
} else {
|
|
adminRole = "No"
|
|
}
|
|
} else {
|
|
adminRole = "Skipped"
|
|
canRolePrivEsc = "Skipped"
|
|
}
|
|
return adminRole, canRolePrivEsc
|
|
}
|
|
|
|
// take an arn and return the resource name
|
|
func GetResourceNameFromArn(arn string) string {
|
|
parts := strings.Split(arn, "/")
|
|
resourceName := parts[len(parts)-1]
|
|
|
|
return resourceName
|
|
}
|
|
|
|
func removeStringFromSlice(slice []string, element string) []string {
|
|
for i, v := range slice {
|
|
if v == element {
|
|
return append(slice[:i], slice[i+1:]...)
|
|
}
|
|
}
|
|
return slice
|
|
}
|