This directory contains the USS components of the z/OS Enumeration and Security Assessment Toolkit.
The supported workflow centers on:
OMVSEnum.javawith itsOMVSSecurityChecks.javadependencysafauth.cfor optional native SAF authorization checksGhostWalker.javafor recursive permission auditingUNIXENUM.shfor generating a deploy-and-run JCL job
Standalone and legacy utilities are documented separately below.
The default OMVSEnum run and normal GhostWalker scans are designed for an ordinary, non-administrative USS identity.
OMVSEnum --active-probesperforms bounded state-changing tests involving temporary files, extended attributes, permission enforcement,su, and ownership changes. Review the target environment before enabling it.safauthrequests can be recorded by RACF, ACF2, or Top Secret even though they do not modify the tested resource.--extended-safperforms additional concrete SURROGAT and JES authorization checks. It does not submit jobs or switch identities.- Content scans and reports may contain passwords, keys, configuration data, user information, and security findings. Store them accordingly.
- Port scans and RACF database processing require explicit authorization.
| File | Classification |
|---|---|
OMVSEnum.java |
Primary USS enumerator and CLI |
OMVSSecurityChecks.java |
Internal OMVSEnum compile/runtime class; no standalone CLI |
safauth.c |
Optional 31-bit SAF authorization helper |
GhostWalker.java |
Standalone filesystem permission auditor |
portscan.java |
Java TCP scanner with optional experimental workers |
portscan.c |
C scanner with matching CLI; not deployed automatically |
racf2john.java |
Standalone offline RACF hash extractor |
OMVSEnum.sh |
Legacy predecessor retained for reference |
Makefile |
Builds deployed Java classes and safauth |
UNIXENUM.sh |
Generates deployment JCL |
UNIXENUM.jcl |
Generated file; do not edit directly |
*-ADCD-*.raw.txt / *.stderr.txt |
Checked-in sample reports |
- z/OS UNIX System Services
- Java 8 or newer for Java tools
javacandjava, normally under/usr/lpp/java/.../bin- IBM
c89or a compatible 31-bit z/OS C compiler forsafauth - compiler options supporting inline assembler and NOXPLINK
- BPXBATCH, IEBGENER, and JES for the generated JCL workflow
/bin/tsocmdand available TSO services for checks that bridge to TSO
Not every component is required. OMVSEnum continues without safauth, but
reports that native SAF evidence is unavailable.
The Makefile builds OMVSEnum, OMVSSecurityChecks, GhostWalker, the Java port scanner, and the optional native helper:
cd Unix
makeTargets:
make # safauth plus all executable Java JARs
make jars # all executable Java JARs, without safauth
make java # compile Java classes only
make cleanJava class files are isolated beneath build/; the executable JARs remain in
the working directory.
The default Java location is /usr/lpp/java/J8.0_64. Override it when needed:
make JAVA_HOME=/usr/lpp/java/J17.0_64Equivalent Java-only compilation:
/usr/lpp/java/J8.0_64/bin/javac \
OMVSEnum.java OMVSSecurityChecks.javaThe Makefile does not build the C port scanner or RACF2John:
c89 -o portscan portscan.c
javac racf2john.javaUNIXENUM.sh generates UNIXENUM.jcl. Configure the generator, regenerate
the JCL, and submit the generated job:
cd Unix
./UNIXENUM.sh > UNIXENUM.jclGenerated JCL and embedded source text remain within columns 1-72. Columns 73-80 are reserved for sequence information and are not used for content.
Site settings near the top of UNIXENUM.sh:
| Variable | Purpose |
|---|---|
STDOUT |
Destination for ENUM and OMVSEnum standard output |
folder |
USS deployment and working directory |
JAVAC |
Full target-system path to javac |
JAR |
Full target-system path to the jar utility |
JAVA |
Full target-system path to java |
C89 |
Full path to the 31-bit C compiler |
MAKE |
Full path to the make utility |
The generated job:
- removes previously deployed copies from
folder - uploads root
ENUMasENUM.rexx - uploads OMVSEnum, OMVSSecurityChecks, GhostWalker,
safauth.c,portscan.java, and the Makefile - runs selected USS-compatible ENUM sections
- invokes the Makefile to build one executable JAR per Java program
- builds
safauththrough the Makefile whenC89is available - runs passive OMVSEnum
- runs effective-user and world-writable GhostWalker scans
The GhostWalker step writes these report pairs under folder:
u.writable-by-user.txt u.world-writable.txt
etc.writable-by-user.txt etc.world-writable.txt
opt.writable-by-user.txt opt.world-writable.txt
usr.writable-by-user.txt usr.world-writable.txt
var.writable-by-user.txt var.world-writable.txt
portscan.java is compiled but not run. racf2john.java, portscan.c, and
the legacy OMVSEnum.sh are not deployed.
UNIXENUM.jcl is regenerated by
../.github/workflows/generate-jcl.yml
after pushes. Make changes in UNIXENUM.sh, not in generated JCL.
The generator passes JAVAC, JAR, and C89 to the Makefile and uses
JAVA for execution. Keep all three Java paths on the same target release.
OMVSEnum enumerates common USS privilege-escalation paths and security misconfigurations using evidence available to the current identity. Output is plain text without terminal-control sequences, making it suitable for JCL SYSOUT.
Usage: java -jar OMVSEnum.jar [options]
Enumeration:
-t, --thorough Enable slower scans
-s, --sections <list> Run only named sections
-x, --skip-sections <list> Skip named sections
-T, --threads <count> Worker count, 1-32 (default 2)
-A, --active-probes Enable bounded state-changing probes
-S, --extended-saf Add SURROGAT/JES candidate checks
Content search:
-P, --passwords Search for password
-K, --credentials Search for key/password/username
-J, --jcl-passwords Search password in *.jcl
-k, --search <regex> Add a custom regular expression
-R, --search-root <path> Add a content-search root
-L, --files-with-matches Print matching file names only
-C, --case-sensitive Use case-sensitive matching
Output:
-q, --quiet Findings and warnings only
-r, --report <file> Also write a report file
-d, --debug Diagnostics on stderr
-h, --help Show help
Available sections, emitted in deterministic order:
system,user,environment,capability,network,services,jobs,software,
files,audit,hfs,chown,racf,content
# Passive default scan with the default two workers
java -jar OMVSEnum.jar
# Passive scan with four workers
java -jar OMVSEnum.jar --threads 4
# Thorough file and software inspection
java -jar OMVSEnum.jar --thorough --sections software,files
# Run all default sections plus active probes
java -jar OMVSEnum.jar --active-probes
# Explicit active-probe-only sections
java -jar OMVSEnum.jar --active-probes --sections hfs,chown
# Expanded concrete SAF checks
java -jar OMVSEnum.jar --extended-saf --sections capability
# Case-insensitive credential scan
java -jar OMVSEnum.jar --sections content --credentials \
--search-root /etc --search-root /u
# List JCL files containing password
java -jar OMVSEnum.jar -s content -J -L -R /u
# Write normal output and a report
java -jar OMVSEnum.jar --report /tmp/omvsenum.txt--sectionsand--skip-sectionscannot be combined.hfsandchownrequire--active-probes.--search-rootrequires--passwords,--credentials,--jcl-passwords, or--search.- Selecting
contentrequires a content-search option. - A requested content search automatically enables
content. --extended-safrequires the capability section and enables it when using--sections.
Invalid arguments exit 2. Failure to open a requested report exits 1.
Sections can run concurrently, but output is buffered and emitted in the fixed section order. The banner and debug diagnostics use stderr. Standard output contains section results and can be redirected or sent to SYSOUT.
--quiet retains findings and warnings rather than suppressing all output.
Unavailable commands or permissions are identified; absence of evidence is
not treated as evidence of a secure configuration.
OMVSSecurityChecks.java is not a separate command. It is a package-private
class compiled with and invoked by OMVSEnum. It contains the ordinary-user
security checks for:
- SAF capabilities and ESM parity
- home directory, identity, and SSH posture
- privileged process and configuration trust
- APF/program-control and SUID/SGID exposure
- scheduled execution and audit/log integrity
- mounts, network services, IPC, and middleware trust
Recursive checks do not follow symbolic links and use bounded walk limits and command timeouts.
safauth is a 31-bit z/OS C helper that issues RACROUTE REQUEST=AUTH for
the current identity.
safauth [--vsam|-V] <class> <entity>
[read|update|control|alter] [volser]
Build and examples:
make
./safauth FACILITY BPX.SUPERUSER read
./safauth FACILITY BPX.SERVER read
./safauth DATASET SYS1.PARMLIB update DUMMY
./safauth --vsam DATASET OMVS.ROOT update--vsam is valid only for the DATASET class. A DATASET volume defaults to
DUMMY.
| Exit code | Meaning |
|---|---|
| 0 | Authorized |
| 4 | SAF made no decision |
| 8 | Denied |
| 16 | Built/run outside z/OS |
| 64 | Invalid usage |
| other nonzero | SAF/RACROUTE error |
OMVSEnum searches the current directory and PATH for the helper, validates
its usage contract, and continues with a warning when it is unavailable.
GhostWalker recursively reports selected files and directories. The default selection is everything the current process can write.
Usage: java -jar GhostWalker.jar [options] <path> [path ...]
Access selection (last selector wins):
-w, --only-user-writeable Effective user write access (default)
-r, --read Effective read or write access
-O, --only-owner-writeable Owner-write bit
-G, --only-group-writeable Group-write bit
-W, --only-world-writeable Others-write bit
Optional columns:
-u, --user Owner and group
-o, --owner Owner
-g, --group Group
-m, --last-modified Modification time
Output:
-c, --csv <file> CSV file
-f, --output <file> Plain-text file
Path types:
-F, --files-only
-d, --directories-only
Other:
-D, --debug Skipped-path diagnostics
-h, --help
Both writeable and writable long-option spellings are accepted where
implemented.
Examples:
make GhostWalker.jar
# Effective write access
java -jar GhostWalker.jar /u
# Effective read or write access
java -jar GhostWalker.jar --read /u
# World-writable entries
java -jar GhostWalker.jar --only-world-writeable /
# Group-writable entries with identity and timestamps
java -jar GhostWalker.jar -G -u -m /u
# CSV report
java -jar GhostWalker.jar -W -u -m --csv /tmp/world.csv /An explicitly supplied root symbolic link is resolved. Links encountered below that root are neither displayed nor followed, preventing link cycles. The resolved starting directory is included when it matches.
The banner always goes to stderr and does not contaminate redirected findings
or CSV output. Missing or unusable start paths are always reported on stderr.
Access errors below a valid root are silent by default. Exit 1 means a root or
subtree could not be searched; use --debug for details.
The Java and C implementations share the same interface and output contract:
portscan <host> <start-port> <end-port> [options]
Options:
-t, --timeout <ms> Connect timeout (default 1000)
-T, --threads <count> Experimental workers (1-64; default 1)
-d, --debug Show closed ports
-h, --help Show help
Both scanners are sequential by default. Parallelism is experimental and must
be explicitly enabled with --threads. Results are printed in ascending port
order regardless of completion order.
Exit 0 means at least one port was open, exit 1 means no open ports were found, and exit 2 indicates invalid input, name-resolution failure, or an internal scan error.
The Java implementation uses a bounded worker thread pool when experimental parallelism is requested:
make portscan.jar
java -jar portscan.jar localhost 1 1024
java -jar portscan.jar host.example 1 65535 \
--timeout 250 --threads 8The lowercase class name is intentional.
The C implementation uses bounded nonblocking socket multiplexing rather than
creating one pthread per worker. --threads controls the same user-visible
parallelism limit as the Java implementation:
c89 -o portscan portscan.c
./portscan localhost 1 1024
./portscan host.example 1 65535 \
--timeout 250 --threads 8It is not part of the Makefile or generated JCL. Validate compiler flags and resource limits on the target system before increasing parallelism or scanning a large range. The generated JCL builds only the Java implementation through the Makefile and does not run either scanner automatically.
racf2john.java reads RACF database binary files and emits hashes in a format
usable by John the Ripper:
javac racf2john.java
java RACF2John <racf-binary-file> [additional-files ...]It is not deployed by the JCL or built by the Makefile. Use it for authorized offline analysis only. RACF database copies and extracted hashes are highly sensitive.
OMVSEnum.sh is the original LinEnum-inspired shell implementation. It is
retained for reference and is superseded by OMVSEnum.java.
OMVSEnum.sh [-k keyword] [-e export-directory]
[-r report-name] [-t] [-h]
It is not deployed by UNIXENUM.jcl, mixes shell-specific constructs, and
contains active tests without the Java version's explicit opt-in model. Use
the Java implementation for current assessments.
Runtime reports are not checked into the repository. OMVSEnum writes to
standard output unless --output is supplied, while banners and diagnostics
use standard error. The generated JCL writes GhostWalker reports beneath its
configured USS working directory.
Other generated artifacts include .class and .jar files, the safauth
executable, user-selected OMVSEnum reports, and GhostWalker report files.
javaorjavacnot found: use the full/usr/lpp/java/.../binpath or update the Makefile/generator settings.safauthbuild fails: verify a 31-bitc89, inline-assembler support, andNOXPLINK; a 64-bit build is intentionally rejected.- OMVSEnum says SAF evidence is unavailable: place executable
safauthin the current directory orPATH. - A content section is rejected: provide at least one search preset or custom regex.
hfsorchownis rejected: add--active-probes.- GhostWalker exits 1 without an error: rerun with
--debug; one or more subtrees could not be searched. - Generated JCL is stale: run
./UNIXENUM.sh > UNIXENUM.jcl; do not patch the generated JCL manually.