-
Notifications
You must be signed in to change notification settings - Fork 21
Expand file tree
/
Copy pathENUM
More file actions
2150 lines (1846 loc) · 71.8 KB
/
ENUM
File metadata and controls
2150 lines (1846 loc) · 71.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* REXX */
/*
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$7'` `'!$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$$$$$$7' `$$$$$$$$$ $ Y$$ $ $$$ $ YP $$
$$$$7' $$$:. :$$$$$$$$ $$$$$ L ?$ $ $$$ $ s s $$
$$$' '7$' `$$$$$$$ $$ $L ? $ $$$ $ $$$$ $$
$$ .4$$$a :$$$$$$$ $$$$$ $$L $ Y$P $ $$$$ $$
$ .4$$$$$$$ $$ .$$$$$$$$ $ $$$L $L J$ $$$$ $$
: :$$$$$$$$' $$$$ ~'$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
! '!:$$$7' '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
`+$$$$$$$$$$$P Y$$$$$P Y$$$$$$$$$$
. l$$$$$$$$$$ Y$P $$$$$ $$$ $$$$$$$$$$
:: .4$$$$$$$$$$$$$$P S$$$$$$ $$$ $$$$$$$$$$
$$a. .$ .4$$$$$$$$$$$$$$P l$$$$$$$$ Y$P $$$$$$$$$$
$$$$b. $$$$b. .4$$$$$$$$$$$$$$$$$ $$ $L J$$$$$$$$$$
$$$$$$$$A. .4$$$$$$$A. .4$$$$$$$$$$$$$$$$$$$$$$$$$$$$ss$$$$$$$$$$$$$$$$$$$$
$$$$$$$$$$$$$$$$$$$$$$$$$.$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
$$Y' '?$$
$$ z/OS Enumeration Pentesting Tool $$
$$ $$
$$ Arguments: HELP, ALL, APF, CAT, JOB, PATH, SEC, SVC, TSTA, TSOT, $$
$$ USSU, VERS, WHO $$
$$b. .d$$
$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$SoF!
*/
/*------------------------------------------------------------------*\
|* z/OS System Enumeration Tool *|
|* *|
|* Description: Enumerates z/OS system information for use in *|
|* penetration testing and security assessments. *|
|* *|
|* Arguments: *|
|* ALL - Display all information *|
|* APF - APF authorized datasets *|
|* CAT - Display master catalog *|
|* JOB - Display executing job name *|
|* PATH - Display dataset concatenations *|
|* SEC - Security manager information *|
|* SVC - Display SVC information *|
|* TSTA - Display TESTAUTH authorization *|
|* TSOT - Display TSO AUTHCMD/AUTHPGM tables *|
|* USSU - Display USS/OMVS user list *|
|* VERS - Operating system version info *|
|* WHO - Currently logged on users (TSO/OMVS) *|
|* *|
|* Credits: Mark Zelden (IPLINFO), CBT Tape Files 221/496, *|
|* Ayoub Elaassal, Jim Taylor, Davide Girardi *|
\*------------------------------------------------------------------*/
NUMERIC DIGITS 20
/*==================================================================*/
/* EBCDIC-SAFE BRACKET/BRACE PLACEHOLDERS */
/*==================================================================*/
/* These placeholders work across all EBCDIC code pages. */
/* After downloading output, use sed to replace with actual chars: */
/* */
/* sed 's/<<LB>>/[/g; s/<<RB>>]/]/g; s/<<LC>>/{/g; s/<<RC>>}/}/g' */
/* */
/* Or use any find/replace tool: */
/* <<LB>> -> [ (left square bracket) */
/* <<RB>> -> ] (right square bracket) */
/* <<LC>> -> { (left curly brace) */
/* <<RC>> -> } (right curly brace) */
/*==================================================================*/
/* Initialize global assessment variables */
assessMode = 0
findings.0 = 0
findingtemplate.0 = 0
verificationcaption.0 = 0
verificationsteps.0 = 0
/* Global variables for AddToArray */
globalVars = 'tsoUsers. tasks. tasksUsers. omvs. omvsUsers.',
'jobs. jobsUsers. system.'
/* Global variables for findings */
findingsVars = 'assessMode findings. findingtemplate.',
'verificationcaption. verificationsteps. ipAddress smfid VSTEP_DELIM'
/* Delimiter for verification steps */
VSTEP_DELIM = '|~~|'
ipAddress = ''
smfid = ''
/* Parse arguments and environment */
PARSE SOURCE s1 s2 prg s3 name s4 s5 space .
PARSE UPPER ARG type restArgs
/* Parse ASSESS subarguments if needed */
IF type == 'ASSESS' THEN DO
PARSE VAR restArgs ipAddress
/* Initialize assessment mode */
assessMode = 1
findings.0 = 0
/* Get SMFID from system */
smfid = GetLparName()
END
/* Adjust for ISPF environment */
IF space == 'ISPF' THEN DO
SAY ''
SAY ''
SAY ''
END
/* Show banner for non-ASSESS modes */
IF type /== 'ASSESS' THEN CALL ShowBanner
/* Set program name based on environment */
IF prg /== '?' & space /== 'OMVS' THEN
prgname = name||'('||prg||')'
ELSE
prgname = name
/* Main dispatch logic */
SELECT
WHEN type == 'APF' THEN CALL EnumApf
WHEN type == 'CAT' THEN CALL EnumCatalog
WHEN type == 'JOB' THEN CALL EnumJobname
WHEN type == 'PATH' THEN DO
IF space /== 'OMVS' THEN CALL EnumPath
ELSE SAY 'DDNAME not supported in OMVS'
END
WHEN type == 'SEC' THEN CALL EnumSecurity
WHEN type == 'SVC' THEN CALL EnumSvc
WHEN type == 'TSTA' THEN CALL EnumTestauth
WHEN type == 'TSOT' THEN CALL EnumTsoTables
WHEN type == 'USSU' THEN CALL EnumUssUsers
WHEN type == 'VERS' THEN CALL EnumVersion
WHEN type == 'WHO' THEN CALL EnumUsers
WHEN type == 'ALL' THEN DO
CALL PrintBanner 'z/OS System Enumeration'
SAY 'Executing from:' prgname
SAY ''
CALL EnumVersion
CALL EnumSecurity
CALL EnumJobname
CALL EnumUsers
CALL EnumApf
CALL EnumSvc
CALL EnumTestauth
CALL EnumUssUsers
CALL EnumTsoTables
IF space /== 'OMVS' THEN DO
CALL EnumPath 1
END
END
WHEN type == 'ASSESS' THEN DO
/* Run all enumeration functions normally */
CALL PrintSectionBanner 'z/OS System Enumeration (Assessment Mode)'
SAY 'Executing from:' prgname
SAY 'Target IP:' ipAddress
SAY 'SMFID:' smfid
SAY ''
CALL EnumVersion
CALL EnumSecurity
CALL EnumJobname
CALL EnumUsers
CALL EnumApf
CALL EnumSvc
CALL EnumTestauth
CALL EnumUssUsers
CALL EnumTsoTables
IF space /== 'OMVS' THEN DO
CALL EnumPath 1
END
/* Output JSON assessment results at the end */
CALL OutputAssessmentJSON
END
OTHERWISE DO
CALL ShowUsage
EXIT 8
END
END
EXIT 0
/*------------------------------------------------------------------*/
/* Display usage information */
/*------------------------------------------------------------------*/
ShowBanner: PROCEDURE
/* credit to https://16colo.rs/pack/sae-006/FMB-SKLL.ASC */
SAY "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
SAY "$$$$$$$$$$$7'` `'!$$$$$$$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
SAY "$$$$$$$7' `$$$$$$$$$ "||,
" $ Y$$ $ $$$ $ YP $$"
SAY "$$$$7' $$$:. :$$$$$$$$ "||,
" $$$$$ L ?$ $ $$$ $ s s $$"
SAY "$$$' '7$' `$$$$$$$ "||,
" $$ $L ? $ $$$ $ $$$$ $$"
SAY "$$ .4$$$a :$$$$$$$ "||,
" $$$$$ $$L $ Y$P $ $$$$ $$"
SAY "$ .4$$$$$$$ $$ .$$$$$$$$ "||,
" $ $$$L $L J$ $$$$ $$"
SAY ": :$$$$$$$$' $$$$ ~'$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
SAY "! '!:$$$7' '$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
SAY " `+$$"||,
"$$$$$$$$$P Y$$$$$P Y$$$$$$$$$$"
SAY ". l$"||,
"$$$$$$$$$ Y$P $$$$$ $$$ $$$$$$$$$$"
SAY ":: .4$$$"||,
"$$$$$$$$$$$P S$$$$$$ $$$ $$$$$$$$$$"
SAY "$$a. .$ .4$$$$$"||,
"$$$$$$$$$P l$$$$$$$$ Y$P $$$$$$$$$$"
SAY "$$$$b. $$$$b. .4$$$$$$$$"||,
"$$$$$$$$$ $$ $L J$$$$$$$$$$"
SAY "$$$$$$$$A. .4$$$$$$$A. .4$$$$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$ss$$$$$$$$$$$$$$$$$$$$"
SAY "$$$$$$$$$$$$$$$$$$$$$$$$$.$$$$$$$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"
RETURN
ShowUsage: PROCEDURE
SAY "$$Y' "||,
" '?$$"
SAY "$$ z/OS Enumeration "||,
"Pentesting Tool $$"
SAY "$$ "||,
" $$"
SAY "$$ Arguments: HELP, ALL, APF, CAT, JO"||,
"B, PATH, SEC, SVC, TSTA, TSOT, $$"
SAY "$$ USSU, VERS, WHO "||,
" $$"
SAY "$$b. "||,
" .d$$"
SAY "$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$"||,
"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$SoF!"
RETURN
ShowHelp: PROCEDURE EXPOSE prgname space
SAY ''
SAY 'z/OS Enumeration tool by Soldier of FORTRAN'
SAY ''
SAY 'Arguments:'
SAY " 'HELP' - Display help information"
SAY " 'ALL' - Display all information"
SAY " 'APF' - Display APF authorized datasets"
SAY " 'CAT' - Display master catalog"
SAY " 'JOB' - Display executing job name"
SAY " 'PATH' - Display dataset concatenations"
SAY " 'SEC' - Display security manager info"
SAY " 'SVC' - Display all SVCs"
SAY " 'TSTA' - Display TESTAUTH authorization"
SAY " 'TSOT' - Display TSO AUTHCMD/AUTHPGM tables"
SAY " 'USSU' - Display USS/OMVS user list"
SAY " 'VERS' - Display system version information"
SAY " 'WHO' - Display logged on TSO/OMVS users"
SAY " 'ASSESS' - Print the findings"
SAY ''
SAY 'Example:'
IF space /== 'OMVS' THEN SAY prgname "'WHO'"
ELSE SAY prgname 'WHO'
RETURN
/*------------------------------------------------------------------*/
/* Enumerate executing job name */
/*------------------------------------------------------------------*/
EnumJobname: PROCEDURE
CALL PrintSectionBanner 'Job Information'
cvt = GetPtr(16)
tcbp = GetPtr(cvt)
tcb = GetPtr(tcbp+4)
tiot = GetPtr(tcb+12)
jobname = STRIP(GetStorage(tiot, 8))
SAY 'Executing Job Name:' jobname
RETURN
/*------------------------------------------------------------------*/
/* Enumerate logged on users (TSO/OMVS/Started Tasks/Jobs) */
/*------------------------------------------------------------------*/
EnumUsers: PROCEDURE EXPOSE (globalvars)
CALL PrintSectionBanner 'Logged On Users'
cvt = GetPtr(16)
asvt = GetPtr(cvt+556) + 512
asvtMaxu = GetPtr(asvt+4)
/* Initialize arrays */
tsoUsers.0 = 0
tasks.0 = 0
tasksUsers.0 = 0
omvs.0 = 0
omvsUsers.0 = 0
jobs.0 = 0
jobsUsers.0 = 0
system.0 = 0
/* Iterate through address spaces */
DO i = 0 TO asvtMaxu - 1
ascb = GetStorage(asvt+16+(i*4), 4)
/* Check if address space is in use */
IF BITAND(ascb, '80000000'x) == '00000000'x THEN DO
ascb = C2D(ascb)
cscb = GetPtr(ascb+56)
chtrkid = GetStorage(cscb+28, 1)
ascbjbni = GetPtr(ascb+172)
ascbjbns = GetPtr(ascb+176)
asxb = GetPtr(ascb+108)
ascboucb = GetPtr(ascb+144)
oucbsubn = GetStorage(ascboucb+176, 4)
oucbtrxn = GetStorage(ascboucb+200, 8)
oucbusrd = GetStorage(ascboucb+208, 8)
/* Started task */
IF ascbjbns <> 0 & chtrkid == '02'x THEN DO
usid = GetUserid(ascb)
CALL AddToArray 'tasks', GetStorage(ascbjbns, 8)
CALL AddToArray 'tasksUsers', usid
END
/* TSO user */
IF ascbjbns <> 0 & chtrkid == '01'x THEN DO
CALL AddToArray 'tsoUsers', GetStorage(ascbjbns, 8)
END
/* System */
IF ascbjbns <> 0 & chtrkid == '04'x THEN DO
CALL AddToArray 'system', GetStorage(ascbjbns, 8)
END
/* OMVS user */
IF STRIP(oucbsubn) == 'OMVS' THEN DO
CALL AddToArray 'omvs', oucbtrxn
CALL AddToArray 'omvsUsers', oucbusrd
END
/* Batch job */
IF ascbjbni <> 0 & chtrkid == '03'x THEN DO
IF STRIP(oucbsubn) == 'OMVS' THEN ITERATE
usid = GetUserid(ascb)
CALL AddToArray 'jobs', GetStorage(ascbjbni, 8)
CALL AddToArray 'jobsUsers', usid
END
END
END
/* Display results */
SAY '**** Started Tasks - Owner ****'
DO i = 1 TO tasks.0
SAY tasks.i '-' tasksUsers.i
END
SAY ''
SAY '**** TSO Users - Owner ****'
DO i = 1 TO tsoUsers.0
SAY tsoUsers.i '-' tsoUsers.i
END
SAY ''
SAY '**** OMVS Users - Owner ****'
DO i = 1 TO omvs.0
SAY omvs.i '-' omvsUsers.i
END
SAY ''
SAY '**** Jobs - Owner ****'
DO i = 1 TO jobs.0
SAY jobs.i '-' jobsUsers.i
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate security manager (RACF/ACF2/Top Secret) */
/*------------------------------------------------------------------*/
EnumSecurity: PROCEDURE EXPOSE (findingsVars)
CALL PrintSectionBanner 'Security Settings'
IF assessMode == 0 THEN SAY 'External Security Manager:'
ELSE SAY 'External Security Manager:'
cvt = GetPtr(16)
cvtrac = GetPtr(cvt+992)
id = GetStorage(cvtrac, 4)
SELECT
WHEN id == 'RCVT' THEN CALL EnumRacf cvtrac
WHEN id == 'RTSS' THEN CALL EnumTopSecret cvtrac
OTHERWISE CALL EnumAcf2 cvt
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate RACF configuration */
/*------------------------------------------------------------------*/
EnumRacf: PROCEDURE EXPOSE (findingsVars) warningDatasets,
excessiveUaccDatasets excessiveAccessDatasets
PARSE ARG rcvt
racfVrm = GetStorage(rcvt+616, 4)
rcvtDsdt = GetPtr(rcvt+224)
dsdtNum = GetPtr(rcvtDsdt+4)
dsdtPrim = STRIP(GetStorage(rcvtDsdt+177, 44), 'T')
dsdtBack = STRIP(GetStorage(rcvtDsdt+353, 44), 'T')
SAY 'Product: RACF'
SAY 'Version: FMID HRF'racfVrm
SAY 'Datasets:'
SAY ''
/* Always show access since we're on RACF */
SAY 'UACC | WARN | ACCESS | DATASET'
SAY '-----|------|--------|' || COPIES('-', 44)
IF dsdtNum == 1 THEN DO
/* Check access for primary and backup - READ access is a finding */
/* Pass empty strings for volume/missing to get simple format */
outputprim = CheckAndReportDatasetAccess(dsdtPrim, '', '', 1)
SAY outputprim
outputback = CheckAndReportDatasetAccess(dsdtBack, '', '', 1)
SAY outputback
END
ELSE DO
offset = 0
DO i = 1 TO dsdtNum
prim = STRIP(GetStorage(rcvtDsdt+177+offset, 44), 'T')
back = STRIP(GetStorage(rcvtDsdt+353+offset, 44), 'T')
offset = offset + 352
/* Check access for primary and backup - READ access is a finding */
/* Pass empty strings for volume/missing to get simple format */
outputprim = CheckAndReportDatasetAccess(prim, '', '', 1)
SAY outputprim
outputback = CheckAndReportDatasetAccess(back, '', '', 1)
SAY outputback
END
END
/* Check if we need to add findings for RACF dataset security */
/* Parse all fields from the output: UACC | WARN | ACCESS | DATASET */
PARSE VAR outputprim primuacc '|' primwarn '|' primaccess '|' .
PARSE VAR outputback backuacc '|' backwarn '|' backaccess '|' .
primuacc = STRIP(primuacc)
primwarn = STRIP(primwarn)
primaccess = STRIP(primaccess)
backuacc = STRIP(backuacc)
backwarn = STRIP(backwarn)
backaccess = STRIP(backaccess)
IF assessMode == 1 THEN DO
/* Check for user access to RACF datasets */
IF primaccess \== 'NONE' | backaccess \== 'NONE' THEN DO
CALL AddFinding 'RACF-DATASET-ACCESS'
CALL AddVerificationCaption 'Run the REXX script ENUM with the',
'SEC argument and observe that the testing account has READ or',
'greater access to the RACF datasets.'
CALL AddVerificationContent 'UACC | WARN | ACCESS | DATASET'||,
' -----|------|--------|---------------------------------'||,
' '||outputprim||' '||outputback
END
/* Check for excessive UACC on RACF datasets */
IF primuacc \== 'NONE' | backuacc \== 'NONE' THEN DO
CALL AddFinding 'RACF-DATASET-EXCESSIVE-UACC'
CALL AddVerificationCaption 'Run the REXX script ENUM with the',
'SEC argument and observe that the RACF datasets have a UACC',
'of READ or greater.'
CALL AddVerificationContent 'UACC | WARN | ACCESS | DATASET'||,
' -----|------|--------|---------------------------------'||,
' '||outputprim||' '||outputback
END
/* Check for WARNING mode on RACF datasets */
IF primwarn == 'YES' | backwarn == 'YES' THEN DO
CALL AddFinding 'RACF-DATASET-WARNING-MODE'
CALL AddVerificationCaption 'Run the REXX script ENUM with the',
'SEC argument and observe that the RACF datasets are configured',
'with WARNING mode enabled.'
CALL AddVerificationContent 'UACC | WARN | ACCESS | DATASET'||,
' -----|------|--------|---------------------------------'||,
' '||outputprim||' '||outputback
END
END
SAY ''
CALL EnumSetropts rcvt
RETURN
/*------------------------------------------------------------------*/
/* Enumerate Top Secret configuration */
/*------------------------------------------------------------------*/
EnumTopSecret: PROCEDURE EXPOSE (findingsVars) warningDatasets,
excessiveUaccDatasets excessiveAccessDatasets
PARSE ARG cvtrac
rcvtDsn = STRIP(GetStorage(cvtrac+56, 44))
SAY 'Product: Top Secret'
SAY 'Dataset:' rcvtDsn
SAY ''
SAY 'Note: Access checking for Top Secret datasets requires'
SAY ' Top Secret-specific commands (not yet implemented)'
RETURN
/*------------------------------------------------------------------*/
/* Enumerate ACF2 configuration */
/*------------------------------------------------------------------*/
EnumAcf2: PROCEDURE EXPOSE (findingsVars) warningDatasets,
excessiveUaccDatasets excessiveAccessDatasets
PARSE ARG cvt
cvtJesct = GetPtr(cvt+296)
sscvt = GetPtr(cvtJesct+24)
DO WHILE sscvt <> 0
ssctsNam = GetStorage(sscvt+8, 4)
IF ssctsNam == 'ACF2' THEN DO
accvt = GetPtr(sscvt+20)
accpfxp = GetPtr(accvt-4)
accpidl = C2D(GetStorage(accpfxp+8, 2))
lenId = accpidl - 4
accpids = STRIP(GetStorage(accpfxp+12, lenId))
acf2Dsns = GetPtr(accvt+252)
acf2Dnum = C2D(GetStorage(acf2Dsns+16, 2))
SAY 'Product: ACF2'
SAY 'Version:' accpids
SAY 'Dataset(s):'
DO i = 1 TO acf2Dnum
adsOff = acf2Dsns + 24 + ((i-1)*64)
acf2Type = GetStorage(adsOff, 8)
acf2Dsn = GetStorage(adsOff+16, 44)
SAY ' ' acf2Type '-' acf2Dsn
END
SAY ''
SAY 'Note: Access checking for ACF2 datasets requires'
SAY ' ACF2-specific commands (not yet implemented)'
LEAVE
END
sscvt = GetPtr(sscvt+4)
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate APF authorized libraries */
/*------------------------------------------------------------------*/
EnumApf: PROCEDURE EXPOSE space (findingsVars)
CALL PrintSectionBanner 'APF Authorized Datasets/Libraries'
IF space == 'OMVS' THEN DO
SAY '! APF Dataset Checking Not Supported in UNIX'
missing = '******'
SAY ''
END
/* Check if we're on RACF to determine if we show access columns */
cvt = GetPtr(16)
cvtrac = GetPtr(cvt+992)
id = GetStorage(cvtrac, 4)
showAccess = (id == 'RCVT')
/* Initialize finding tracking arrays */
warningDatasets = ''
excessiveUaccDatasets = ''
excessiveAccessDatasets = ''
IF showAccess THEN DO
SAY 'VOLUME | EXISTS | UACC | WARN | ACCESS | DATASET'
SAY '-------|--------|------|------|--------|' || COPIES('-', 20)
END
ELSE DO
SAY 'VOLUME | EXISTS | DATASET'
SAY '-------|--------|' || COPIES('-', 44)
END
cvtAuthl = GetPtr(cvt+484)
/* Check if APF table is dynamic or static */
IF cvtAuthl == C2D('7FFFF001'x) THEN DO
CALL EnumDynamicApf cvt, showAccess
END
ELSE DO
CALL EnumStaticApf cvtAuthl, showAccess
END
/* Add findings if any issues were found */
IF showAccess & assessMode == 1 THEN DO
IF warningDatasets \== '' THEN DO
CALL AddFinding 'APF-WARNING-MODE-ENABLED'
CALL AddVerificationCaption 'Run the REXX script ENUM and observe',
'that the following datasets were configured with WARNING mode',
'enabled:'
CALL AddVerificationContent warningDatasets
END
IF excessiveUaccDatasets \== '' THEN DO
CALL AddFinding 'APF-EXCESSIVE-UACC'
CALL AddVerificationCaption 'Run the REXX script ENUM and observe',
'that the following datasets were configured with a UACC of',
'UPDATE, CONTROL, or ALTER:'
CALL AddVerificationContent excessiveUaccDatasets
END
IF excessiveAccessDatasets \== '' THEN DO
CALL AddFinding 'APF-EXCESSIVE-USER-ACCESS'
CALL AddVerificationCaption 'Run the REXX script ENUM and observe',
'that the testing account had UPDATE, CONTROL, or ALTER access',
'to the following datasets:'
CALL AddVerificationContent excessiveAccessDatasets
END
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate dynamic APF table */
/*------------------------------------------------------------------*/
EnumDynamicApf: PROCEDURE EXPOSE space warningDatasets,
excessiveUaccDatasets excessiveAccessDatasets
PARSE ARG cvt, showAccess
cvtEcvt = GetPtr(cvt+140)
ecvtCsvt = GetPtr(cvtEcvt+228)
apfPtr = GetPtr(ecvtCsvt+12)
cur = GetPtr(apfPtr+8)
last = GetPtr(apfPtr+12)
DO FOREVER
dataset = GetStorage(cur+24, 44)
missing = ' Yes '
IF SUBSTR(dataset, 1, 1) \== '00'x THEN DO
volSms = GetStorage(cur+4, 1)
IF BITAND(volSms, '80'x) == '80'x THEN DO
volume = 'SMS '
IF space /== 'OMVS' THEN
retcode = LISTDSI("'"STRIP(dataset)"'" norecall)
END
ELSE DO
volume = GetStorage(cur+68, 6)
IF space /== 'OMVS' THEN
retcode = LISTDSI("'"STRIP(dataset)"'",
'volume('STRIP(volume)')' norecall)
END
IF retcode <> 0 THEN DO
IF SYSREASON == 24 THEN missing = ' No '
ELSE missing = SPACE(D2C(SYSREASON), 8, ' ')
END
/* Check dataset access if on RACF */
IF showAccess THEN DO
output = CheckAndReportDatasetAccess(dataset, volume, missing)
SAY output
END
ELSE DO
SAY LEFT(STRIP(volume),6) '|' STRIP(LEFT(missing,6)),
'|' STRIP(dataset)
END
END
IF cur == last THEN LEAVE
cur = GetPtr(cur+8)
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate static APF table */
/*------------------------------------------------------------------*/
EnumStaticApf: PROCEDURE EXPOSE warningDatasets,
excessiveUaccDatasets excessiveAccessDatasets
PARSE ARG cvtAuthl, showAccess
numApf = C2D(GetStorage(cvtAuthl, 2))
len = C2D(GetStorage(cvtAuthl+2, 1))
cur = cvtAuthl + 3
DO i = 1 TO numApf
volume = GetStorage(cur, 6)
dataset = GetStorage(cur+7, len)
missing = ' N/A '
/* Check dataset access if on RACF */
IF showAccess THEN DO
output = CheckAndReportDatasetAccess(dataset, volume, missing)
SAY output
END
ELSE DO
SAY STRIP(volume) '|' STRIP(dataset)
END
cur = cur + len + 1
len = C2D(GetStorage(cur-1, 1))
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate operating system version information */
/*------------------------------------------------------------------*/
EnumVersion: PROCEDURE
CALL PrintSectionBanner 'Operating System Version'
cvt = GetPtr(16)
cvtExt2 = GetPtr(cvt+328)
cvtJesct = GetPtr(cvt+296)
ecvt = GetPtr(cvt+140)
/* OS version */
prodName = GetStorage(cvt-40, 7)
prodName2 = STRIP(GetStorage(ecvt+496, 16), 'T')
ver = GetStorage(ecvt+512, 2)
rel = GetStorage(ecvt+514, 2)
mod = GetStorage(ecvt+516, 2)
vrm = ver'.'rel'.'mod
fmidNum = GetStorage(cvt-32, 7)
SAY 'The OS version is' prodName2 vrm '- FMID' fmidNum,
'('prodName').'
/* LPAR and Processor information */
csd = GetPtr(cvt+660)
ecvtHdnm = GetStorage(ecvt+336, 8) /* Hardware name */
ecvtLpnm = GetStorage(ecvt+344, 8) /* LPAR name */
IF ecvtHdnm \== ' ' & ecvtLpnm \== ' ' THEN DO
csdPlpn = C2D(GetStorage(csd+252, 1)) /* LPAR number */
SAY 'The Processor name is' STRIP(ecvtHdnm)'.',
'The LPAR SMFID is' STRIP(ecvtLpnm) '(LPAR #'csdPlpn').'
END
/* TSO version */
cvtTvt = GetPtr(cvt+156)
tsvtLver = GetStorage(cvtTvt+100, 1)
tsvtLrel = GetStorage(cvtTvt+101, 2)
tsvtLrel = FORMAT(tsvtLrel)
tsvtLmod = GetStorage(cvtTvt+103, 1)
tsoLev = tsvtLver'.'tsvtLrel'.'tsvtLmod
SAY 'TSO:' tsoLev
/* JES version */
CALL EnumJes cvtJesct
/* VTAM version */
CALL EnumVtam cvtExt2
RETURN
/*------------------------------------------------------------------*/
/* Enumerate JES information */
/*------------------------------------------------------------------*/
EnumJes: PROCEDURE
PARSE ARG cvtJesct
jesSsct = GetPtr(cvtJesct+24)
jesPjesn = GetStorage(cvtJesct+28, 4)
ssctsNam = GetStorage(jesSsct+8, 4)
DO UNTIL jesSsct == 0
IF jesPjesn == ssctsNam THEN DO
ssctSsvt = GetPtr(jesSsct+16)
ssctSuse = GetPtr(jesSsct+20)
ssctSus2 = GetPtr(jesSsct+28)
LEAVE
END
jesSsct = GetPtr(jesSsct+4)
END
IF jesPjesn == 'JES3' THEN DO
jesVers = SYSVAR('SYSJES')
jesNode = SYSVAR('SYSNODE')
END
ELSE IF jesPjesn == 'JES2' THEN DO
jesVers = STRIP(GetStorage(ssctSuse, 8))
jesNode = GetJes2Node(jesVers, ssctSus2)
END
SAY 'JES:' jesPjesn jesVers 'Node:' jesNode
RETURN
/*------------------------------------------------------------------*/
/* Get JES2 node name based on version */
/*------------------------------------------------------------------*/
GetJes2Node: PROCEDURE
PARSE ARG jesVers, ssctSus2
prefix = SUBSTR(jesVers, 1, 8)
SELECT
WHEN prefix == 'z/OS 2.2' THEN
jesNode = STRIP(GetStorage(ssctSus2+664, 8))
WHEN prefix == 'z/OS 2.1' | prefix == 'z/OS1.13' |,
prefix == 'z/OS1.12' | prefix == 'z/OS1.11' THEN
jesNode = STRIP(GetStorage(ssctSus2+656, 8))
WHEN prefix == 'z/OS1.10' | prefix == 'z/OS 1.9' THEN
jesNode = STRIP(GetStorage(ssctSus2+708, 8))
WHEN prefix == 'z/OS 1.8' THEN
jesNode = STRIP(GetStorage(ssctSus2+620, 8))
WHEN prefix == 'z/OS 1.7' THEN
jesNode = STRIP(GetStorage(ssctSus2+616, 8))
WHEN prefix == 'z/OS 1.5' | prefix == 'z/OS 1.4' THEN
jesNode = STRIP(GetStorage(ssctSus2+532, 8))
WHEN SUBSTR(jesVers,1,7) == 'OS 2.10' |,
prefix == 'z/OS 1.2' THEN
jesNode = STRIP(GetStorage(ssctSus2+452, 8))
WHEN SUBSTR(jesVers,1,6) == 'OS 1.1' |,
SUBSTR(jesVers,1,4) == 'SP 5' THEN
jesNode = STRIP(GetStorage(ssctSus2+336, 8))
WHEN SUBSTR(jesVers,1,5) == 'OS 1.' |,
SUBSTR(jesVers,1,5) == 'OS 2.' THEN
jesNode = STRIP(GetStorage(ssctSus2+372, 8))
OTHERWISE
jesNode = SYSVAR('SYSNODE')
END
RETURN jesNode
/*------------------------------------------------------------------*/
/* Enumerate VTAM information */
/*------------------------------------------------------------------*/
EnumVtam: PROCEDURE
PARSE ARG cvtExt2
chkVtAct = GetStorage(cvtExt2+64, 1)
IF BITAND(chkVtAct, '80'x) == '80'x THEN DO
cvtAtcvt = C2D(GetStorage(cvtExt2+65, 3))
istAtcvt = GetPtr(cvtAtcvt)
atcvtLvl = GetStorage(istAtcvt, 8)
vtamVer = SUBSTR(atcvtLvl, 3, 1)
vtamRel = SUBSTR(atcvtLvl, 4, 1)
vtamMod = SUBSTR(atcvtLvl, 5, 1)
IF vtamMod == ' ' THEN vtamLev = vtamVer'.'vtamRel
ELSE vtamLev = vtamVer'.'vtamRel'.'vtamMod
atcNetid = STRIP(GetStorage(istAtcvt+2080, 8))
atcNqnam = STRIP(GetStorage(istAtcvt+2412, 17))
SAY 'VTAM:' vtamLev '(NETID:' atcNetid')',
'(SSCPNAME:' atcNqnam')'
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate SVC table */
/*------------------------------------------------------------------*/
EnumSvc: PROCEDURE EXPOSE (findingsVars)
CALL PrintSectionBanner 'SVC Table'
IF assessMode == 0 THEN DO
SAY 'Installed SVCs (APF authorized only):'
END
ELSE DO
SAY 'Installed SVCs:'
END
SAY 'SVCEP | SVC | HX | TYPE | APF | ESR'
SAY '---------|-----|----|------|-----|----'
cvt = GetPtr(16)
cvtAbend = GetPtr(cvt+200)
scvtSvct = GetPtr(cvtAbend+132)
cvtNucmp = GetPtr(cvt+1200)
nucmAddr = GetPtr(cvtNucmp+8)
/* Find IGCERROR address */
nucmap = cvtNucmp + 16
DO WHILE nucmap <= nucmAddr
IF GetStorage(nucmap, 8) == 'IGCERROR' THEN DO
igcError = GetStorage(nucmap+8, 4)
LEAVE
END
nucmap = nucmap + 16
END
/* Iterate through SVC table */
DO i = 0 TO 255
addr = BITAND(GetStorage(scvtSvct+(i*8), 4), '7FFFFFFF'x)
IF igcError \== addr THEN DO
svcType = GetStorage(scvtSvct+(i*8)+4, 1)
/* Determine type */
SELECT
WHEN BITAND(svcType, '80'x) == '80'x THEN type = '2'
WHEN BITAND(svcType, 'C0'x) == 'C0'x THEN type = '3/4'
WHEN BITAND(svcType, '20'x) == '20'x THEN type = '6'
WHEN BITAND(svcType, 'F0'x) == '00'x THEN type = '1'
OTHERWISE type = '?'
END
/* Check APF and ESR flags */
IF BITAND(svcType, '08'x) == '08'x THEN apf = 'Y'
ELSE apf = 'N'
IF BITAND(svcType, '04'x) == '04'x THEN esr = 'Y'
ELSE esr = 'N'
/* If not in assess mode, only show APF authorized SVCs */
IF assessMode == 0 THEN DO
IF apf == 'Y' THEN DO
SAY C2X(GetStorage(scvtSvct+(i*8), 4)) '|',
RIGHT(i, 3, 0) '|' RIGHT(D2X(i), 2, 0) '|',
type ' |' apf '|' esr
END
END
ELSE DO
/* In assess mode, show all SVCs */
SAY C2X(GetStorage(scvtSvct+(i*8), 4)) '|',
RIGHT(i, 3, 0) '|' RIGHT(D2X(i), 2, 0) '|',
type ' |' apf '|' esr
END
END
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate dataset concatenations (PATH) */
/*------------------------------------------------------------------*/
EnumPath: PROCEDURE EXPOSE (globalvars)
PARSE ARG lvl
CALL PrintSectionBanner 'DDNAME Concatenations'
IF lvl < 1 THEN lvl = 0
psAlccav = C2D(STORAGE('21C', 4))
tcbTio = GetPtr(psAlccav+12)
tiot = tcbTio + 24
tioElngh = 0
dd = ''
IF lvl < 1 THEN DO
SAY 'Only displaying SYSPROC/SYSEXEC'
SAY ''
SAY 'DD | DATASET Name'
SAY '---------|' || COPIES('-', 44)
END
ELSE DO
SAY 'DD | VOLUME | DATASET Name'
SAY '---------|--------|' || COPIES('-', 44)
END
DO FOREVER
tiot = tiot + tioElngh
tioElngh = C2D(GetStorage(tiot, 1))
IF tioElngh == 0 THEN LEAVE
tioEddnm = GetStorage(tiot+4, 8)
IF tioEddnm \== ' ' THEN dd = tioEddnm
dsnAddr = Swareq(GetStorage(tiot+12, 3))
dataset = STRIP(GetStorage(dsnAddr, 44))
volume = GetStorage(X2D(dsnAddr)+118, 6)
IF lvl < 1 THEN DO
IF dd == 'SYSPROC ' | dd == 'SYSEXEC ' THEN
SAY dd '|' dataset
END
ELSE SAY dd '|' volume '|' dataset
END
RETURN
/*------------------------------------------------------------------*/
/* Enumerate master catalog */
/*------------------------------------------------------------------*/
EnumCatalog: PROCEDURE
cvt = GetPtr(16)
ecvt = GetPtr(cvt+140)
ecvtIpa = GetPtr(ecvt+392)
ipaScat = GetStorage(ecvtIpa+224, 63)
mcatDsn = STRIP(SUBSTR(ipaScat, 11, 44))
mcatVol = SUBSTR(ipaScat, 1, 6)
SAY 'Master Catalog:' mcatDsn 'Volume:' mcatVol
RETURN
/*------------------------------------------------------------------*/
/* Test TESTAUTH authorization */
/*------------------------------------------------------------------*/
EnumTestauth: PROCEDURE
CALL PrintSectionBanner 'TESTAUTH Authorization'
ADDRESS 'TSO' 'NEWSTACK'
QUEUE 'END'
rc = OUTTRAP('out.')
ADDRESS 'TSO' "TESTAUTH 'SYS1.LINKLIB(ICEPRML)'"