# DECOMPILATION of iRely.Web.dll — authentication configuration (OWIN + IdentityServer3)

Date: 2026-09-16. Source: `D:\i21App\2210CherryEnergyUAP1\bin\iRely.Web.dll` (515148 bytes).
Method: download via `certutil -encode` → `type` via xp_cmdshell → decode base64.
Decompilation: `monodis --typedef` + `strings` (ilspycmd requires .NET 6, not available).

---

## Authentication architecture

iRely i21 uses **OWIN + IdentityServer3 + ASP.NET Identity** (not simple CookieAuth).

### Found components (from strings in the DLL):

**OWIN/IdentityServer3:**
- `iRely.Web.Startup` — OWIN startup class
- `ConfigureIdentityServer` — IdentityServer3 configuration method
- `IdentityServer3.Core.Configuration.IdentityServerOptions`
- `IdentityServer3.Core.Services.InMemory` — InMemory stores (signing keys, clients)
- `IdentityServer3.AspNetIdentity.AspNetIdentityUserService` — ASP.NET Identity integration

**Cookie names:**
- **`.AspNet.ApplicationCookie`** — main auth cookie (ASP.NET Identity default)
- `ExternalCookie` — external auth intermediate cookie
- `TwoFactorCookie` — 2FA cookie
- `idsrv:*` — IdentityServer cookies (idsrv:IdentityServerBasePath, idsrv:IdentityServerHost)

**IdentityServer endpoints:**
- `/identityserver/connect/authorize` — OAuth2 authorization endpoint
- `/identityserver/select-company` — custom company-selection endpoint
- `/signoutcleanup` — signout cleanup
- `idsrv3test.pfx` — **IdentityServer signing certificate** (in `\IdSvr\idsrv3test.pfx`)

**Token/Auth:**
- `Bearer` — bearer token auth (API endpoints)
- `Authorization=Bearer <token>` — API authorization format
- `access_token` — OAuth2 access token
- `grant_type=authorization_code` — OAuth2 authorization code flow
- `client_id`, `client_secret`, `redirect_uri`, `code` — OAuth2 parameters

**External integrations:**
- `HubSpot` — OAuth2 integration (`https://api.hubapi.com/oauth/v1/token`, `refreshToken`)
- `Google Authenticator` — 2FA (TOTP)
- `AzureAD` — Azure AD integration (ClientId, Authority, `https://login.microsoftonline.com/`)
- `FormRecognizerKey`, `FottForSharedToken` — Azure Form Recognizer

**SQL (for auth):**
- `SELECT TOP 1 [ssses_key] FROM sssesmst WHERE LTRIM(RTRIM(ssses_user_id)) = @userId ORDER BY [ssses_key] DESC` — sessions
- `INSERT INTO sssesmst(ssses_key, ...)` — session creation

**Other secrets in the DLL:**
- `GoogleSecretKey`, `GoogleSiteKey` — reCAPTCHA (duplicate of Web.config)
- `AzureApplicationInsightsInstrumentationKey` — App Insights
- `PowerBIClientId` — Power BI integration

---

## EXPLOITATION VECTORS (updated)

### Vector 1: `.AspNet.ApplicationCookie` forgery — CRITICAL

**Confirmed:** cookie name = `.AspNet.ApplicationCookie` (ASP.NET Identity default).

ASP.NET Identity OWIN cookie auth in a System.Web host uses **machineKey** for protection:
- `decryption=AES` with `decryptionKey=304DCCF...` → cookie payload decryption
- `validation=HMACSHA256` with `validationKey=632EF2...` → signature verification

**Attack:**
1. Knowing the machineKey → can **forge `.AspNet.ApplicationCookie`** with arbitrary claims
2. Claims include: `UserId`, `UserName`, `Email`, `CompanyId`, `IsAdmin` (determined from ApplicationUser/GenerateUserIdentityAsync)
3. Insert admin claims → send the cookie in a request → **login as admin without a password**

**What's needed to realize:**
- Cookie format (ASP.NET Identity ClaimsIdentity → OWIN cookie format)
- Claims structure (which claims are checked)
- `ApplicationUserManager.CreateIdentityAsync` — claims generation method (extracted in typedef, but IL not decompiled)

**Status:** VECTOR CONFIRMED, need to implement the forge. Tooling: `Microsoft.Owin.Security.Cookies` + machineKey → cookie generation.

### Vector 2: IdentityServer3 signing certificate — `idsrv3test.pfx`

**Found:** `\IdSvr\idsrv3test.pfx` — signing certificate file for IdentityServer3.
**Already obtained:** in `loot/agent_cfg/D_/iRely/CHERRYENERGYUAP1/IdSvr/idsrv3test.pfx` (from L4 exfil).

**Attack:**
1. If the pfx has no password or the password is known → import the certificate
2. Sign an arbitrary OAuth2 token (JWT) with this certificate (RSA-2048, RS256)
3. Send the token as `Bearer` in an API request → **API authentication bypass**

**Status:** pfx already ours. Password `idsrv3test` confirmed. RSA 2048 private key extracted. JWT signed with RS256 (see `jwt_forge.py`, `forged_tokens.json`).

### Vector 3: OAuth2 client credentials

**Found:** `grant_type=authorization_code&client_id={0}&client_secret={1}&redirect_uri={2}&code={3}` — OAuth2 authorization code flow format.

**Attack:**
1. If client_id/client_secret are stored in the DLL or Web.config (hardcoded) → can get an access_token
2. But `client_id`/`client_secret` are most likely in the DB (tblSMCompanyPreference) or IdentityServer config

**Status:** need client_id/client_secret values.

### Vector 4: HubSpot OAuth refresh

**Found:** `crm/api/hubspotintegration/authorizeintegrate?refreshToken={0}` and `https://api.hubapi.com/oauth/v1/token`.

**Attack:** if the refreshToken leaked → get a new access_token for the HubSpot API.

**Status:** refreshToken is stored in the DB (tblSMCompanyPreference?), needs checking.

---

## SUMMARY

| Vector | Secret | Threat | Status | Next step |
|---|---|---|---|---|
| **1** | machineKey → `.AspNet.ApplicationCookie` forge | **RCE-level auth bypass** | **CONFIRMED** | implement forge (Python/C#) |
| **2** | idsrv3test.pfx (IdentityServer signing cert) | **OAuth2 token forgery** | pfx already ours | verify password, sign JWT |
| **3** | OAuth2 client_id/secret | API access | need to find values | — |
| **4** | HubSpot refreshToken | HubSpot API access | in DB? | check tblSMCompanyPreference |

## Cleanup
- `D:\irelyinstall\backup\web.enc` (certutil encoded DLL) — **remained on the server**, needs deletion
- `master.dbo.dll_b64` table — **created**, needs to be dropped
- `iRely.Web.dll` — downloaded locally (515148 bytes, PE header OK)
