- Hi, I'm Jake Labelle.
And my talk today is gonna be on finding
Surrogat chains on a mainframe.
So, who am I?
I'm a security consultant at F-secure.
Technically associate, but sounds a bit shit.
So, I've been on a couple of mainframe jobs,
so not an expert by any means.
I'm currently streaming from Basingstoke UK,
which is in Vegas,
but what can you do?
And I was gonna put a picture here,
but just look to the right end, yep.
There I am.
So, before I go into my tool, I've created,
I'll just do a quick high level introduction
to z/OS, which is the operating system
that you find on most mainframes.
One of the major difference between Linux and windows
and z/OS is that z/OS has data sets.
So for example, here, it's USER01.REXXLIB.
And one thing to know about it is it's a flat filesystem,
so there's no folders,
but normally how it works is that
you'll have your high level qualifier,
which is normally the owner first.
So user01, which would be,
and then dot something, dot something bla bla.
And you have apostrophes around data sets.
This indicates that it's an absolute path
in all of my Gator program,
the apostrophes around every single dataset
cause just easier.
You now can have partitioned data sets where,
so usually USERO1.REXLIB is the dataset,
but then you can have multiple members in that data set.
So for example, and this one would be, Hello.
And the picture below is just a picture of a DS list,
which just shows a lot of,
which shows all the data sets
of a high level qualifier of IBM user and so, yeah.
So my program is mostly written in REXX,
which is a scripting language like Python,
has a couple slightly unique functions though.
So one of them is address,
which lets you run a program in another program.
So, this is running lists DSD in TSO
and the output of that
you can store using
something called outtrap,
which you will then put all the output of that TSO command
into a STEM variable, which is basically an array.
So another language that's uses the JCL,
which is a job control language.
It's a batch job though.
So when you submit a JCL,
the JCL is then run at some point by the mainframe
and on the first line of every JCL
you have the job card,
which has the title of the job
and a couple of other parameters.
Say, for example, this will notify the user
after it's run and it will also store it in the spool.
So in all of my program all of the JCL
that I have are embedded inside REXX scripts.
And so this one, for example,
it will cue all of the lines of the JCL.
It will then use outtraps,
concatenate those lines and then submit them.
The reason why I use this in a REXX script is
because you can then pass on arguments easier
and you can then have a more dynamic JCL.
So, one of the major subsystems on z/OS is OMVS
and it's a Unix subsystem,
and it's kinda of like the WSL windows subsystem for Linux.
However, there's no segregation
between the two parts.
So, on there's no segregation between TSO and OMVS.
TSO being the main part of where you log into the mainframe.
So on TSO, you can run OMVS commands
and OMVS, you can run TSO commands.
So if you have access to one,
you basically have access to the other
and the security of OMVs.
So for example,
what would be slash etc slash pseudos is,
is managed by RACF
and RACF is resource access control facility,
and this can handle different types of resources.
So for example, datasets, surrogats,
as mentioned before the pseudo,
the OMVS resources.
So for example, super user would be in there.
So each resource has an owner
and they have alter access.
So basically, complete access to the resource.
You can also set a UACC,
which is how much access that just any random user
has to the resource.
You can also permit other users to have access.
So there's four different types of access you can give.
It's execute, reads, update and alter,
and they do what they sound like they do.
One other special attribute you can give
to a user is special.
Special means that you basically have authorized access
to every single resource,
which you can think of as being like having roots.
One of the main classes in z/OS is surrogat,
and there's a couple different types of these.
So we have *.SUMMIT.
So for example, USERID.SUBMIT
So, USER01.SUBMIT, would mean
if you had read access to this,
you could submit a JCL as that as USER01,
there's also BPX.SRV.USERID.
So for example,
BPX.SRV.USER2, means you can run
a still command as that user.
There's also DFHSTART.USERID.
And this just means you can run a kicks transaction
as that user.
I don't use DFHSTART in my program,
but maybe in the future.
So, one thing that you'll find on mainframes
or surrogat chains and the reasons why these occur
is cause there's lots of users
and no one knows what they were all of them are for.
So for example,
I was added as a user on a pen test job.
And 20 years later, someone's probably gonna ask,
who is this Jake character?
And why does he have access to these things?
No one's gonna know,
and no one's gonna delete it
because maybe it will break something.
And that also tends to the other thing where
mainframes have been running for decades.
It's one of their major selling factor.
So, the person who added me,
it's probably gonna be long gone
before the next person even looks at me.
So, surrogat chain is where, for example,
user one has read access to a surrogat class on user two
and user two has read access to a surrogat on user three.
So in this case,
user one practically has access to everything
that user three has
and the way you can list what access,
what surrogats you have, you can run a command,
RLIST SURROGAT *
However, RACF has a thing where you can only see
the protections on a RACF that you have at list read for.
So in this case, user one would not be able to see
that user two has a read on a surrogat and use a three.
The other problem is that *.SUBMIT is a batch job.
So let's say you wanted to run a REXX script
that ran the JCL from user one
as a surrogat on user two,
And then want from user two run a JCL to use the three.
You can't just run that in one program
because it's using a JCL
which again, it's a batch job.
So what you could do, is you could manually
submit reverse shells one at a time.
So you'd as user one,
find out that you had a user to surrogat,
then you would submit a reverse shell for user two
then once you've user two,
your would list all your surrogats again,
and then you would submit a reverse shell for user three.
However, it takes a long time and there's a lot of users.
So this might not even be feasible.
Another thing you could do, is you could just use a user
which has read access to all the resources.
So for example, a special account
or an auditor account,
they don't really have read access to these,
but they basically do.
Then, you could also then use this
to find all the surrogat chains.
The only problem with this is that
you're not gonna get a special account.
You're definitely not gonna get a special account
on a pen test and you probably won't get
an auditor account and a pen test either.
So I have a GATOR, is the GitHub link to it
and it allows you to find and exploit surrogat chains.
So the first thing you did with GATOR,
is you run BEGIN.REXX.
It gets all the output data sets ready.
It gets the Unix file ready.
And it adds the current user that you're running it
from to the path.
And it START GATOR.REXX.
GATOR.REXX gets the path that it currently is at.
So when the first run,
it would just be just the original user.
If it's special,
if you're using, you have a special,
it will just stop because if you have special,
you've already won.
It will then run PLUGINS.REXX, which I'll explain later,
it will list all the surrogats that you have read access to,
and it checks that those surrogats haven't been visited yet.
The reason why I have to add this,
is because I didn't wanna have to deal with cycles.
And this was the quickest and easiest way to deal with that.
So you won't actually get the whole,
I guess, surrogat network,
but you will get a chain of through them.
If it easier to START.SUMBIT resource
or run SUBM.REXX.
And if it sees a to BPS.SRV.* resource or run UNIXM.REXX.
So SUBM.REXX just submit to JCL as the surrogat user,
which then runs GATOR.REXX.
So, then it'll continue it on.
UNIXM.REXX it's a JCL, which just runs Gator.
It's moved into OMVS with BEGIN.REXX to /temp/unixm
and then Gator calls it with a bpxbatch that's you'd run
OMVS commands in TSO.
And then you do so to that target user.
So PLUGINS.REXX is a list of REXX scripts
to run on each user.
There's a number of enumeration scripts you can run.
I have three that I have set up already.
One of them just lists the user.
So, this will tell you if they have special,
if they have operations,
what groups they're connected to,
those types of things.
I also have one which will just list
your access to all of the RACF databases.
It's unlikely you'll have anything
other than none for this,
but might as well test.
If you have read access,
it's really good to let you unload the database.
So you can see all the things in the RACF database
really useful.
If you have update or alter,
then you can just put yourself in a special,
and I have a tool to just write yourself in, but yeah,
they're very unlikely, but if it does happen,
hit the jackpot.
The other one is it will search all of the APF libraries
to see what access you have to those,
you can think of APF libraries
as kind of like set good libraries in Unix.
It's not really, but if you have updated, alter,
you can get special.
And now there's tools out there to do that.
Oh, and also, if you have any other scripts you want to add,
it's fairly easy to just, it's fairly extensible.
Just add your own REXX script in
and like, for example,
if you have one, if you have just a LINUX script
that you have, that you can use,
you can quickly add that to there.
So, to test to see that the program was working properly,
I using an emualted z/OS created a thousand users
then randomly assigned a couple operators
and a couple special users,
added a couple of surrogats of each type to each user,
and then run Gator,
the test script to generate all of these users
are on GitHub as well.
So, using the output of the all the paths
that were generated
and also the user, the list user command.
So, here you can see the large squares are operators
and the big stars special
shows you all the paths to get to these users.
If you're anyone can think of a better way to show
a thousand nodes on a graph, then yeah,
that'd be helpful.
I also created a shell macro.
So from the user that you ran the Gator from,
you can pick any user that's in the path,
the surrogat chain, and it runs shell be that user,
it will then keep submitting a JCL continuously
passing on how far along in the target it is.
How far along in the path to the target is?
And at the end, it will submit a CATSO shell.
It's like meterpreter.
Here is the GitHub humbling to it by mainframed.
I've also just created a bash script,
which will quickly upload all the REXX scripts.
And it's just quick to set that up and yeah,
that's my a tool.
And I'll do a quick thing on
if you wanna get into mainframes yourself.
So one of the probably the easiest way
is with TK4-
it's based on a 1980's, mainframe MVS 3.8J,
it runs on a Raspberry PI, which is pretty cool.
Everything is open source and public domain,
pretty cool again.
Here's the link to download it.
And there's a user guide to just get started and yeah.
Here's a picture of it, again pretty cool.
And on there, you can install two fairly important things.
So you can get Kikcs, which is a Cics clone,
and there's a Moshik's guides.
I've put the YouTube link to it.
And kicks is like web servers
before web servers were cool.
So, you can test your COBOL scripting
and Brexx is just a back ported thing
that lets you run REXX scripts.
Again, here's the Moshik's guides to get it installed.
If you can't be able to get these installed,
I have a one with these already installed on my GitHub,
TK4 base, that's what I called it.
Another tool to get yourself, to get started on mainframes.
It's Hercules.
So Q public license,
it's a mainframe emulator
and it's what TK4 uses to run.
And now there is an old version of z/OS 1.10 online
but piracy is bad.
So yeah, don't do that.
But if you do end up getting a z/OS version,
there's a, is the GitHub link to mainframes lamps, and yeah,
they're pretty good to get started
and there's a Mattermost community that's fairly good
to answer any questions.
If you want to ask me any questions, my username is Tdasu.
So yeah, drop me a message on there
and I'll answer.
And that's my talk done.
Are there any questions?