Scope (v0.3) for replacing the website's sysadmin login 'tom' with a least-privilege login: two-phase plan (GTIware co-residency forces keeping cc_file in Phase 1), Grok + Gemini independent review folded in, and live RMM recon findings that materially changed the picture - the website is a cross-office + Sage accounting + payroll + msdb hub on one sysadmin credential, SQL is centralized on GTI-INV-SQL\GTISQL:3436 (not per-site). PARKED pending a full network recon. Session log covers the website outage fix (incomplete E1 ACL hardening) + the scoping + recon. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
11 KiB
Glaztech Session Log — 2026-06-05
User
- User: Mike Swanson (mike)
- Machine: GURU-5070
- Role: admin
Session Summary
Two threads on Glaztech today: (1) a customer-facing website outage that was diagnosed and resolved, and (2) scoping the least-privilege SQL login migration (#32378 / coord todo aebaf751), which turned into a significant infrastructure-recon effort that materially changed the understanding of the environment.
Outage: glaztech.com (WWW, 192.168.8.72 / 65.113.52.88) returned site-wide HTTP 500 then 401. Root cause: a 2026-06-04 change applied the E1 hardening (removed the insecure Everyone:(R) from the web root D:\web\glaztech_4) but did not restore read access for the IIS serving accounts — and this server's IIS_IUSRS group was non-default, missing IUSR (the anonymous-auth identity). The IIS worker could load the app (DLLs + Web.config had explicit grants) but could not read the ~43,600-file content tree → 500.50 then 401.3 (access-denied-by-ACL). A web.config rollback was a red herring (preserved as Web.config.broken-20260605-084124). Fix (least-privilege; Everyone stays removed — completing E1 correctly): added IUSR + IIS APPPOOL\glaztech_new to IIS_IUSRS, granted IIS_IUSRS ReadAndExecute across the content tree (detached icacls — slow on 43.6K files, exceeded the agent command timeout), then iisreset to regenerate the cached IUSR token (an app-pool recycle was insufficient). Verified: last 60 requests 55x 200 / 0x 401 / 0x 500; external 200s on apex, www, customer_login.aspx, and product images. Posted a customer-visible #32378 comment ("Website service restored"), then resent it after Mike updated the ticket contacts (Tom primary, Alex + Steve CC).
Least-privilege scope: drafted a full scope for replacing the website's sysadmin login tom with a least-privilege login. The central constraint is GTIware co-residency (in-process card-engine DLLs share the website's Web.config connection and need cc_file), forcing a two-phase plan (Phase 1 strip sysadmin + the OS-RCE/domain-admin/cross-office/linked-server blast radius, keep cc_file; Phase 2 DENY cc_file after GTIware is decoupled). Routed the scope to Grok 4.3 and Gemini 3 Pro for independent adversarial review — both CONCUR with the two-phase approach and the matrix, with no material disagreement. Corrections folded in: don't DENY tempdb; audit linked-login catch-all mappings; dynamic SQL breaks ownership chaining; app-pool recycle to flush the ADO.NET pool on swap and rollback; alphanumeric-only interim password; fixed a rotation-gating contradiction; don't overstate Phase 1 (containment, not card-safety).
Recon — the picture changed: Mike suspected per-site SQL servers across a meshed 192.168.0-9.x network. Read-only RMM recon (GuruRMM agents on WWW + GTI-INV-SQL) showed it's centralized now (his memory matches the OLD topology, preserved in commented-out Web.config strings). All office data lives on one instance GTI-INV-SQL\GTISQL (192.168.8.62,3436, SQL 2012) — ~57 per-office DBs; a separate default instance (2008 R2) holds payroll/reporting; a third instance is on :3430. The website's Web.config revealed its true footprint: ~15 connection strings, all as tom, reaching all 10 offices' glaz_prod_* DBs + Sage accounting (mas_gti @ 192.168.0.55) + payroll (qqest) + msdb. That contradicts the scope's "DENY other offices/accounting/payroll/msdb" — the app legitimately uses them, shrinking Phase 1's value and favoring the architectural fixes. Mike parked the migration pending a real network recon (he's enrolling the site servers in RMM) and saved everything.
Key Decisions
- Outage fix completed E1 correctly (least-privilege ACL,
Everyonestays removed) rather than reverting Tom's hardening — turned the incident into a remediation step done right. iisresetover app-pool recycle — the anonymousIUSRtoken is cached at the IIS service level; only a full reset picks up the newIIS_IUSRSmembership.- Detached
icaclsto escape the agent command timeout on the 43.6K-file ACL propagation. - No blame in the ticket comment (Mike's instruction) — described only what was done; customer-visible + emailed to the updated contacts.
- Two-phase least-privilege migration forced by GTIware co-residency; routed to two independent models for concurrence before treating it as execution-ready.
- Parked the migration once recon showed the website is a cross-office + accounting + payroll + msdb hub on one sysadmin credential — a clean least-priv login barely exists; the durable fix is architectural, and a full network recon is the prerequisite.
Problems Encountered
icacls /Ton 43,602 files exceeded the agent command timeout repeatedly → ran it detached (Start-Process) and polled a completion marker.- App-pool recycle didn't clear
401.3→ root cause was the cached IUSR token;iisresetresolved it. web.configrollback didn't fix the outage (it was an ACL problem, not config) — preserved Tom's file rather than discarding his hardening.- Recon hit the wrong SQL instance first (default instance via
localhost -E); the cards instance is the namedGTISQLon:3436. SYSTEM(agent) is not sysadmin on:3436, so the authoritative login/role/tommap there still needs thetomcredential or a sysadmin Windows login.
Configuration Changes
Glaztech WWW (192.168.8.72) — production server, via GuruRMM:
IIS_IUSRSlocal group: addedNT AUTHORITY\IUSRandIIS APPPOOL\glaztech_new(were missing — non-default).icacls "D:\web\glaztech_4" /grant "IIS_IUSRS:(OI)(CI)(RX)" /T— granted app-pool/anonymous read across the content tree (completes E1;Everyone:(R)remains removed).iisreset /restart.Web.configrolled back toWeb.config.bak-20260604-170500(the working 6/3 version); Tom's 6/4 edit preserved asWeb.config.broken-20260605-084124(NOT the cause; contains debug=false + security headers + secure cookies, for re-apply after coordinating with Tom).
Repo:
- Created
clients/glaztech/reports/2026-06-05-least-privilege-db-migration-scope.md(v0.3 — scope + Grok/Gemini review + recon findings; PARKED). - Created this session log.
Syncro:
- #32378 comment 417493519 ("Website service restored", customer-visible) + resend 417494988 to updated contacts.
Infrastructure & Servers (Glaztech SQL topology — corrected 2026-06-05)
- GTI-INV-SQL (machine, 192.168.8.62, at "INV - Involta" colo) runs 3 SQL instances:
- Default instance — SQL Server 2008 R2 (10.50.2550), DBs:
qqest, ReportServer(+TempDB), system.NT AUTHORITY\SYSTEMIS sysadmin here. GTI-INV-SQL\GTISQLon port 3436 — SQL Server 2012 (11.0.7507) — the cards/website instance, ~57 DBs:glaz_prod_<office>+_archive+_webfor alb, boi, brl, corp, den, elp, phx, shp, slc, tuc, PDF stores (glaz_pdf*),gti_samsara,qqest.xp_cmdshell=1.SYSTEMis NOT sysadmin here.- Third instance on 192.168.8.62,3430.
- Default instance — SQL Server 2008 R2 (10.50.2550), DBs:
- Linked servers (from
:3436): 192.168.0.54,55181 · 192.168.0.55,55181 (mas_gti/Sage) · 192.168.8.52,3436 (backup) · 192.168.8.212,3436 (backup) · 192.168.8.62,3430 ·GLAZ\TIMEFORCE(qqest). All data-access enabled; default-instance linked logins map(default-all) → tom. - Website (
WWW) connection strings (active, alluser id=tom): glaz_prod (tuc), glaz_prod_phx/_slc/_elp/_den/_alb/_boi/_brl/_shp/_corp, glaz_pdf, glaz_pdf_corp — all on 192.168.8.62,3436;mas_gti@ 192.168.0.55,55181 (Sage);qqestvia glaz\timeforce (payroll);msdb@ 192.168.8.62,3436 (glaztech_jobs). - Old (commented-out) topology (matches Mike's per-site memory): per-office ports
glaz,3430(tuc) / 3432 (phx) / 3438 (slc) / 3431 (elp) / 3435 (den) / 3433 (alb) / 3437 (boi) / 3439 (brl);sql1,3436;sql3,3430. Since consolidated. tomSQL login created 2017-12-30; sysadmin; cross-mesh remote login. Password in WWWWeb.config(cleartext, NOT vaulted; redacted from all artifacts).- GuruRMM Glaztech agents (4): WWW (455a1bc7), GTI-INV-SQL (869e56b4), GTI-INV-DC, GTI-INV-DC1.
Commands & Outputs (key)
# Outage fix (WWW, via /rmm)
net localgroup IIS_IUSRS IUSR /add ; net localgroup IIS_IUSRS "IIS APPPOOL\glaztech_new" /add
icacls "D:\web\glaztech_4" /grant "IIS_IUSRS:(OI)(CI)(RX)" /T /C /Q # 43,602 files; run detached
iisreset /restart
# verify: last 60 IIS requests -> 55x200 0x401 0x500 ; external 200 on apex/www/login/images
# SQL recon (GTI-INV-SQL, via /rmm, sqlcmd -S localhost[,3436] -E, read-only)
SELECT name FROM sys.databases # default inst: qqest/ReportServer/system ; :3436: ~57 glaz_prod_* etc
SELECT name,data_source FROM sys.servers WHERE is_linked=1 # the mesh (0.54/0.55/8.52/8.212/8.62:3430/timeforce)
# Web.config connectionStrings on WWW -> all user id=tom across all offices + mas_gti + qqest + msdb
Pending / Incomplete Tasks
- Least-privilege
tommigration — PARKED pending a full network recon (Mike enrolling site servers in RMM) to map how the estate fits together; the website's true footprint (all offices + accounting + payroll + msdb) makes a clean least-priv login barely viable → reconsider in favor of the architectural fixes (assessment items 16-17, 22). Scope:clients/glaztech/reports/2026-06-05-least-privilege-db-migration-scope.md(v0.3). Coord todoaebaf751. - Authoritative
:3436login/role recon still needs thetomcredential (or a sysadmin Windows login) —SYSTEMisn't sysadmin there. - Emergency containment (E2-E5) still open and now more urgent: E2 (rotate
glaztech\administrator+ strip cleartext frommsdbjob steps) is a hard prerequisite because the website legitimately holds anmsdbconnection. E3 (disablexp_cmdshell— still =1 on:3436), E4 (de-priv SQL Agent / disablesa), E5 (firewall/RealVNC). - Tom's
web.confighardening (debug=false + security headers + secure cookies) preserved on WWW; re-apply after coordinating with Tom. - Whole web-app remediation remains parked on #32378 (Waiting on Customer).
- Failed-login detection/lockout (H5): options laid out; waiting on Tom (app-side) — no evidence of active attack.
Reference Information
- Scope doc:
clients/glaztech/reports/2026-06-05-least-privilege-db-migration-scope.md - Assessment:
clients/glaztech/reports/2026-06-03-website-security-assessment.md - Ticket: #32378 (id 112111185), Waiting on Customer. Comments 417493519 + 417494988.
- Coord todos:
aebaf751(least-privtommigration),6d15fc88(E2-E4 containment). - GuruRMM: WWW agent
455a1bc7-1c29-42bc-b597-fa1e64f08eec; GTI-INV-SQL agent869e56b4-e8ed-4808-8c88-782d1577c152.