If you’ve been following this blog you’ve occasionally seen me post about the amazing scripts by @zospentest (@ayoul3__ on twitter). Around this time last year, literally out of nowhere Ayoub released ELV.APF.
Before I get too far in to what the script does we need to talk about RACF, z/OS and data areas.
If you’re really curious about data areas you can read the following. What I did was combine them all in to one PDF for easy searching. But everything you need is right here:
GA32-0935-03 z/OS V2R2 MVS Data Areas Volume 1 (ABE - IAX)
GA32-0936-03 z/OS V2R2 MVS Data Areas Volume 2 (IAX - ISG)
GA32-0937-03 z/OS V2R2 MVS Data Areas Volume 3 (ITK - SCE)
GA32-0938-03 z/OS V2R2 MVS Data Areas Volume 4 (SCF - XTL)
On top of these is the Security Server RACF Data Areas (ICHC400) which discusses the various areas in memory (aka storage) that RACF uses.
The data area we’re most interested in is the ACEE aka the Access Control Environment Element. Rolls right off the tongue.
Long story short, after a successful login a region of memory is dedicated to your ACEE. The ACEE is made up of many components and you can read all about them in the Page 3 here. The way it gets created is with a call to RACINIT. Go ahead and read the entirety of the ACEE data area. I’ll watch this GIF while I wait.
If you actually did read it you’ll notice a very SPECIAL area thats worth digging in to: ACEEFLG1
Once you’ve logged in, RACF will make your ACEE and, in summary, copy your access rights to your ACEE. That way every access lookup is done in memory instead of a database lookup. But, if you look at ACEEFLG1 you’ll see that some global attributes (SPECIAL, AUDIT, OPERATIONS) are included in memory!
If you’ve read up on mainframe hacking, in relation to RACF, you’ll know that the ultimate goal is to get system SPECIAL. This attribute is the same as domain admin. Though it doesn’t give you access to anything itself, it allows you to give yourself access to anything you want. So, basically all we need to do is change the ACEEFLG1: ACEESPEC bit from a zero to a one. That’s it!
Now, you might be in a panic thinking ‘oh my god, you can just change your memory.’ Tell your stupid brain to shut the hell up. This region of memory is protected. i.e. only programs in supervisor state can make changes to this data area. I don’t really want to get in to supervisor state at this time there’s lots of documentation about it. The only important thing to know is that programs that are APF (authorized program facility) can get to supervisor state. If you’re an auditor you’ll recognize he term APF because it is #1 on every audit guide ever. And for good reason. Any APF library can change the ACEEFLG1 and set it to whatever we want.
So the attack works like this:
1 - Identify all APF authorized libraries
2 - Check if we have write access to any of these libraries
3 - Insert our own code in one of those libabries
4 - Execute our code
Step one is relatively easy, what we need to do is find every APF authorized library on the system and see if we have write access to any of them. I’m using library here when really the term should be PDS (partitioned dataset), or for non mainframers ‘a folder’. Conveniently the listing of every APF library is also stored in memory and we can use some simple rexx to extract that information.
Step two is even easier. We just issue a RACF command to check our access rights: LISTDSD DATASET(’<filename>’) GENERIC where <filename> is the library we want to check access to. Take a look at these two screenshots:
Notice the difference? Under “Your Access” it tells you if the access is READ/ALTER/NONE. For the first file (USER.VTAMLIB) we have READ access. BUT for the second file we have ALTER access!
Step 3 now requires us to write some assembler and get it compiled with JCL. That is WAAAAAY more complicated. But thankfully you can use metasploit to generate the code we need (thanks to @bigendiansmalls amazing work!).
We can use Metasploits msfvenom to create the JCL/Assembler we need to do the privilege escalation:
That DSN (aka file) should look familiar. It’s the library we have ALTER access to!
Now, the msfvenom output also takes care of step 4 for us by executing the code for us at the compile step (ASMACLG means Compile, Link and Go). How convenient. Once its run, the user running the JCL has SPECIAL. But only so long as that JCL is running. So there’s an extra step in the JCL to make it permanent:
Basically, ALU <USERNAME> SPECIAL alters the UserID (ALU) for the user INFOS10 and sets it to system SPECIAL. Since our ACEE has the SPECIAL flag set RACF obediently obeys and changes whatever userID you supplied to system special.
Wow, that was a pain in the ass huh? This is where Ayoub’s script ELV.APF comes in. Imagine you could do all of this in two steps?
To show how easy it is I’ve wipped up this little rexx script to only show the important bits from RACF:
So, with ELV.APF we really only need to do two things:
1) Call the script with the command ‘list’
2) Call the script again with a name of a PDS you have ALTER/WRITE access to
Here it is in action:
Firs I’ll run the rexx INFO script to show my current ATTRIBUTES:
Next we’ll call ELV.APF with the ‘list’ command. Followed by passing it the only APF authorized library we have access to. Finally I’ll run the INFO script again. Notice how my ATTRIBUTE has changed:
And thats it! There are MANY more methods for privilege escalation this is just one method. But hopefully now everyone will understand why protecting APF authorized libraries is so important.
To those wondering how long this takes, I’ll leave with a parting GIF: