The bank's code calls POST /AcceptTransaction with an empty JSON body {}
and no CSRF token. The only authentication is the ASP.NET_SessionId cookie,
which the browser sends automatically on every request to the bank's domain.
An attacker hosts a page that auto-submits to /AcceptTransaction.
If the victim has an active bank session, the browser sends the
ASP.NET_SessionId cookie automatically. The server processes the
pending transfer without any OTP validation.
/AcceptTransaction — browser sends cookies automatically.
The attacker can also call the transfer endpoint directly with stolen session data. This is the Python script approach shown in the Full Kill Chain tab.
Evidence from the bank's code: OnSuccessDuplicada() receives the full transfer response
— CuentaDebitar, Monto, Beneficiario, CedulaBeneficiario,
BancoBeneficiario, Resultado — all returned from the server without OTP.
The bank loads 4 external scripts from 3 different subdomains, all from the same
/55151/ directory. These scripts load asynchronously with no SRI integrity hash.
Any compromise of these subdomains grants the attacker same-origin JavaScript execution
on the bank's application — full access to sessionStorage, document.cookie,
and all JavaScript variables.
| Script | Source | Loaded On | SRI Hash? | Status |
|---|---|---|---|---|
cc.js |
edit.banesco.com/55151/cc.js |
Every post-login page | ❌ NO | CHECKING... |
scrl.js |
cache.banesco.com/55151/scrl.js |
Login page | ❌ NO | CHECKING... |
clip.js |
servicio.banesco.com/55151/clip.js |
Login page | ❌ NO | CHECKING... |
port.js |
edit.banesco.com/55151/port.js |
Login page | ❌ NO | CHECKING... |
The bank's login page stores JavaScript code in hidden input values
and then sets them directly as onClick handlers via setAttribute().
This is equivalent to eval() on click.
lnkSitioSeguro, lnkSitioSeguro2, lnkCandado),
the attacker can execute arbitrary JavaScript in the victim's session.
The example below replicates the bank's exact pattern. Click the link to see how hidden input values become executable code:
Click here — see what the hidden input executes
The bank's OnSuccessDuplicada() opens Error.aspx with
the Error parameter derived from server data. If the error page
renders this parameter without encoding, it's reflected XSS.
The bank uses openSwalModal(htmlToShow) and ModalNotificacionTD(msj)
with the html: parameter — which renders raw HTML.
If any caller passes user-controllable data into these functions, it's HTML injection.
| Vector | Injection Point | Type | Severity |
|---|---|---|---|
setAttribute("onClick", ...) |
Hidden input values in login.aspx | DOM-based / Stored if values come from DB | HIGH |
Error.aspx?Error= |
Query parameter from server data | Reflected / Stored if MotivoSuspension from DB | HIGH |
SweetAlert html: |
Any caller of openSwalModal/ModalNotificacionTD | DOM-based | MEDIUM |
| URL params in OnSuccessDuplicada | Beneficiario, Concepto, CedulaBeneficiario | Reflected (if confirmation page echoes them) | MEDIUM |
The bank's RenovarSesionMP() reads the refresh URL from
sessionStorage.getItem("ConvergenciaMPrefreshUrl"). If an attacker
can set this value (via XSS or another injection), the auto-renewal loop
sends the session cookies to the attacker's server every 2.5 minutes.
The ejecutarServicio() function uses the global JavaScript variable
urlRenovarCookie. If this variable is ever set dynamically (e.g.,
from a URL parameter or server response), an attacker can redirect the
fetch() call to their server.
| # | Vulnerability | Enables | Severity |
|---|---|---|---|
| 1 | Third-party scripts without SRI 4 scripts from 3 subdomains, all async, no integrity hash |
Same-origin code execution | CRITICAL |
| 2 | sessionStorage plaintext tokens session_token, User_SESSION, ConvergenciaMPrefreshUrl all in plaintext |
Token theft via any JS on origin | CRITICAL |
| 3 | No httpOnly on ASP.NET_SessionId document.cookie readable by JavaScript |
Session cookie theft | CRITICAL |
| 4 | OTP only at UI layer ValidateSession, ejecutarServicio, AcceptTransaction never check OTP |
Transfer execution without OTP | CRITICAL |
| 5 | CSRF on /AcceptTransaction No CSRF token, empty JSON body accepted |
Cross-origin transfer confirmation | HIGH |
| 6 | XSS via setAttribute("onClick") Hidden inputs contain executable JavaScript |
Session hijacking | HIGH |
| 7 | Auto-renewal loop (2.5 min) RenovarSesionMP() fires automatically, exfiltrates token |
Persistent session hijacking | HIGH |
edit.banesco.com/55151/cc.js (or one of the other 3 scripts)
was compromised at the CDN level. The attacker injected a single line that exfiltrates
sessionStorage and cookies to a C2 server. Every user who loaded the bank's page
after login had their session stolen./AcceptTransaction. If the victim had an active
bank session, the transfer was confirmed without their knowledge.Each fix addresses a specific vulnerability in the kill chain.
| # | Vulnerability | Fix | Effort |
|---|---|---|---|
| 1 | Third-party scripts without SRI | Add integrity="sha384-..." crossorigin="anonymous" to all external script tags. If the CDN is compromised, the browser will refuse to load the modified script. |
LOW |
| 2 | sessionStorage plaintext tokens | Use httpOnly cookies for session tokens. Never store authentication tokens in sessionStorage. Use SameSite=Strict to prevent CSRF. |
MEDIUM |
| 3 | No httpOnly on ASP.NET_SessionId | Set httpOnly=true and Secure=true and SameSite=Strict on the session cookie in web.config. |
LOW |
| 4 | OTP only at UI layer | Validate Clave Dinámica server-side in ejecutarServicio(), AcceptTransaction, and all state-changing API endpoints. The OTP must be per-transaction, not per-session. |
HIGH |
| 5 | CSRF on /AcceptTransaction | Add anti-CSRF tokens to all POST requests. Validate Origin and Referer headers. Require Content-Type: application/json with CSRF token in custom header. |
MEDIUM |
| 6 | XSS via setAttribute("onClick") | Never store executable code in hidden inputs. Use event listeners (addEventListener) instead. Apply CSP: script-src 'self'. |
LOW |
| 7 | Auto-renewal loop exposes tokens | Use refresh tokens stored in httpOnly cookies, not in sessionStorage. Rotate tokens on each use. Bind tokens to IP/device fingerprint. | MEDIUM |