Skip to content

Commit

Permalink
πŸ—“ Dec 31, 2022 12:52:53 PM
Browse files Browse the repository at this point in the history
βž• deps added/updated
πŸ”₯ remove unused spinner
🚧 aws utils
✨ aws utils get-caller-identity
πŸš€ better logging for gcp
  • Loading branch information
securisec committed Dec 31, 2022
1 parent eb99235 commit 4f5e6c2
Show file tree
Hide file tree
Showing 10 changed files with 310 additions and 95 deletions.
7 changes: 4 additions & 3 deletions TODO
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,14 @@ Todo:
☐ session-json for aws is not the right format
☐ gcp set parent as project if one is not set. get project from json file
☐ aws all regions flag
☐ aws : helper : ebs : ability for bruteforcing all regions for specific aws permission
☐ aws : helper : sts : get caller identity
☐ aws : helper : cognito : get unauth creds
☐ gcp : helper : iam : get service accounts and their roles
☐ optionally pass known values as a json file
☐ if session-json is being used, check if expiration is valid
☐ flag that will show all possible valid keys for known values
☐ πŸ› bug with debug message which says azure although it is aws
☐ πŸ’š πŸ› build for arm mac doesnt work on zsh
☐ ✨ sas-token enumeration for azure
☐ πŸ’‘ local database?

Helpers:

Expand Down
19 changes: 19 additions & 0 deletions cli/cmd/aws_utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package cmd

import (
"github.com/spf13/cobra"
)

var awsUtilsCmd = &cobra.Command{
Use: "utils",
Short: "AWS utilities",
PreRun: func(cmd *cobra.Command, args []string) {
if len(args) == 0 {
cmd.Help()
}
},
}

func init() {
awsCmd.AddCommand(awsUtilsCmd)
}
212 changes: 212 additions & 0 deletions cli/cmd/aws_utils_ec2_snapshots.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
package cmd

// TODO πŸ”₯ 🚧
// import (
// "context"
// "encoding/xml"
// "fmt"
// "io"
// "net/http"
// "net/url"
// "strings"
// "sync"
// "time"

// "github.com/aws/aws-sdk-go/aws/credentials"
// v4 "github.com/aws/aws-sdk-go/aws/signer/v4"
// "github.com/securisec/cliam/aws/signer"
// "github.com/securisec/cliam/logger"
// "github.com/securisec/cliam/shared"
// "github.com/spf13/cobra"
// )

// var awsUtilsEc2SnapshotCmd = &cobra.Command{
// Use: "ec2-snapshots",
// Short: "Enumerate AWS EC2 snapshots across specified regions",
// Run: awsUtilsEc2SnapshotCmdFunc,
// PreRun: awsLoadEnvVarsFirst,
// }

// func init() {
// awsUtilsCmd.AddCommand(awsUtilsEc2SnapshotCmd)
// awsUtilsEc2SnapshotCmd.Flags().StringSlice("regions", []string{}, "AWS Regions")
// awsUtilsEc2SnapshotCmd.Flags().Bool("all", false, "Enumerate all regions")
// awsUtilsEc2SnapshotCmd.Flags().Int("max-results", 5, "Max results to get")
// awsUtilsEc2SnapshotCmd.Flags().String("description", "", "Description to search for. Can use the format *search query*")
// awsUtilsEc2SnapshotCmd.Flags().String("owner-id", "", "Owner ID to search for")

// awsUtilsEc2SnapshotCmd.RegisterFlagCompletionFunc("regions", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
// return aws_Regions, cobra.ShellCompDirectiveNoFileComp
// })
// }

// func awsUtilsEc2SnapshotCmdFunc(cmd *cobra.Command, args []string) {
// // parse flags
// regions, _ := cmd.Flags().GetStringSlice("regions")
// all, _ := cmd.Flags().GetBool("all")
// maxResults, _ := cmd.Flags().GetInt("max-results")
// description, _ := cmd.Flags().GetString("description")
// ownerID, _ := cmd.Flags().GetString("owner-id")

// // enumerate all regions
// if all {
// regions = aws_Regions
// }

// // sanity check flags
// if description == "" && ownerID == "" {
// logger.LoggerStdErr.Fatal().Msg("You must specify either a description or an owner ID")
// }
// if description != "" && ownerID != "" {
// logger.LoggerStdErr.Fatal().Msg("You must specify either a description or an owner ID")
// }

// if len(regions) == 0 {
// logger.LoggerStdErr.Fatal().Msg("You must specify at least one region")
// }

// // get credentials
// key, secret, token, _ := getCredsAndRegion()
// creds := signer.SetCredentials(key, secret, token, awsProfile)

// // create waitgroup
// wg := &sync.WaitGroup{}
// wg.Add(1)

// ch := make(chan _snapshotType)
// max := make(chan struct{}, MaxThreads)

// // start goroutine to process results
// go func() {
// defer wg.Done()

// for s := range ch {
// wg.Add(1)

// go func(wg *sync.WaitGroup, s _snapshotType) {
// max <- struct{}{}
// ctx, cancel := context.WithTimeout(context.Background(), time.Duration(RequestTimeout)*time.Second)

// defer func() {
// cancel()
// wg.Done()
// <-max
// }()

// req, err := _awsUtilsEc2RequestGen(ctx, s)
// if err != nil {
// logger.LogError(err, "Error generating request")
// return
// }

// res, err := http.DefaultClient.Do(req)
// if err != nil {
// logger.LogError(err, "Error performing request")
// return
// }

// body, err := io.ReadAll(res.Body)
// if err != nil {
// logger.LogError(err, "Error reading response body")
// return
// }
// if err := res.Body.Close(); err != nil {
// logger.LogError(err, "Error closing response body")
// return
// }

// var snapshots _snapshotRes
// if err := xml.Unmarshal(body, &snapshots); err != nil {
// logger.LogError(err, "Error unmarshalling response body")
// }

// if len(snapshots.Snapshots.Items) > 0 {
// for _, item := range snapshots.Snapshots.Items {
// logger.Logger.Info().
// Str("region", s.Region).
// Str("snapshot-id", item.SnapshotID).
// Str("owner-id", item.OwnerID).
// Str("description", item.Description).
// Int64("volume-size", item.VolumeSize).
// Msg(shared.GetMessageColor("success"))
// }
// }

// // wg.Done()

// }(wg, s)

// }
// }()

// // send requests to goroutine
// for _, region := range regions {
// ch <- _snapshotType{
// Region: region,
// Filter: description,
// OwnerId: ownerID,
// Creds: creds,
// MaxResults: maxResults,
// }
// }

// close(ch)
// wg.Wait()

// }

// type _snapshotRes struct {
// Snapshots struct {
// Items []struct {
// Description string `xml:"description"`
// Encrypted bool `xml:"encrypted"`
// OwnerID string `xml:"ownerId"`
// Progress string `xml:"progress"`
// SnapshotID string `xml:"snapshotId"`
// StartTime string `xml:"startTime"`
// State string `xml:"state"`
// VolumeID string `xml:"volumeId"`
// VolumeSize int64 `xml:"volumeSize"`
// StorageTier string `xml:"storageTier"`
// } `xml:"item"`
// } `xml:"snapshotSet"`
// }

// type _snapshotType struct {
// Region string `json:"region"`
// Filter string `json:"filter"`
// OwnerId string `json:"ownerId"`
// MaxResults int `json:"maxResults"`
// Creds *credentials.Credentials `json:"creds"`
// }

// func _awsUtilsEc2RequestGen(ctx context.Context, t _snapshotType) (*http.Request, error) {
// reqUrl := fmt.Sprintf("https://ec2.%s.amazonaws.com/", t.Region)

// body := url.Values{}
// body.Set("Action", "DescribeSnapshots")
// body.Set("Version", "2016-11-15")
// body.Set("MaxResults", fmt.Sprintf("%d", t.MaxResults))
// if t.Filter != "" {
// body.Add("Filter.1.Name", "description")
// body.Add("Filter.1.Value.1", t.Filter)
// }
// // TODO handle ownerId
// data := strings.NewReader(body.Encode())

// req, err := http.NewRequestWithContext(ctx, "POST", reqUrl, data)
// if err != nil {
// return nil, err
// }
// req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
// req.Header.Add("Accept", "application/json")

// signer := v4.NewSigner(t.Creds)
// logger.LogDebugVerbose("url", req.URL.String())

// if _, err := signer.Sign(req, data, "ec2", t.Region, time.Now()); err != nil {
// return nil, err
// }

// return req, nil
// }
59 changes: 59 additions & 0 deletions cli/cmd/aws_utils_sts_caller_identity.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"context"
"encoding/json"

"github.com/securisec/cliam/aws/policy"
"github.com/securisec/cliam/aws/signer"
"github.com/securisec/cliam/logger"
"github.com/securisec/cliam/shared"
"github.com/spf13/cobra"
)

var awsUtilsStsCallerIdentityCmd = &cobra.Command{
Use: "sts-get-caller-identity",
Short: "Enumerate AWS EC2 snapshots across specified regions",
Run: awsUtilsStsCallerIdentityCmdFunc,
PreRun: awsLoadEnvVarsFirst,
}

func init() {
awsUtilsCmd.AddCommand(awsUtilsStsCallerIdentityCmd)
}

func awsUtilsStsCallerIdentityCmdFunc(cmd *cobra.Command, args []string) {
// get credentials
key, secret, token, region := getCredsAndRegion()
creds := signer.SetCredentials(key, secret, token, awsProfile)

pol := policy.STSPolicies["GetCallerIdentity"]
url, err := pol.GetRequestURL(region, "sts", awsEndpoint)
if err != nil {
logger.LoggerStdErr.Fatal().Err(err).Msg("Failed to get request URL")
}
pol.ReqURL = url

_, res, body, err := signer.MakeScannerRequest(context.Background(), region, "sts", &pol, creds)
if err != nil {
logger.LoggerStdErr.Fatal().Err(err).Msg("Failed to make request")
}

if res.StatusCode != 200 {
logger.LoggerStdErr.Fatal().Msgf("Failed to get caller identity: %d", res.StatusCode)
}

var r map[string]interface{}
json.Unmarshal(body, &r)

rr, ok := r["GetCallerIdentityResponse"].(map[string]interface{})
if !ok {
logger.LoggerStdErr.Fatal().Msg("Failed to parse response")
}

l := logger.Logger.Info()
for k, v := range rr["GetCallerIdentityResult"].(map[string]interface{}) {
l.Str(k, v.(string))
}
l.Msg(shared.GetMessageColor("success"))
}
6 changes: 5 additions & 1 deletion cli/cmd/gcp_bruteforce.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@ func gcpBruteforceCmdFunc(_ *cobra.Command, _ []string) {

ctx := context.Background()
sa, project, region, zone := getSaAndRegion()
cliGcpLogRegion(region, zone)
cliGcpLogRegion(map[string]string{
"region": region,
"zone": zone,
"project": project,
})

if accessToken == "" {
at, err := gcp.GetAccessToken(ctx, sa)
Expand Down
6 changes: 5 additions & 1 deletion cli/cmd/gcp_rest_enumerate.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ func gcpRestEnumerateCmdFunc(_ *cobra.Command, args []string) {
accessToken := gcpAccessToken

sa, projectID, region, zone := getSaAndRegion()
cliGcpLogRegion(region, zone)
cliGcpLogRegion(map[string]string{
"region": region,
"zone": zone,
"project": projectID,
})
if projectID != "" {
gcpRestParent["project"] = projectID
}
Expand Down
Loading

0 comments on commit 4f5e6c2

Please sign in to comment.