diff --git a/wiki/clients/glaztech.md b/wiki/clients/glaztech.md index b178c91..97fbd5e 100644 --- a/wiki/clients/glaztech.md +++ b/wiki/clients/glaztech.md @@ -40,16 +40,16 @@ Multi-site Windows environment (~200 users, 9 locations). Active Directory confi | Server | Role | OS / Build | Local IP | Public IP | Notes | |---|---|---|---|---|---| -| WWW | IIS web server — customer/e-commerce site | Windows Server 2019 Standard, build 10.0.17763.8755 (patched ~May 2026) | 192.168.8.72 | 65.113.52.88 | IIS 10.0, .NET 4.8; site `glaztech_new` at `D:\web\glaztech_4`; full VB.NET source on disk (not precompiled); LE cert CN=www.glaztech.com, SAN apex+www, exp 2026-08-19 via Certify The Web (HTTP-01); GuruRMM agent 455a1bc7-1c29-42bc-b597-fa1e64f08eec (v0.6.54); **doubles as dev workstation** (VS 2015+2022 installed — see Security Posture); active IIS site W3SVC4 (log dir `C:\inetpub\logs\LogFiles\W3SVC4`; older sites W3SVC1/2/3 stale, last writes 2018–2022) | -| GTI-INV-SQL | SQL Server — website backend + GTIware PSA (shared instance) | [unverified — Server OS not confirmed; co-located with GTI/Glaztech infra] | 192.168.8.62,3436 | — | **Hostname: GTI-INV-SQL.** Login `tom` = named SQL login (SQL auth, created 2018), **member of `sysadmin` server role** (also securityadmin, dbcreator, db_owner); password embedded in site `Web.config` (NOT vaulted). **46 databases total:** all offices' `glaz_prod*` + `*_archive` databases, PDF stores, `qqest` (TimeForce payroll), `gti_samsara`, `mas_gti` (Sage 100), system DBs (`master`, `msdb`). Other sysadmin logins on instance: `GTI-INV-SQL\Administrator`, `NT SERVICE\*`, `sa` (enabled), `tom`. | +| WWW | IIS web server — customer/e-commerce site | Windows Server 2019 Standard, build 10.0.17763.8755 (patched ~May 2026) | 192.168.8.72 | 65.113.52.88 | IIS 10.0, .NET 4.8; site `glaztech_new` at `D:\web\glaztech_4`; full VB.NET source on disk (not precompiled); LE cert CN=www.glaztech.com, SAN apex+www, exp 2026-08-19 via Certify The Web (HTTP-01); GuruRMM agent 455a1bc7-1c29-42bc-b597-fa1e64f08eec (v0.6.54); **doubles as dev workstation** (VS 2015+2022 installed — see Security Posture); active IIS site W3SVC4 (log dir `C:\inetpub\logs\LogFiles\W3SVC4`; older sites W3SVC1/2/3 stale, last writes 2018–2022). IIS app-pool identity: `IIS APPPOOL\glaztech_new` (PID 13752 = `w3wp`). GTIware card-engine DLLs (`gt_auto_process_2020.dll`, `glaztech_utilities_2020.dll`) are co-resident in `D:\web\glaztech_4\Bin\` and load in-process into this worker — see C0-Extended. New internet-facing endpoints `/webhooks` (Samsara receiver, `samsara_webhook_receiver.dll`) and `/webhooks1` (`webhooks_test` — unreviewed). Second host referencing the same code tree surfaced: `\\192.168.0.147\web\glaztech_4` — not yet reconned. | +| GTI-INV-SQL | SQL Server — website backend + GTIware PSA (shared instance) | [Server OS not confirmed; co-located with GTI/Glaztech infra] | 192.168.8.62,3436 | — | **Hostname: GTI-INV-SQL.** Login `tom` = named SQL login (SQL auth, created 2018), **member of `sysadmin` server role** (also securityadmin, dbcreator, db_owner); password embedded in site `Web.config` (NOT vaulted). **47 databases total** (46 custom + system DBs): all offices' `glaz_prod*` + `*_archive` databases, PDF stores, `qqest` (TimeForce payroll), `gti_samsara`, `mas_gti` (Sage 100), system DBs (`master`, `msdb`). **All 47 databases `is_encrypted=False` (no TDE).** Other sysadmin logins on instance: `GTI-INV-SQL\Administrator`, `NT SERVICE\*`, **`sa` (enabled)**, `tom`. **SQL Agent service runs as `Administrator@glaztech.com`** (domain-admin class). **7 linked servers** (remote-login + data-access) across `192.168.0.x` and `192.168.8.x`: `192.168.0.54,55181` (unknown), `192.168.0.55,55181` (`mas_gti` / Sage accounting), `192.168.8.52,3436` (backup host), `192.168.8.212,3436` (backup host), `192.168.8.62,3430` (`GTI-INV-SQL\GTISQL` self-link), `GLAZ\TIMEFORCE` (`qqest` payroll). **CHD `.bak` backups copied to `\\192.168.8.52\sql_backup\`** (unencrypted, plaintext PAN/CVV). Cleartext `glaztech\administrator` domain-admin password embedded in `msdb` SQL Agent backup-copy job steps — harvestable by any sysadmin/`tom` connection; **password value redacted from all artifacts; must be rotated.** Server-side billing engine: `d:\sql_jobs\bin\gt_console_apps.exe` (modes: `cp`, `is`, `oa`, `lo`) run by the Agent as domain-admin. | | Service | Details | Notes | |---|---|---| | M365 tenant | glaztechindustries.onmicrosoft.com | ~200 users, basic licensing (no Entra P1) | | Exchange Online | glaztech.com | MailProtector inbound filter (MX 5 primary) | | Active Directory | glaztech.com domain | [unverified — AD inferred from OU references in scripts] | -| Payment processing | CyberSource REST (api.cybersource.com/pts/v2/payments) — PNC merchant processor for card payments; CyberSource SOAP toolkit for eCheck/ACH (cybs.log) | Card path: online-payment-pnc.aspx; eCheck path: ach.aspx. Card-on-file auto-pay engine is GTIware (`gt_auto_process_2020.dll`) — not the website. | -| GTIware PSA | Internal PSA (Tom's software): `glaztech_utilities_2020.dll` + `gt_auto_process_2020.dll` — staff-operated card-on-file system. Writes `cc_file` rows stamped with staff usernames. Shares `GTI-INV-SQL` with the public website. | Cards stored by GTIware, NOT by the website (website's `.aspx`/`.vb` has zero `cc_file`/`save_cc_data` references). | +| Payment processing | CyberSource REST (api.cybersource.com/pts/v2/payments) — PNC merchant processor for card payments; CyberSource SOAP toolkit for eCheck/ACH (cybs.log) | Card path: online-payment-pnc.aspx; eCheck path: ach.aspx. Card-on-file auto-pay engine is GTIware (`gt_auto_process_2020.dll`) — not the website. `Web.config` holds CyberSource (`cybs.*` + on-disk signing keys) and PNC (`pnc_key/pin/token`) secrets **in cleartext**. | +| GTIware PSA | Internal PSA (Tom's software): `glaztech_utilities_2020.dll` + `gt_auto_process_2020.dll` — staff-operated card-on-file system. Writes `cc_file` rows stamped with staff usernames. Shares `GTI-INV-SQL` with the public website. **Both DLLs are co-resident in the public IIS worker (`D:\web\glaztech_4\Bin\`) and carry no own connection strings — they run on the website's `tom` (sysadmin) connection.** | Cards stored by GTIware, NOT by the website (website's `.aspx`/`.vb` has zero `cc_file`/`save_cc_data` references). However, the card engine executes in-process in the internet-facing IIS worker, so a web-tier or host-level compromise lands directly inside the card-on-file write/charge engine. | ### Email & Identity @@ -112,42 +112,65 @@ Note on Priority 1: The "GTIMail No-Reply - Reject Inbound" transport rule rejec - **DNS access:** `root@172.16.3.10` (IX server) - **Deploy (endpoints):** GuruRMM (preferred) or ScreenConnect - **MailProtector / CloudFilter partner portal:** NO credentials in vault — manual partner-portal login required for any MailProtector changes (provisioning, spam summary enable). Consider vaulting. -- **Glaztech SQL login (`tom`):** present in `D:\web\glaztech_4\Web.config` connectionStrings — NOT in vault. Used read-only for the 2026-06-03 assessment only; do NOT use outside of authorized sessions. This login has sysadmin rights on `GTI-INV-SQL` — treat with corresponding care. +- **Glaztech SQL login (`tom`):** present in `D:\web\glaztech_4\Web.config` connectionStrings — NOT in vault. Used read-only for the 2026-06-03/06-04 assessment only; do NOT use outside of authorized sessions. This login has sysadmin rights on `GTI-INV-SQL` — treat with corresponding care. +- **ACG management stack on WWW:** ScreenConnect (both `support.azcomputer.guru` and the `kgc7jt` ScreenConnect Cloud instance), Datto RMM (CentraStage), Datto EDR (Infocyte), Syncro, Splashtop, GuruRMM — all ACG's sanctioned management agents. None of these are third-party intrusions. The only remote-access finding on this host is end-of-life RealVNC 4.x (Steve's tool — see H2 below). ## Security Posture — CRITICAL (Active Issue — Ticket #32378) **Classification: CONFIDENTIAL/Security.** Full detail in: - `clients/glaztech/reports/2026-06-03-pci-cardholder-data-finding.md` -- `clients/glaztech/reports/2026-06-03-website-security-assessment.md` (incl. Appendix A — Intrusion/Brute-Force Log Review, 2026-06-04) +- `clients/glaztech/reports/2026-06-03-website-security-assessment.md` (incl. Appendix A — Intrusion/Brute-Force Log Review 2026-06-04; C0-Extended — deep host + SQL-infrastructure recon 2026-06-04) -A full read-only security assessment of the Glaztech e-commerce web application and SQL backend was performed 2026-06-03. A follow-up read-only intrusion/brute-force log review was performed 2026-06-04 (see Appendix A in the assessment report). Overall risk: **CRITICAL**. Key findings (no card numbers or passwords are reproduced here): +A full read-only security assessment of the Glaztech e-commerce web application and SQL backend was performed 2026-06-03. A follow-up read-only intrusion/brute-force log review was performed 2026-06-04 (see Appendix A in the assessment report). A second follow-up read-only deep host + SQL-infrastructure recon was performed 2026-06-04 (see C0-Extended; session log "Update: 09:38 PT"). Overall risk: **CRITICAL**. Key findings (no card numbers or passwords are reproduced here): ### C0 (TOP CRITICAL) — Website connects to `GTI-INV-SQL` as `sysadmin` -**This is the single most dangerous finding.** The public website at `D:\web\glaztech_4` logs into the SQL server `GTI-INV-SQL` (192.168.8.62,3436) using SQL login **`tom`** — a **named SQL login** (SQL authentication, created 2018, NOT the built-in `sa`) that is a **member of the `sysadmin` server role** (also securityadmin, dbcreator, db_owner). The password is **embedded in the site's `Web.config`** on the internet-facing server. +**This is the single most dangerous finding.** The public website at `D:\web\glaztech_4` logs into the SQL server `GTI-INV-SQL` (192.168.8.62,3436) using SQL login **`tom`** — a **named SQL login** (SQL authentication, created 2018, NOT the built-in `sa`) that is a **member of the `sysadmin` server role** (also securityadmin, dbcreator, db_owner). The password is **embedded in the site's `Web.config`** on the internet-facing server. The web root ACL grants **`Everyone:(R)`** on `D:\web\glaztech_4`, its `bin`, and `Web.config` — so any local principal can read the `tom` SQL password and both processors' secrets. -That same SQL instance (`GTI-INV-SQL`) is **shared with GTIware** (Tom's internal PSA) and hosts **46 databases**: all offices' `glaz_prod*` + `*_archive`, PDF stores, `qqest` (TimeForce payroll), `gti_samsara`, `mas_gti` (Sage 100), and system DBs. +That same SQL instance (`GTI-INV-SQL`) is **shared with GTIware** (Tom's internal PSA) and hosts **47 databases**: all offices' `glaz_prod*` + `*_archive`, PDF stores, `qqest` (TimeForce payroll), `gti_samsara`, `mas_gti` (Sage 100), and system DBs (`master`, `msdb`). **None of the 47 databases use TDE (all `is_encrypted=False`).** Because a SQL injection executes as the connecting login, the website's `quo()` SQLi flaw executes with **full sysadmin rights across the entire instance**. Cross-database reach was confirmed live: from a single injectable page on the Tucson connection, other offices' `cc_file` tables were read (`glaz_prod_phx` = 141 rows, `glaz_prod_den` = 190, `glaz_prod_elp` = 179). -**Attack chain:** (1) guess one website customer login (no lockout, username = account number, passwords as short as 3 chars, plaintext) → (2) hit an injectable payment page → (3) inject as sysadmin → total control of `GTI-INV-SQL`. As sysadmin an attacker can: steal every stored card PAN+CVV and password; DROP/encrypt all 46 databases (every office, all archives); commit fraud; enable `xp_cmdshell` → OS-level code execution on the SQL server → network pivot into the GTI/Glaztech environment. +**Attack chain:** (1) guess one website customer login (no lockout, username = account number, passwords as short as 3 chars, plaintext) → (2) hit an injectable payment page → (3) inject as sysadmin → total control of `GTI-INV-SQL`. As sysadmin an attacker can: steal every stored card PAN+CVV and password; DROP/encrypt all databases; commit fraud; invoke `xp_cmdshell` (already enabled — see C5) → OS-level code execution on the SQL server → pivot across 7 linked servers → domain-admin takeover. -**One guessed website login + the SQLi = full theft, destruction, or ransom of the entire GTIware database server.** +**One guessed website login + the SQLi = full theft, destruction, or ransom of the entire GTIware database server, and a path to domain-admin.** **Required remediation — do this FIRST:** -1. Pull the `tom` sysadmin login from the website. Give the site a **dedicated least-privilege login** scoped only to the tables/views/procs it needs, with **no access to GTIware databases** (no `cc_file`, no other offices, no archives). +1. Pull the `tom` sysadmin login from the website. Give the site a **dedicated least-privilege login** scoped only to the tables/views/procs it needs, with **no access to GTIware databases** (no `cc_file`, no other offices, no archives). Follow the sequencing callout in the assessment report — do NOT improvise this step. 2. **Separate the website's data from GTIware.** The internet-facing app must not share a SQL instance with the internal PSA's cardholder data. 3. **Stop storing cards on-prem** — call the processor's API/hosted vault directly (no card data lands on Glaztech systems), or at minimum tokenize (store a token, never the PAN). CVV must never be stored — PCI Req 3.2, no exception. 4. Fix the SQLi (parameterize all queries, remove `quo()`); add login lockout/rate-limiting. +### C0-Extended — Verified blast-radius and privilege-escalation chain (deep recon, 2026-06-04) + +A follow-up read-only recon of the `WWW` host and `GTI-INV-SQL` confirmed the C0 "foothold into the rest of the network" warning is not hypothetical. The path from a web compromise to full domain takeover requires **no additional vulnerability** beyond the SQLi already documented in C3. + +- **GTIware card engine co-resident in the public IIS worker:** `gt_auto_process_2020.dll` and `glaztech_utilities_2020.dll` are present in `D:\web\glaztech_4\Bin\`; their `.dll.config` files carry no connection strings of their own, so they use the website's `tom` (sysadmin) connections. A web-tier compromise lands directly inside the card-on-file write/charge engine with `sysadmin` DB rights — the "website vs. GTIware" distinction collapses for any in-process or host-level attacker. +- **`xp_cmdshell = 1` (already enabled):** `sys.configurations` shows `value_in_use = 1`. There is no "enable it first" step — a `tom` SQLi can `EXEC xp_cmdshell` for **immediate OS command execution** on `GTI-INV-SQL` (192.168.8.62). +- **SQL Agent service runs as `Administrator@glaztech.com`** (domain-admin class). Any Agent job step sysadmin `tom` can create executes as that account. +- **Cleartext `glaztech\administrator` domain-admin password in `msdb`:** Multiple backup-copy SQL Agent job steps run `EXEC xp_cmdshell 'net use \\192.168.8.52\sql_backup\... /user:glaztech\administrator /persistent:yes'`. The password is stored in `msdb.dbo.sysjobsteps`, **readable by any sysadmin/`tom` connection** — harvestable straight from the web-app SQLi without even invoking `xp_cmdshell`. **The password value was redacted from all assessment artifacts and is not reproduced here. It must be rotated — see Emergency-containment bucket E2.** +- **7 linked servers** (remote-login + data-access) spanning two subnets: `192.168.0.54,55181`; `192.168.0.55,55181` (`mas_gti` / Sage accounting); `192.168.8.52,3436` (backup); `192.168.8.212,3436` (backup); `192.168.8.62,3430` (`GTI-INV-SQL\GTISQL`); `GLAZ\TIMEFORCE` (`qqest` payroll); and `GTI-INV-SQL\GTISQL`. From the single internet-reachable `tom` credential an attacker pivots across the entire SQL estate — including accounting and payroll — on two subnets. +- **`sa` login enabled** on `GTI-INV-SQL`. +- **No TDE on any of 47 databases** (`is_encrypted=False`). CHD `.bak` backups written to `d:\sql_backup\prod\` and **copied to `\\192.168.8.52\sql_backup\`** — unencrypted cardholder data on a reachable file share. +- **`Web.config` cleartext processor secrets:** CyberSource (`cybs.Password`, `cybs.merchantID.password`, on-disk signing keys at `cybs.keysDirectory`/`cybs.keyFilename`) and PNC (`pnc_key`, `pnc_pin`, `pnc_token`) — all in `appSettings` in cleartext, readable by any `Everyone:(R)` local principal. +- **Host firewall:** Domain profile On; **Private and Public profiles Off.** Listening services include RDP (3389), SMB (445), NetBIOS (139), VNC (5800/5900), ScreenConnect (6783), WinRM (5985/47001), MSMQ (1801/210x), Dell OMSA (1311). +- **TLS 1.0 explicitly enabled** in SChannel (`Enabled=1`, Server and Client) — not merely left at OS default. +- **Full end-to-end chain:** Public site → SQLi as sysadmin `tom` → (a) read all CHD + ~9,000 plaintext passwords; (b) `xp_cmdshell` → OS RCE on DB server; (c) read cleartext `glaztech\administrator` password from `msdb`; (d) pivot across 7 linked servers (accounting, payroll, backups) on two subnets; (e) **domain admin.** In parallel, `Everyone:(R)` on `Web.config` gives a host-level attacker the same outcome without SQLi. + +### C5 — `xp_cmdshell` enabled + cleartext domain-admin in `msdb` + +`xp_cmdshell = 1` (confirmed `value_in_use = 1`) on `GTI-INV-SQL`. Combined with the cleartext `glaztech\administrator` password embedded in `msdb` job steps, a `tom` SQLi yields **immediate OS command execution on the DB server AND harvestable domain-admin credentials** — no additional exploit required. This makes C0 not just a database compromise but a direct path to full network takeover. + +**Immediate containment:** disable `xp_cmdshell`; rotate `glaztech\administrator`; remove all cleartext credential use from `msdb` job steps (updating all consumers in the same change window). See Emergency-containment bucket E2–E3. + ### Cardholder Data — PCI-DSS Violations (Req 3.2 + 3.4) -**Storage attribution (IMPORTANT):** The website stores **NO** cards. The website's `.aspx`/`.vb` files have zero `cc_file`/`save_cc_data`/`gt_auto_process` references; the quick-pay pages even carry a disclaimer that no card info is saved. The plaintext cards are written by **GTIware** — Tom's internal PSA (`glaztech_utilities_2020.dll` + `gt_auto_process_2020.dll`, compiled libs in the site `Bin` but not called by the site). Recent `cc_file` rows are stamped with staff usernames (Victoria, Bryce, Diana) and notes like "RUN CARD WHEN REQUESTED" — a back-office card-on-file workflow. The website is the **access vector** (C0), not the storer. +**Storage attribution (IMPORTANT):** The website stores **NO** cards. The website's `.aspx`/`.vb` files have zero `cc_file`/`save_cc_data`/`gt_auto_process` references; the quick-pay pages even carry a disclaimer that no card info is saved. The plaintext cards are written by **GTIware** — Tom's internal PSA (`glaztech_utilities_2020.dll` + `gt_auto_process_2020.dll`, compiled libs in the site `Bin` but not called by the site's web pages). Recent `cc_file` rows are stamped with staff usernames (Victoria, Bryce, Diana) and notes like "RUN CARD WHEN REQUESTED" — a back-office card-on-file workflow. The website is the **access vector** (C0), not the storer. However, the GTIware card engine DLLs run in-process in the public IIS worker (see C0-Extended), so a web compromise reaches the card engine directly. - **`cc_file` (~780 saved cards):** Full PAN stored in plaintext in every per-office database (`glaz_prod`, `glaz_prod_phx`, `glaz_prod_slc`, `glaz_prod_elp`, `glaz_prod_den`, `glaz_prod_alb`, `glaz_prod_boi`, `glaz_prod_brl`, `glaz_prod_shp`, `glaz_prod_corp`). Zero encrypted rows. `cc_file.cc_code` retains CVV/CID (50/54 rows in tuc; mirrors expected in all offices). **CVV retention is a PCI Req 3.2 violation — indefensible; no exception even if encrypted.** - **`cof_payments_header` (historical payments):** Phoenix alone: 14,496 rows, 11,794 plaintext PANs. Tuc: 2,245 rows, ~367 plaintext + ~597 formatted. Years of transaction history with recoverable card numbers. - **Why cards are stored:** Card-on-file invoice auto-pay. `i_get_cc_on_file_invoices` joins `invoice` × `cc_file`; `gt_auto_process_2020.dll` reads stored PANs and bills them via CyberSource. `get_cc_data` is `SELECT * FROM cc_file` (returns full PAN+CVV; IDOR-shaped on `@acctno`). Stale copies in `Old_bin`/`Old_code\Bin`. **Feature can be preserved by migrating to the chosen processor's token vault — store a token reference instead of the raw PAN.** -- **Containment:** Exposure is contained to the GTIware card-on-file tables (`cc_file`, `cof_payments_header`) in the 15 custom web-app databases on `GTI-INV-SQL` (192.168.8.62). The Sage 100 ERP DB (`mas_gti`) stores **no** cardholder data — its native CC module is **disabled** (`SY_Company.CreditCardEnable=N`, `AR_CustomerCreditCard`=0 rows; tokenization columns exist in the schema but are unused). Sage is **not** a cardholder-data location. **Database backups also contain plaintext PANs — cleanup must address backups, not just live data.** +- **Containment:** Exposure is contained to the GTIware card-on-file tables (`cc_file`, `cof_payments_header`) in the 15 custom web-app databases on `GTI-INV-SQL` (192.168.8.62). The Sage 100 ERP DB (`mas_gti`) stores **no** cardholder data — its native CC module is **disabled** (`SY_Company.CreditCardEnable=N`, `AR_CustomerCreditCard`=0 rows). Sage is **not** a cardholder-data location. **Database backups also contain plaintext PANs — cleanup must address backups, not just live data.** Backups confirmed at `\\192.168.8.52\sql_backup\` (unencrypted). - **Processor reality (verified 2026-06-03):** despite a belief that processing moved to "Payrilla/Paya," the website is **still on CyberSource/PNC** (no Payrilla anywhere in site code/config) and **still writing plaintext cards daily** (`cc_file` last write tuc 2026-06-03 14:15, phx 10:19; live `CC-WebPayment-PNC` txns today). Sage's CC module is off. Payrilla, if used, is a **separate channel not visible in either system and not connected to the website** — the website exposure is unchanged. Anomaly: `cc_file` absent in the `corp` DB though present earlier 2026-06-03 — needs a look. ### Authentication — Plaintext Passwords @@ -164,19 +187,22 @@ Function quo(stext) As String Return "'" + stext + "'" ' wraps in quotes, does NOT escape embedded quotes End Function ``` -Used to build concatenated dynamic SQL in payment pages (`ach.aspx.vb`, `quick-pay-ach.aspx.vb`, `quick-pay-pnc.aspx.vb`, `quick-pay.aspx.vb`, `order-detail*`). 59 concatenated SQL statements identified (~10 joining user input). The login path itself is parameterized (sproc) and not injectable; 948 parameterized calls elsewhere. **Any input containing `'` breaks out and allows injection; because the site connects as sysadmin, injection = full instance compromise (see C0).** +Used to build concatenated dynamic SQL in payment pages (`ach.aspx.vb`, `quick-pay-ach.aspx.vb`, `quick-pay-pnc.aspx.vb`, `quick-pay.aspx.vb`, `order-detail*`). 59 concatenated SQL statements identified (~10 joining user input). The login path itself is parameterized (sproc) and not injectable; 948 parameterized calls elsewhere. **Any input containing `'` breaks out and allows injection; because the site connects as sysadmin, injection = full instance compromise and OS RCE via `xp_cmdshell` (see C0/C5).** ### Other Critical/High Findings | Finding | Severity | |---|---| +| C5: `xp_cmdshell` enabled (`value_in_use=1`) + cleartext `glaztech\administrator` domain-admin in `msdb` SQL Agent job steps — `tom` SQLi yields immediate OS RCE + domain-admin takeover without additional exploits | Critical | | Reflected XSS: `gt_errorpage.aspx` — `errmsg` query param → `lblerr.Text` unencoded | High | | `debug="true"` + `customErrors=Off` + exceptions echoed to users in URLs | High | | Production server is also a dev workstation: VS Community 2015 + 2022, .NET 8 SDKs, MSBuild, IIS Express, full VB.NET source on disk | High | -| Remote-access sprawl: RealVNC Enterprise E4.2.8 (~2009, EoL), stale ScreenConnect v6.0.11622 (2018), Splashtop, Datto RMM+EDR, Syncro, GuruRMM (6+ agents) | High | -| Server listener accepts TLS 1.0 + 1.1 (SChannel Enabled=1) | High | -| Single shared SQL login (`tom`) with sysadmin rights; creds in `Web.config` in cleartext | High | +| H2: End-of-life RealVNC 4.x (≈2009, EoL) listening on 5900/5800 — **Steve's tool**; other remote-access agents (both ScreenConnect instances including `kgc7jt` cloud, Datto RMM/EDR, Syncro, Splashtop, GuruRMM) are ACG's sanctioned management stack, not findings | High | +| Server listener accepts TLS 1.0/1.1 (SChannel `Enabled=1` explicitly set) | High | +| Single shared SQL login (`tom`) with sysadmin rights; creds in `Web.config` in cleartext; `Everyone:(R)` ACL on web root + bin + Web.config | High | | No Secure/HttpOnly cookies; no session regeneration on login; session-fixation risk; no MFA, no lockout; H5 detection blind spot (see below) | High | +| H9: No TDE on any of 47 databases; CHD `.bak` backups copied unencrypted to `\\192.168.8.52\sql_backup\` | High | +| H10: Host firewall Private/Public profiles Off; 7 linked servers form a cross-subnet lateral mesh reachable from `tom`; RDP/SMB/VNC/WinRM/MSMQ all listening | High | ### H5 Detection Blind Spot — No Failed-Login Visibility @@ -186,7 +212,7 @@ The employee login (`/emp/employee-login.aspx`) returns **HTTP 200 on both succe ### Attack Chain Summary -Obtain a customer login (LOW difficulty — no lockout, guessable username = account number, plaintext passwords as short as 3 chars) → access payment pages → SQL inject with `quo()` → executes as **sysadmin** on `GTI-INV-SQL` → full read/write/DROP of all 46 databases, `xp_cmdshell` OS takeover, network pivot. **Every compensating control (lockout, password hashing, PAN encryption, parameterized queries, least-privilege DB login) is absent; first failure is last failure.** +Obtain a customer login (LOW difficulty — no lockout, guessable username = account number, plaintext passwords as short as 3 chars) → access payment pages → SQL inject with `quo()` → executes as **sysadmin** on `GTI-INV-SQL` → `xp_cmdshell` (already enabled, no extra step) → OS RCE on DB server → read cleartext `glaztech\administrator` domain-admin password from `msdb` → pivot across 7 linked servers → **domain admin**. **Every compensating control (lockout, password hashing, PAN encryption, parameterized queries, least-privilege DB login, `xp_cmdshell` disabled, no cleartext domain-admin in DB) is absent; first failure is last failure.** ### Intrusion / Brute-Force Log Review — 2026-06-04 (No Evidence of Attack) @@ -203,22 +229,35 @@ Full detail in `clients/glaztech/reports/2026-06-03-website-security-assessment. ### Remediation Roadmap (Ticket #32378 — Waiting on Customer) -**Now (days) — requires client sign-off:** -1. Pull sysadmin login from the website: give the site a dedicated least-privilege login with no access to GTIware/card data (this alone cuts the blast radius of a breach from "total GTIware compromise" to "website DB only") -2. Purge stored CVV (`cc_file.cc_code`, backup-first — needs Tom/Steve explicit sign-off) +**Emergency containment (THIS WEEK — closes the trivially-exploitable internet-to-domain-admin path while it is open):** +- **E1.** Remove `Everyone:(R)` from `D:\web\glaztech_4`, its `bin`, and `Web.config` — scope to the app-pool identity + required admins only +- **E2.** Rotate `glaztech\administrator` and remove every embedded cleartext use of it from the `msdb` SQL Agent backup-copy job steps, updating all consumers in the same change window; pause those jobs until they use a dedicated low-privilege account +- **E3.** Disable `xp_cmdshell` on `GTI-INV-SQL` (`sp_configure 'xp_cmdshell', 0`); verify on linked instances too +- **E4.** De-privilege the SQL Agent service account off domain-admin to the minimum needed; disable the built-in `sa` login (or confirm strong, unique password + restricted use) +- **E5.** Turn the Private/Public host-firewall profiles back On; replace/disable end-of-life RealVNC 4.x (coordinate with Steve); restrict WinRM/MSMQ/Dell-OMSA to specific management IPs + +**Coord todos filed for E2–E4:** `6d15fc88` (rotate `glaztech\administrator` + remove `msdb` cleartext use; disable `xp_cmdshell`/`sa`) and `aebaf751` (least-privilege `tom` migration). + +**Now (days) — start immediately after Emergency containment:** +1. Pull sysadmin login from the website: give the site a dedicated least-privilege login with no access to GTIware/card data — **strictly per the "Sequencing the least-privilege DB migration" callout in the assessment report** (do NOT improvise) +2. Purge stored CVV (`cc_file.cc_code`, backup-first — needs Tom/Steve explicit sign-off); stop writing new CVV to `cc_code` going forward 3. `debug="false"` + `customErrors="On"`; HTML-encode `gt_errorpage.aspx`; stop echoing exception text to users -4. Remove RealVNC 4.2.8 and stale ScreenConnect v6 -5. Disable TLS 1.0/1.1 on the IIS/SChannel listener +4. Add failed-login logging (timestamp, username, source IP) and basic throttling/lockout immediately +5. Add security response headers (CSP first — partial XSS mitigation — plus HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy) +6. Remove RealVNC 4.2.8 and stale ScreenConnect v6 (if E5 not already done) +7. Disable TLS 1.0/1.1 on IIS/SChannel listener **Short term (weeks):** -6. Hash all passwords (PBKDF2/bcrypt/Argon2); replace email-the-password flow with reset-token flow; force global reset -7. Parameterize all concatenated SQL in payment pages; delete `quo()` -8. Add Secure+HttpOnly cookies, session regeneration on login, login throttling/lockout, **failed-login logging (timestamp, username, source IP)** -9. Migrate card-on-file to the chosen processor's token vault (CyberSource or new provider — confirm which flows actually route through "Payrilla"); purge/encrypt historical `cc_number` columns; address backups +8. Hash all passwords (PBKDF2/bcrypt/Argon2); replace email-the-password flow with reset-token flow; force global reset +9. Parameterize all concatenated SQL in payment pages; delete `quo()` +10. Add Secure+HttpOnly cookies, session regeneration on login, CSRF anti-forgery tokens on payment/ACH/quick-pay POSTs +11. Migrate card-on-file to the chosen processor's token vault (CyberSource or new provider); purge/encrypt historical `cc_number` columns; address backups; move CyberSource + PNC gateway secrets out of `Web.config` **Structural:** -10. Separate dev from production; deploy precompiled; remove SDKs/IDE/source from prod host -11. Least-privilege SQL accounts per function; secret management for Web.config connection strings; TDE at rest; re-scope merchant PCI SAQ after remediation +12. Separate dev from production; deploy precompiled; remove SDKs/IDE/source from prod host +13. Decouple the GTIware card engine from the public IIS process — run it off a non-CDE host with its own dedicated low-privilege DB login +14. Enable TDE on all databases; audit and minimize the 7 linked servers; restrict backup shares to specific management IPs; network segmentation for the SQL listener +15. Lock down `/webhooks` and `/webhooks1` (Samsara); recon the second host `\\192.168.0.147\web\glaztech_4`; re-scope merchant PCI SAQ after remediation ## Patterns & Known Issues @@ -239,8 +278,11 @@ Full detail in `clients/glaztech/reports/2026-06-03-website-security-assessment. - **MailProtector digest provisioning is per-mailbox on the MailProtector side:** The SCL=-1 transport rule (Priority 4) ensures digest emails from `noreply@azcomputerguru.com` are not spam-filtered by EOP — but a mailbox that was never provisioned in MailProtector will never receive a digest regardless of EOP rules. Confirmed via message trace (shannon@glaztech.com: 629 digests sent to ~60 recipients over 10 days, 0 to Shannon). Fix is on the MailProtector partner portal — no Exchange change needed. - **Glaztech custom web app — stored card feature requires tokenization to remediate safely:** Cards in `cc_file` are there for GTIware auto-pay via `gt_auto_process_2020.dll`. Deleting the PANs without a replacement breaks the auto-billing feature. The safe path is processor token vault migration (tokenize on write, replace stored PAN with token, update `gt_auto_process` to bill by token). Quick win: purge CVV (`cc_code`) immediately — this has no functional impact and is the fastest PCI Req 3.2 remediation. - **Glaztech SQL login (`tom`) + Web.config creds are NOT in the SOPS vault.** Do not commit these credentials. If future automation needs SQL access, vault them first. This login has sysadmin rights — treat any use with corresponding care. -- **Internet-facing website + internal PSA (GTIware) share one SQL instance; website connects as sysadmin → any website SQLi = full internal-DB compromise.** The public website (`WWW`, 65.113.52.88) and GTIware (the internal card-on-file PSA) both use `GTI-INV-SQL` (192.168.8.62,3436). The web login `tom` is sysadmin. A SQL injection on the website executes as sysadmin against the entire 46-DB instance — cross-DB reads confirmed live. Public web apps must use least-privilege DB logins isolated from internal data. Internet-facing apps must never share a SQL instance with an internal PSA without strict permission partitioning. +- **Internet-facing website + internal PSA (GTIware) share one SQL instance; website connects as sysadmin → any website SQLi = full internal-DB compromise AND OS RCE via `xp_cmdshell`.** The public website (`WWW`, 65.113.52.88) and GTIware (the internal card-on-file PSA) both use `GTI-INV-SQL` (192.168.8.62,3436). The web login `tom` is sysadmin. `xp_cmdshell` is already enabled. A SQL injection on the website executes as sysadmin against the entire instance, can immediately run OS commands, and can harvest the cleartext domain-admin password from `msdb` — no extra steps. Cross-DB reads confirmed live. Internet-facing apps must never share a SQL instance with an internal PSA without strict permission partitioning. +- **`xp_cmdshell` is enabled on `GTI-INV-SQL`; cleartext domain-admin password is in `msdb` job steps.** These are the two facts that elevate C0 from "database compromise" to "network takeover." Disable `xp_cmdshell` and rotate `glaztech\administrator` (with all `msdb` job steps updated in the same window) before any other remediation work — see Emergency-containment E2/E3. Do not rotate the domain-admin password without first identifying and updating every job step and linked-server connection that uses it. +- **ACG management stack on WWW is fully sanctioned:** Both ScreenConnect instances (including `kgc7jt` ScreenConnect Cloud), Datto RMM/EDR, Syncro, Splashtop, and GuruRMM are ACG's own tools. An earlier draft of the assessment mis-flagged the `kgc7jt` instance as "foreign/unrecognized third-party access" — that finding was **fully retracted**. The only genuine remote-access finding is end-of-life RealVNC 4.x (Steve's personal tool, ≈2009 build, EoL). Do not treat ACG's management agents as security findings. - **Employee login HTTP 200 on both success and failure — status code is not a success/failure signal; no failed-login logging exists:** `/emp/employee-login.aspx` returns HTTP 200 regardless of outcome (no redirect-on-success pattern). The application logs no failed login attempts anywhere, and app-level auth does not generate Windows Security log events. A slow credential-guessing campaign against staff or customer accounts would be completely invisible: no lockout triggers, no log to audit after the fact. Confirmed during the 2026-06-04 log review — the 381 "200 responses" on the employee portal that initially appeared anomalous proved to be normal authenticated sessions. Fix: add failed-login logging + account lockout. Do not treat HTTP status code as an auth-outcome signal on this endpoint. +- **GTIware card engine DLLs are co-resident in the public IIS worker.** `gt_auto_process_2020.dll` and `glaztech_utilities_2020.dll` live in `D:\web\glaztech_4\Bin\` and load in-process into `w3wp` (PID 13752, app pool `glaztech_new`). Their `.dll.config` carry no connection strings — they use the website's `tom` (sysadmin) connections. The "website vs. GTIware" distinction collapses for any in-process or host-level attacker. A web compromise reaches the card-on-file write/charge engine directly. A second execution path (`d:\sql_jobs\bin\gt_console_apps.exe`) runs server-side via the Agent (domain-admin account). Both paths must be decoupled from the internet-facing host in the structural remediation. ## Active Work @@ -268,16 +310,22 @@ MFA rollout plan: Phase 1 — user communication (install Authenticator); Phase ### Website Security Remediation (Ticket #32378 — Waiting on Customer) -Security assessment complete 2026-06-03. Intrusion/brute-force log review complete 2026-06-04 (no attacker found; detection gap confirmed). Assessment and reports delivered to client (Steve/Tom). Tom replied 2026-06-03 confirming that the website stores no cards (correct); investigation of his reply surfaced C0 (sysadmin login). Reply posted on #32378 explaining the sysadmin+SQLi chain and the four required remediations. Ticket set to **Waiting on Customer** — Tom/Steve to remediate. ACG can execute quick wins (CVV purge, least-privilege login, debug-off) on client go-ahead. +Security assessment complete 2026-06-03. Intrusion/brute-force log review complete 2026-06-04 (no attacker found; detection gap confirmed). Deep host + SQL-infrastructure recon complete 2026-06-04 (C0-Extended; C5/H9/H10 findings; Emergency-containment bucket). Assessment and reports delivered to client (Steve/Tom). Tom replied 2026-06-03 confirming that the website stores no cards (correct); investigation of his reply surfaced C0 (sysadmin login). Reply posted on #32378 explaining the sysadmin+SQLi chain and the four required remediations. Ticket set to **Waiting on Customer** — Tom/Steve to remediate. ACG can execute quick wins on client go-ahead. -Key actions queued but not yet executed (require client sign-off): -- Pull `tom` sysadmin login from the website → replace with least-privilege login that cannot see GTIware data (HIGHEST PRIORITY) -- Purge CVV from `cc_file.cc_code` (backup-first; needs explicit go-ahead from Tom) +**Open coord todos:** +- `6d15fc88` — rotate `glaztech\administrator` + remove cleartext from `msdb` job steps; disable `xp_cmdshell`; disable `sa` (Emergency-containment E2–E4) +- `aebaf751` — least-privilege `tom` migration (replace website's sysadmin login with a scoped low-privilege login) + +Key actions queued but not yet executed (require client sign-off, ordered by urgency): +- **Emergency-containment E1–E5 first** (see roadmap above — these close the domain-admin exposure this week) +- Pull `tom` sysadmin login from the website → replace with least-privilege login (HIGHEST PRIORITY after E-bucket, per sequencing callout in assessment report) +- Purge CVV from `cc_file.cc_code` (backup-first; needs explicit go-ahead from Tom); stop writing new CVV - `debug="false"` + `customErrors="On"` — can apply quickly with low risk - Remove RealVNC 4.2.8 and stale ScreenConnect v6 - Disable TLS 1.0/1.1 on IIS/SChannel listener - Add failed-login logging + account lockout (reinforced by 2026-06-04 log review finding) - App-side investigation of HTTP 500 bursts on post-login pages (possible SQLi error path) — IPs `201.146.179.166`, `64.178.182.162`, `205.185.107.49`, `172.87.137.60`; not yet handed to Tom +- Lock down `/webhooks` and `/webhooks1` (Samsara); recon `\\192.168.0.147\web\glaztech_4` ### gtimail@glaztech.com Daily Digest Failure (Pending — review with Steve) @@ -302,6 +350,10 @@ Message trace confirmed shannon@glaztech.com receives no MailProtector digests a - Investigate `corp` DB `cc_file` "Invalid object name" anomaly (existed 2026-06-03 morning with 3 rows, then returned "Invalid object name" later same day — per-office DBs unaffected) - Confirm with Tom/Payrilla which flows actually route through Payrilla, and whether a migration to tokenized card storage via the new provider is planned for the website - Optional: enumerate listening/forwarded ports on `WWW` to confirm RDP is not internet-exposed (log review strongly implies it is not; a port enumeration would make it definitive) +- Verify IDOR on `get_cc_data(@acctno)` — confirm `@acctno` is bound server-side to the session (not client-supplied); if not, this is a second full-PAN read path independent of the SQLi +- Recon second host `\\192.168.0.147\web\glaztech_4` — same code/secrets/DLLs? public-facing? bring into scope +- Audit and minimize the 7 linked servers (remove any not required; restrict remote-login + data-access) +- Confirm backup share ACLs at `\\192.168.8.52\sql_backup\` and retention/disposal policy for CHD-laden backups ## History Highlights @@ -314,7 +366,8 @@ Message trace confirmed shannon@glaztech.com receives no MailProtector digests a - **2026-06-02** — MailProtector quarantine digest messages from `noreply@azcomputerguru.com` confirmed hitting `FilteredAsSpam` for some recipients (e.g., tshaw@glaztech.com). Transport rule created: "SCL Bypass - noreply@azcomputerguru.com (MailProtector digests)" at Priority 4 (From=noreply@azcomputerguru.com, SetSCL=-1). Message trace via `Get-MessageTraceV2` also revealed `gtimail@glaztech.com` failing daily due to pre-existing Priority-1 reject rule — flagged for Steve review. - **2026-06-03 (earlier)** — Three tickets on web server `WWW` (192.168.8.72 / 65.113.52.88), all via GuruRMM. (1) **Apex 404 emergency:** glaztech.com returned 404 (IIS site `glaztech_new` had www-only binding); added apex http:80+https:443 bindings (cert SAN already covered apex), then added HTTP→HTTPS 301 URL Rewrite redirect with `/.well-known/acme-challenge/` exclusion (Certify/LE HTTP-01 renewal safe). `web.config.bak-20260603-090701` created. Ticket #32376 — Resolved, 1h remote. (2) **CyberSource payment outage ("Could not create SSL/TLS secure channel"):** CyberSource (PNC merchant processor) disabled TLS 1.0/1.1; .NET 4.x on Server 2019 defaulted to old TLS. Fix: `SchUseStrongCrypto=1` + `SystemDefaultTlsVersions=1` in both `.NETFramework\v4.0.30319` hives + app pool `glaztech_new` recycle. Verified via payments DB (credit-card approval at 09:36 post-fix). Ticket #32377 — Resolved, 1.5h emergency remote. (3) **Security assessment:** read-only deep inspection of IIS config, VB.NET source, and SQL backend revealed CRITICAL posture. Sage 100 (`mas_gti`) confirmed NOT a cardholder-data location — CC module disabled (0 stored cards). Two reports created. Ticket #32378 opened. Billed 1h remote. Prepaid block: 26.5 → 22.25 hrs. Also: shannon@glaztech.com digest-not-received confirmed as MailProtector provisioning issue (not Exchange) — requires MailProtector partner-portal fix. Payrilla/CyberSource reconciliation: live system confirmed website is still on CyberSource/PNC with daily ongoing card writes. - **2026-06-03 (late — ~19:32 PT)** — **Tom (GTIware dev) replied to #32378** clarifying that the website's online payment system stores no card data — he is correct. Investigation of Tom's reply surfaced the **top critical finding (C0):** the website connects to the shared SQL server `GTI-INV-SQL` (192.168.8.62,3436) as SQL login `tom`, a **named SQL login that is a member of the `sysadmin` role** (created 2018; password in `Web.config`). The instance hosts 46 databases shared between GTIware and the website. Because SQLi executes as the connecting login, the website's `quo()` injection = sysadmin over the entire `GTI-INV-SQL` instance; cross-database card-table reads confirmed live. **Attribution corrected in both reports:** the website is the access path (C0); GTIware (staff-operated) writes the cards. Sage CC module confirmed disabled (0 stored cards, not a CHD location). Both reports updated. Plain-English reply posted to Tom on #32378 (public+emailed, comment 417070212) explaining the sysadmin+SQLi chain and the four required fixes. Ticket set to **Waiting on Customer**. -- **2026-06-04** — **Read-only intrusion/brute-force log review** on `WWW` (GuruRMM agent 455a1bc7, v0.6.54). Reviewed 7 days of IIS W3SVC4 logs (~52,000 requests, May 29 – Jun 4) and Windows Security event log (4625/4624 events, 7-day window, log retained back to 2026-03-31). **Finding: NO evidence of a brute-force or intrusion attempt** against the website logins or the Windows server. Customer login traffic is normal (2,547 successes/740 IPs). Employee login: initial "381 failures" corrected — the employee login returns HTTP 200 on BOTH success and failure (status code is not an auth-outcome signal); all flagged IPs proved to be legitimate employees reaching protected pages post-login. Windows Security log: 13 failed logons in 7 days, all SMB type 3 from internal LAN IPs, zero external, no RDP failures — RDP/SMB not internet-exposed. **Key confirmation:** the H5 detection blind spot is real — 200-on-both + no failed-login logging + no lockout = a slow guessing attack would currently be completely invisible. HTTP 500 bursts on post-login pages flagged as an open app-side item. Findings folded into the security report as Appendix A. Ticket #32378 remains Waiting on Customer. +- **2026-06-04 (morning)** — **Read-only intrusion/brute-force log review** on `WWW` (GuruRMM agent 455a1bc7, v0.6.54). Reviewed 7 days of IIS W3SVC4 logs (~52,000 requests, May 29 – Jun 4) and Windows Security event log (4625/4624 events, 7-day window, log retained back to 2026-03-31). **Finding: NO evidence of a brute-force or intrusion attempt** against the website logins or the Windows server. Customer login traffic is normal (2,547 successes/740 IPs). Employee login: initial "381 failures" corrected — the employee login returns HTTP 200 on BOTH success and failure (status code is not an auth-outcome signal); all flagged IPs proved to be legitimate employees. Windows Security log: 13 failed logons in 7 days, all SMB type 3 from internal LAN IPs, zero external, no RDP failures. **Key confirmation:** the H5 detection blind spot is real — 200-on-both + no failed-login logging + no lockout = a slow guessing attack would currently be completely invisible. HTTP 500 bursts on post-login pages flagged as an open app-side item. Findings folded into security report as Appendix A. Ticket #32378 remains Waiting on Customer. +- **2026-06-04 (09:38 PT) — Deep host + SQL-infrastructure recon (Grok gap-analysis loop).** Collaborative gap-analysis (Claude + Grok CLI, 4 turns, session `019e9351-ed1c-7bc3-b171-b4cf4b53745d`) plus 3 read-only GuruRMM pulls on `WWW` (recon1/recon2/recon3). New confirmed findings folded into assessment report as **C0-Extended**, findings **C5/H9/H10**, and **Emergency-containment roadmap bucket (E1–E5)**. Key discoveries: GTIware card engine co-resident in public IIS worker on `tom` sysadmin connection; `xp_cmdshell=1` already enabled on `GTI-INV-SQL`; SQL Agent runs as domain-admin `Administrator@glaztech.com`; cleartext `glaztech\administrator` domain-admin password embedded in `msdb` job steps (redacted; must rotate); 7 linked servers spanning two subnets; `sa` enabled; all 47 DBs unencrypted; `Everyone:(R)` ACL on web root; firewall Private/Public Off; TLS 1.0 explicitly Enabled=1; new Samsara webhook endpoints. **Retraction:** earlier draft mis-flagged `kgc7jt` ScreenConnect Cloud as "foreign/unrecognized third-party access" (draft finding C6) — **fully retracted**; both ScreenConnect instances and all other management agents (Datto RMM/EDR, Syncro, Splashtop, GuruRMM) are ACG's sanctioned stack. RealVNC 4.x remains H2 (EoL, Steve's tool). Two coord todos filed: `6d15fc88` (domain-admin rotation + xp_cmdshell/sa) and `aebaf751` (least-priv `tom` migration). ## Backlinks