Files
cloudfox/aws/shared.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
}