CTFZONE Quals 2024 | Youtube Unlock & Youtube Unlock Revenge (GGC Exploit)
Difficulty : Easy to Medium
I solved these two tasks but I don't understand them very much, sorry if there are any inconsistencies.
Youtube Unlock :

Let's start by reading the code to understand the task.
/app/nginx/nginx.conf :
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 4431 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
location / {
return 301 https://blocked.org.uk:443;
}
}
server {
listen 4432 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
location / {
return 301 https://www.youtube.com/watch?v=WIRK_pGdIdA;
}
}
}
stream {
map $ssl_preread_server_name $proxy {
youtube.com backend;
www.youtube.com backend;
default backend_default;
}
upstream backend_default {
server 127.0.0.1:4431;
}
upstream backend {
server 127.0.0.1:4432;
}
server {
listen 4430;
ssl_preread on;
proxy_pass $proxy;
}
}
/app/dpi/dpi.py :
import socket
import select
import os
def server_connection(dst_ip, dst_port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((dst_ip, dst_port))
return sock
BUFFER_SIZE = 140
dst_ip = 'nginx'
dst_port = 4430
srv_port = 443
sockets = []
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", srv_port))
srv.listen(3)
print(f'listening connection on port {srv_port}')
sockets.append(srv)
while True:
socks,_,_=select.select(sockets,[],[])
for sock in socks:
try:
if sock==srv:
print ("sock : " +str(sock))
print ("srv : " + str(srv))
buf ="empty"
client,_=srv.accept()
print(f"new connection")
sockets.append(client)
server=server_connection(dst_ip, dst_port)
sockets.append(server)
buff=sock.recv(BUFFER_SIZE)
print("buffer : "+str(buff))
else:
buf=sock.recv(BUFFER_SIZE)
if b'youtube' in buf:
print('BAN!!!')
os.system("echo BAN > ban.txt;")
continue
id=sockets.index(sock)
if id%2==1:
if len(buf) == 0:
sockets[id].close()
sockets[id+1].close()
del sockets[id]
del sockets[id]
else:
sockets[id+1].sendall(buf)
else:
if len(buf) == 0:
sockets[id-1].close()
sockets[id].close()
del sockets[id-1]
del sockets[id-1]
else:
sockets[id-1].sendall(buf)
print("success")
except Exception as e:
print(e)
The nginx server hosts 2 servers each one under a service name, accessing the server normally will result to a redirect blocked.org.uk, what is needed is to use the Service name youtube.com to access the youtube video that will probably contain the flag.
So now checking the python code, we see that it acts as a proxy to our nginx server, it will block every request containing the string "youtube", but since it's case sensitive we can just bypass it by using "Youtube.com" instad of "youtube.com".
So now how do we do this ?
First we intercepted a request to the server and put in repeater.

Then you got edit target and change the check override SNI and enter Youtube.com
After it we follow the redirection and get to a youtube video

This video will contain the flag.
Pretty easy stuff
Youtube unlock | Revenge :

The second challenge is almost the same thing but with a little change to the files.
/app/nginx/nginx.conf :
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 4431 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
location / {
return 301 https://blocked.org.uk:443;
}
}
server {
listen 4432 ssl;
ssl_certificate /cert.pem;
ssl_certificate_key /cert.key;
location / {
return 301 https://www.youtube.com/watch?v=WIRK_pGdIdA;
}
}
}
stream {
map $ssl_preread_server_name $proxy {
youtube.com backend;
www.youtube.com backend;
default backend_default;
}
upstream backend_default {
server 127.0.0.1:4431;
}
upstream backend {
server 127.0.0.1:4432;
}
server {
listen 4430;
ssl_preread on;
proxy_pass $proxy;
}
}
/app/dpi/dpi.py :
import socket
import select
def server_connection(dst_ip, dst_port):
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((dst_ip, dst_port))
return sock
BUFFER_SIZE = 140
dst_ip = 'nginx'
dst_port = 4430
srv_port = 443
sockets = []
srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
srv.bind(("0.0.0.0", srv_port))
srv.listen(3)
print(f'listening connection on port {srv_port}')
sockets.append(srv)
while True:
socks,_,_=select.select(sockets,[],[])
for sock in socks:
try:
if sock==srv:
client,_=srv.accept()
print(f"new connection")
sockets.append(client)
server=server_connection(dst_ip, dst_port)
sockets.append(server)
else:
buf=sock.recv(BUFFER_SIZE)
if b'youtube' in buf.lower():
print('BAN!!!')
continue
id=sockets.index(sock)
if id%2==1:
if len(buf) == 0:
sockets[id].close()
sockets[id+1].close()
del sockets[id]
del sockets[id]
else:
sockets[id+1].sendall(buf)
else:
if len(buf) == 0:
sockets[id-1].close()
sockets[id].close()
del sockets[id-1]
del sockets[id-1]
else:
sockets[id-1].sendall(buf)
except Exception as e:
print(e)
The key difference is now file upload is allowed on the server and secondly the server will require a pair socket id. To ensure we get two sockets in our request, we can upload a blank file so it would queue the file transfer in the socket queue.
so again with the same.
and for our request.
we get the flag appended to the youtube link.
I didn't understand this challenge very well, it tried this and worked, what I wrote here is me trying to understand why it works, so sorry if I'm wrong in some points.
Last updated