SecureMyi.com Security and Systems Management Newsletter for the IBM i June 12, 2013 - Vol 3, Issue 30
What is an Exit Point? And How do I Write Exit Programs?
By Dan Riehl
Is There a Security Problem with IBM i?
The IBM i security architecture is VERY robust when we take the time to properly configure our user applications and system settings.
However, security exposures can be introduced by network-data-access tools like FTP and ODBC, but these do not indicate a failing on the part of IBM i security. Rather, the object level authority(i.e. permission) you provide to a user for "green screen" access using menus and textual screens is usually not the same authority you want to allow using network tools like FTP and ODBC.
The same object-level authority that enables a user to view the contents of the Payroll file is the same authority needed to download the file to a PC and post the content on the Internet. IBM recognized the potential areas for abuse and has provided an "Exit Point" facility to let you audit and control these sensitive network access points.
One important point on the need for Exit Programs is that without an Exit Program in place, the IBM i operating system provides NO LOGGING of access when tools like FTP are used. There is no FTP Log. So, Who downloaded your most sensitive file today? There is no way to know. Given that fact, Exit Programs that can audit and control server activities are an essential requirement for security and compliance.
This article describes how you can audit and control access using Exit Programs. I'll specifically show you an Exit Program, written in Control Language, that you can use to audit and control the FTP server Logon process for the IBM i.
What exactly is an Exit Point?
An exit point is simply a point in an application at which the application can optionally call an external program to perform customized processing. The IBM i FTP logon server application includes an exit point where you can hook your own program into the FTP logon processing logic to control who can log on and what will occur when a logon attempt is made. To tell the FTP server that you have an exit program, you use the WRKREGINF (Work with Registration Information) or ADDEXITPGM (Add Exit Program) command. We'll see the actual ADDEXITPGM command shortly.
Once you have registered your exit program, whenever a user attempts to log on to the FTP server, the server finds your program that's registered for the exit point, then calls your exit program, passing as parameters information about the user who's logging on. Your exit program then processes that information and takes the appropriate action, according to the security rules you implement in the exit program. Upon return, your exit program passes back a flag to either ACCEPT or REJECT the logon attempt.
Exit Point Names and Interfaces
Each exit point has a name and an Exit Point Interface. The Exit Point Interface is a list of input and output parameters the IBM server program exchanges with your exit program. The QIBM_QTMF_SVR_LOGON exit point occurs immediately after a user enters a user ID and an authentication string (i.e., password) to log on to the FTP server. This exit point typically uses the TCPL0100 interface. Figure 1 lists some of the FTP logon exit point interfaces. I use the TCPL0100 interface and SVR_LOGON exit point for my exit program, which I explain a bit later.
Let's look at an example to help clarify what a simple exit program can actually perform and how it interacts with an IBM supplied server process.
Using an exit program attached to the QIBM_QTMF_SVR_LOGON exit point, the FTP server calls your custom program so you can use your own logic to validate the logon attempt. With this or any exit program, your program must accept and return certain input parameters and output values. Among the input parameters in Figure 1 are the client's IP address, the user ID, and the authentication string. Among the output values your program must return is a flag indicating logon acceptance or rejection. If your program returns an "accept" indication, the normal IBM i security logon process continues. Thus, you aren't circumventing the FTP logon processing; rather, you are using an exit program to better control the logon attempt. If your program returns a "reject" return code, the FTP server notifies the user that the FTP logon failed.
Figure 1 - Parameters for the exit program
Parameter Format for the TCPL0100 exit point interface
Parameter Description Input or Output Type and length 1 Application identifier Input Binary (4) 2 User identifier Input Char (variable length) 3 Length of user identifier Input Binary (4) 4 Authentication string Input Char (variable length) 5 Length of authentication string Input Binary (4) 6 Client IP address Input Char (variable length) 7 Length of client IP address Input Binary (4) 8 Return code Output Binary (4) 9 User profile Output Char (10) 10 Password Output Char (10) 11 Initial current library Output Char (10) The following Parameteres were Added in OS/400 V4R4 for the TCPL0200 Interface: 12 Initial home directory Output Char (variable length) 13 Length of initial home direct Input/Output Binary (4) 14 Application-specific data Input/Output Char (variable length) 15 Length of applic-specific data Input Binary (4)
Again, let me reiterate, the exit program does not replace the server logon security protection, but rather is a logon preprocessor that intercepts the logon attempt before it reaches the IBM i logon processor. In the exit program, you can direct the FTP server to either accept or reject the logon attempt, and you can override certain FTP logon options as well.
Figure 2 - Return Code and Return Values
Output Parameters for the TCPL0100 Interface
Return Code User Profile Password Initial (Current) Library Used 0 Reject Ignored Ignored Ignored 1 Accept Original User ID Original Password From User profile 2 Accept Original User ID Original Password Return value 3 Accept Return value Return value From User profile specified in Return value 4 Accept Return value Return value Return value 5 Accept Return value Ignored From User profile specified in Return value 6 Accept Return value Ignored Return value
As you view the allowable values for the accept/reject return code flag in Figure 2, it's easier to understand how to use the user profile, password, and CURLIB return values. Depending on the value set for the accept/reject return code flag, you may need to place a value in one or more of these return parameters. The return parameters let you override the values that would normally be used in the FTP logon attempt. For instance, by using the value 3 for the accept/reject flag, you tell FTP you are overriding the values for the user profile and password with the values that your exit program places in the user profile and password return parameters. With other accept/reject flag values, you decide whether the value of CURLIB for the FTP session should come from the CURLIB value specified in the user profile object or from the CURLIB return parameter. Using the accept/reject flag with the other return parameters, you can dictate not only the profile and password for the FTP session but also the library used as the CURLIB for the session.
You should be aware that if your program returns a 5 or 6 value in the accept/reject flag, no further password validation occurs. Although this seems really scary, it can actually be a good method to enable anonymous FTP (i.e., letting an unnamed user access files you want to make publicly available via FTP). The authentication string for an anonymous FTP user typically is the user's e-mail address. However, an e-mail address typically cannot be used as a valid IBM i password. Thus, you can use values 5 or 6 to bypass password-checking. If, or when you decide to enable anonymous FTP, there are several issues that you must deal with, such as restricting anonymous users to accessing only your public files and to prohibit use of certain FTP subcommands, such as RCMD (Remote Command).
The Server Logon Exit Program and special handling for "Hacker Traps"
Now that you know what exit points are, let's explore a sample FTP logon exit point program. CL program FTPLIEXIT (Figure 3) does a few functions you may find useful. (To learn how to install this program, see "Installing Exit Program FTPLIEXIT," below.)
First, it records all FTP logon attempts by sending a formatted message to a message queue(i.e. The Audit Trail). There is no other easy way to see this Logon information on the IBM i, so FTPLIEXIT lets you easily see who's attempting to access your FTP server.
Second, I have added what I call "hacker traps." The first hacker trap checks to see whether someone is trying to log on as user ANONYMOUS. A hacker will routinely try anonymous FTP to a host to determine what operating system is in use, look at file structures, and so on. Since I want to disallow all use of anonymous FTP, I'll treat this anonymous logon attempt as an attempt to break into the system, and send a message to the system operator advising of the intrusion attempt.
The second hacker trap consists of testing the user's IP address to see whether the request is coming from outside my local subnet. If the user's IP address is not in my subnet, I again treat it as an intrusion attempt, and send a message to the system operator.
Figure 3 - The FTPLIEXIT program Source code
/* Program Name: FTPLIEXIT */ /* Purpose: This is the FTP server Login exit point program to */ /* record all FTP login attempts to a message queue, */ /* and to send attempted intrusion messages to the */ /* System Operator. */ /* Exit Point IS QIBM_QTMF_SVR_LOGON. */ /* Parameter format is TCPL0100. */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Copyright - Dan Riehl 2000-2013 ALL RIGHTS RESERVED */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ /* Security: Place in a secure library (I.E., PUBLIC(*EXCLUDE)). */ /* Place source code in a secure library. */ /* Do not allow retrieval of CL Source. */ /* Compilation: CRTCLPGM PGM(ASECURELIBRARY/FTPLIEXIT) + */ /* SRCFILE(ASECURELIBRARY/QCLSRC) + */ /* LOG(*NO) + */ /* ALWRTVSRC(*NO) + */ /* AUT(*EXCLUDE) */ /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ Pgm ( &P_AppID + &P_User + &P_UserLen + &P_Pwd + &P_PwdLen + &P_IP + &P_IPLen + &P_RtnOut + &P_UserOut + &P_PwdOut + &P_LibOut ) /* Paramaters for exit point interface format TCPL0100 */ /* Input Parms */ DCL &P_AppID *CHAR 4 /* Application ID (%BIN) */ /* 1 = FTP */ DCL &P_User *CHAR 999 /* User ID */ DCL &P_UserLen *CHAR 4 /* User ID Length (%BIN) */ DCL &P_Pwd *CHAR 999 /* Password */ DCL &P_PwdLen *CHAR 4 /* Password length (%BIN) */ DCL &P_IP *CHAR 15 /* Requester IP Address */ DCL &P_IPLen *CHAR 4 /* IP Address length (%BIN) */ /* Output parms */ DCL &P_RtnOut *CHAR 4 /* Return Code OUT */ /* Values are: */ /* 0=Reject */ /* 1=Accept, W/USRPRF CURLIB */ /* 2=Accept, W/ &P_LIbOut */ /* 3=Accept, W/USRPRF CURLIB */ /* AND &P_UserOut */ /* AND &P_PwdOut */ /* 4=Accept, W/ &P_LibOut */ /* AND &P_UserOut */ /* AND &P_PwdOut */ /* 5=Accept, W/USRPRF CURLIB */ /* AND &P_UserOut */ /* PASSWORD BYPASS */ /* 6=Accept, W/ P_LibOut */ /* AND &P_UserOut */ /* PASSWORD BYPASS */ DCL &P_UserOut *CHAR 10 /* User Profile OUT */ DCL &P_PwdOut *CHAR 10 /* Password OUT */ DCL &P_LibOut *CHAR 10 /* Curlib OUT */ /* END OF FORMAT TCPL0100 */ /* VARIABLES FOR BINARY CONVERSIONS */ DCL &AppID *DEC (1 0) DCL &UserLen *DEC (3 0) DCL &PwdLen *DEC (3 0) DCL &IPLen *DEC (3 0) /* MISC. WORK VARIABLES */ DCL &Time *CHAR 6 DCL &Date *CHAR 6 DCL &Message *CHAR 256 DCL &Accept1 *DEC 1 VALUE(1) DCL &Reject0 *DEC 1 VALUE(0) DCL &MsgQ *CHAR 10 VALUE('FTPLOG') DCL &MsgQLib *CHAR 10 VALUE('FTPLIB') /* MESSAGE-HANDLING VARIABLES */ DCL &MsgID *CHAR 7 DCL &MsgF *CHAR 10 DCL &MsgFLib *CHAR 10 DCL &MsgDta *CHAR 100 Monmsg (CPF0000 MCH0000) Exec(GoTo Error) ChgVar &AppID %BIN(&P_AppID) ChgVar &Userlen %BIN(&P_UserLen) ChgVar &Pwdlen %BIN(&P_PwdLen) ChgVar &IPLen %BIN(&P_IPLen) RtvSysVal QTIME &Time RtvSysVal QDATE &Date /* Send Intrusion Message if ANONYMOUS FTP Attempted */ IF (%SST(&P_User 1 &UserLen) = 'ANONYMOUS') Do Chgvar &Message + ('FTP INTRUSION by' + *BCAT %SST(&P_User 1 &UserLen) + *BCAT 'at IP Addr' + *BCAT %SST(&P_IP 1 &IPLen) + *BCAT 'at' + *BCAT %SST(&Time 1 2) + *CAT ':' + *CAT %SST(&Time 3 2) + *CAT ':' + *CAT %SST(&Time 5 2) + *BCAT %SST(&Date 1 2) + *CAT '/' + *CAT %SST(&Date 3 2) + *CAT '/' + *CAT %SST(&Date 5 2) + *CAT ': PWD=' + *CAT %SST(&P_Pwd 1 &PwdLen)) ChgVar %Bin(&P_RtnOut) Value(&Reject0) /* Return "Rejected"*/ SndPgmMsg MsgID(CPF9897) + Msgf(QCPFMSG) + MsgDta(&Message) + ToMsgQ(QSYSOPR) SndPgmMsg MsgID(CPF9897) + Msgf(QCPFMSG) + MsgDta(&Message) + ToMsgQ(FTPLIB/FTPLOG) GoTo EndCLPgm EndDo /* Send Intrusion Message if Attempt made from Outside Submet IP range */ IF (%SST(&P_IP 1 6) *NE '10.0.8') Do Chgvar &Message + ('FTP INTRUSION by' + *BCAT %SST(&P_User 1 &UserLen) + *BCAT 'at IP Addr' + *BCAT %SST(&P_IP 1 &IPLen) + *BCAT 'at' + *BCAT %SST(&Time 1 2) + *CAT ':' + *CAT %SST(&Time 3 2) + *CAT ':' + *CAT %SST(&Time 5 2) + *BCAT %SST(&Date 1 2) + *CAT '/' + *CAT %SST(&Date 3 2) + *CAT '/' + *CAT %SST(&Date 5 2)) /* Don't include the password here. It may be a valid user and password */ ChgVar %Bin(&P_RtnOut) Value(&Reject0) /* Return "Rejected"*/ SndPgmMsg MsgID(CPF9897) + Msgf(QCPFMSG) + MsgDta(&Message) + ToMsgQ(QSYSOPR) SndPgmMsg MsgID(CPF9897) + Msgf(QCPFMSG) + MsgDta(&Message) + ToMsgQ(FTPLIB/FTPLOG) GoTo EndCLPgm EndDo /* Looks like a valid request. Let IBM i check UserID and Password */ /* Here we log the attempted Login to the FTPLOG Message queue */ Chgvar &Message + ('FTP Logon' + *BCAT %SST(&P_User 1 &UserLen) + *BCAT 'From IP Addr' + *BCAT %SST(&P_IP 1 &IPLen) + *BCAT 'at' + *BCAT %SST(&Time 1 2) + *CAT ':' + *CAT %SST(&Time 3 2) + *CAT ':' + *CAT %SST(&Time 5 2) + *BCAT 'on' + *BCAT %SST(&Date 1 2) + *CAT '/' + *CAT %SST(&Date 3 2) + *CAT '/' + *CAT %SST(&Date 5 2)) SndPgmMsg MsgID(CPF9897) + Msgf(QCPFMSG) + MsgDta(&Message) + ToMsgQ(&MsgQLib/&MsgQ) ChgVar %Bin(&P_RtnOut) Value(&Accept1) /* Return "Accept" */ EndCLPgm: Return /* Normal end of program */ Error: /* if the exit program bombs, a message will be sent to the JobLog */ RcvMsg Msgtype(*LAST) + MsgDta(&MsgDta) + MsgID(&MsgID) + MsgF(&MsgF) + SndMsgFLib(&MsgFLib) /* Prevent loop, just in case */ MonMsg CPF0000 SndPgmMsg MsgID(&MsgID) + MsgF(&MsgFLib/&MsgF) + MsgDta(&MsgDta) + MsgType(*ESCAPE) /* Prevent loop, just in case */ MonMsg CPF0000 EndPgm
Detail of the Exit Program
As you can see, it's a simple CL program that accepts the QIBM_QTMF_SVR_LOGON parameter values shown in Figure 1 and assembles messages that are sent to a message queue. In hacker trap situations it rejects the log-on request, otherwise the log-on is accepted, and normal IBM i log-on validation proceeds.
Note: For the purpose of portability to various OS/400 and IBM i releases, the CL code used in the exit program is written to be a CLP source type, using older language constructs such as using the %BIN function, where with the advances in CL, we could have used the newer *INT data type.
Figure 4 below shows the FTPLOG message queue - a record of all FTP server log-on requests. This information is useful when you want to know who's been logging on, or attempting to break into your FTP server. The displayed information includes the requester's user ID, IP address, and time and date of the log-on attempt. For Anonymous log-on attempts, the authentication string(password or e-mail address) is also shown. Keep in mind that TCP/IP's limitations mean none of this information is guaranteed to be true; a hacker can, for example, forge the originating IP address on the log-on packet to make the log-on attempt appear to originate from another location. However, for nondevious users, you can expect the information to be accurate.
Figure 4 - Screen shot of the FTPLOG Message Queue (Audit Trail)
Display Messages System: SECURMYI Queue . . . . . : FTPLOG Program . . . . : *DSPMSG Library . . . : FTPLIB Library . . . : Severity . . . : 00 Delivery . . . : *HOLD Type reply (if required), press Enter. FTP Logon DRIEHL From IP Addr 220.127.116.11 at 12:28:54 on 04/12/13 FTP INTRUSION by PROGRAMMER1 From IP Addr 18.104.22.168 at 12:30:38 on 04/12/13 FTP Logon DEVELOPMENT From IP Addr 22.214.171.124 at 12:31:50 on 04/12/13 FTP Logon TESTAPP From IP Addr 126.96.36.199 at 12:33:17 on 04/12/13 FTP Logon BOSS From IP Addr 188.8.131.52 at 12:34:03 on 04/12/13 FTP INTRUSION by ANONYMOUS From IP Addr 10.1.2.1 at 12:34:42 on 04/13/13: PWDfirstname.lastname@example.org FTP Logon AS400DEV From IP Addr 111.135.291.111 at 12:35:36 on 04/14/13 FTP Logon DRIEHL From IP Addr 184.108.40.206 at 12:44:31 on 04/15/13 Bottom F3=Exit F11=Remove a message F12=Cancel F13=Remove all F16=Remove all except unanswered F24=More keys
Whenever a user Logs-on to the FTP server, an exit program attached to the FTP server Logon process, as this program is, will receive, in plain text, the UserID and Password. An exit program registered at this exit point could be used improperly to harvest passwords.
The current issue (June 12, 2013) of the SecureMyi Security Newsletter contains an article on further security exposures of the FTP Logon Exit program, and how it can be improperly used to compromise the integrity and security of your system. The article is entitled "Logon to IBM i with No UserID and No Password"
Registering your Exit Program
Once you've written and compiled an exit program for a TCP/IP exit point, you must tell the system the name of the program and library in which it resides. To do this, you must register the exit program with the WRKREGINF command. For our sample program here, Page down to the QIBM_QTMF_SVR_LOGON exit point and enter option 8 (Work with Exit Programs). You then enter the name of the exit program and the library in which it exists on the screen. In order to activate the new exit point program, you must restart the FTP server. Then, each time the FTP application reaches the exit point, your program will be called.
If the exit program encounters an error, an error message is written to the joblog of the FTP server job.
Time to Exit
The FTP server Log-on exit point lets you customize your FTP environment to a considerable extent. But in order to audit and control the activity of a user once logged on to FTP, you will need to examine the use of the FTP Server Request Validation exit point and exit program.
If you have any questions or comments about this article, or the exit program, please let me know.
Sidebar: Installing Exit Program FTPLIEXIT
1. Sign on as QSECOFR, or some other powerful profile with *ALLOBJ and *IOSYSCFG special authority. (Note: Users who have *USE authority to this powerful profile can potentially modify your exit program.)
2. Create library FTPLIB with AUT(*EXCLUDE).
CRTLIB LIB(FTPLIB) TEXT('FTP Log Library') AUT(*EXCLUDE)
3. Grant user QTCP *USE authority to the library.
GRTOBJAUT OBJ(FTPLIB) OBJTYPE(*LIB) USER(QTCP) AUT(*USE)
3. Create source file QCLSRC with AUT(*EXCLUDE).
CRTSRCPF FILE(FTPLIB/QCLSRC) TEXT('FTP CL Source code') AUT(*EXCLUDE)
4. Enter the source in the main article's Figure 4 into CLP member FTPLIEXIT.
Be sure to replace the subnet IP address with your own subnet requirements.
IF (%SST(&P_IP 1 6) *NE '10.0.8') Do
(Note: If the subnet you specify is different than 6 characters long, as in '127.125.13', which is 10 characters(including dots), you must change the %SST function to indicate the length of the subnet, in this case 10. Here you would need to use %SST(&P_IP 1 10)… the 10 indicating the length of the subnet string.)
5. Create the program in library FTPLIB.
CRTCLPGM PGM(FTPLIB/FTPLIEXIT) SRCFILE(FTPLIB/QCLSRC) + SRCMBR(FTPLIEXIT) LOG(*NO) ALWRTVSRC(*NO) AUT(*EXCLUDE)
6. Create message queue FTPLOG.
CRTMSGQ MSGQ(FTPLIB/FTPLOG) TEXT('FTP Login Log') AUT(*EXCLUDE)
7. Grant user QTCP *CHANGE authority to the FTPLOG message queue.
GRTOBJAUT OBJ(FTPLIB/FTPLOG) OBJTYPE(*MSGQ) USER(QTCP) AUT(*CHANGE)
8. Register the exit program with the ADDEXITPGM (Add Exit Program) command.
ADDEXITPGM EXITPNT(QIBM_QTMF_SVR_LOGON) FORMAT( TCPL0100) + PGMNBR( 1) PGM(FTPLIB/FTPLIEXIT)
9. Activate the new exit program. This requires resetting the FTP Server. (Note: When you modify and recompile the exit program, you must always restart the FTP server to have the changes take effect.)
About the Author
Dan performs IBM i security assessments and provides security consulting, remediation, forensic evaluations, and other customized security services for his clients. He also provides training in all aspects of IBM i security and other technical areas through The 400 School, Inc.