Date
July 26, 2026
Author
Karan Patel
,
CEO

Few integration projects keep hospital security teams awake like an Epic or Cerner rollout. The EHR itself is usually hardened by the vendor, but the moment a health system connects a patient portal, a scheduling app, a telehealth platform, or a third-party analytics tool through FHIR and SMART on FHIR, the attack surface multiplies. Every custom integration is a new set of endpoints, tokens, and trust relationships, and each one can expose protected health information (PHI) if it is built or configured incorrectly.

This post walks through how Redfox Cybersecurity approaches EHR penetration testing for Epic and Cerner (now Oracle Health) integrated applications. We will cover the methodology we follow, the FHIR API testing techniques that consistently surface real findings, and two anonymized case studies from recent engagements: an Insecure Direct Object Reference (IDOR) in a patient portal that leaked PHI, and broken authentication in a FHIR API that allowed access to records across patients. No client names, no identifying details, just the technical lessons hospitals and health tech vendors need.

Why EHR Integrations Are a Prime Target

Epic and Cerner are not typically the weak point. The weak point is everything bolted onto them. A mid-sized health system can easily run dozens of integrated applications, many of them built by smaller vendors or internal teams working against tight go-live deadlines. These apps often sit on the public internet, accept patient logins, and pull data from the EHR through FHIR R4 endpoints, HL7 v2 interfaces, or proprietary APIs.

Attackers know this. Healthcare breaches are among the most expensive of any industry, and third-party vendors and business associates are a recurring entry point in healthcare incidents. From an attacker's perspective, a vulnerable patient portal is a far easier path to PHI than breaking into the EHR database directly.

The integration patterns we see most often

  • SMART on FHIR apps launched from within the EHR or as standalone patient-facing apps, using OAuth 2.0 and OpenID Connect for authorization.
  • Custom middleware that proxies FHIR calls between a mobile app or web portal and the EHR, often adding its own session layer.
  • Backend services using the SMART Backend Services (client credentials) flow for bulk data, analytics, or population health.
  • Legacy HL7 v2 feeds running alongside newer FHIR integrations, frequently with weaker transport security.

Each pattern introduces different failure modes. A middleware layer, for example, may correctly receive a scoped token from the EHR but then fail to enforce that scope on its own API, effectively stripping away the protections the EHR vendor built in.

Our EHR Penetration Testing Methodology

Effective EHR penetration testing is not a generic web scan with a healthcare label attached. It combines established frameworks with healthcare-specific knowledge of FHIR resources, SMART scopes, and HIPAA Security Rule requirements. Our methodology is built on four pillars.

1. Scoping and data flow mapping

Before any testing begins, we map how PHI moves between the EHR, the integration layer, and every client application. We identify which FHIR resources are exposed (Patient, Observation, MedicationRequest, DiagnosticReport, DocumentReference, and so on), which OAuth flows are in use, and which identities exist: patients, proxies, clinicians, and service accounts. This mapping drives every later test case, because authorization flaws only become visible when you know which identity should see which record.

2. OWASP-aligned application and API testing

We test patient portals and clinician-facing apps against the OWASP Web Security Testing Guide (WSTG) and the APIs behind them against the OWASP API Security Top 10. In EHR integrations, three categories dominate our findings:

  • API1: Broken Object Level Authorization (BOLA), the API-world name for IDOR, where a user can access another patient's resource by changing an identifier.
  • API2: Broken Authentication, including weak token validation, missing audience checks, and session handling flaws.
  • API5: Broken Function Level Authorization, where patient-level users can reach clinician or administrative functions.

3. FHIR and SMART on FHIR specific testing

Generic tools do not understand FHIR semantics. We manually test search parameters, chained queries, _include and _revinclude behavior, compartment enforcement, and SMART scope handling. We also verify that the app honors launch context, so a token issued for one patient cannot be replayed to query another.

4. HIPAA risk mapping and reporting

Every finding is mapped to the relevant HIPAA Security Rule safeguards, such as access control (164.312(a)), audit controls (164.312(b)), and person or entity authentication (164.312(d)). That gives compliance and risk teams evidence they can use directly in their risk analysis, not just a list of CVSS scores. If your organization needs testing that satisfies both security and compliance stakeholders, our HIPAA penetration testing services are designed around exactly this reporting model.

Case Study 1: IDOR in a Patient Portal Leaking PHI

The first engagement involved a patient-facing portal built by a third-party vendor and integrated with an Epic environment. Patients could log in, view lab results, download visit summaries, and message their care team. The portal used its own session cookie after an initial OAuth login and called an internal REST API that in turn queried the EHR.

How we found it

We created two test patient accounts with distinct records in the non-production environment. While browsing lab results as Patient A, we intercepted traffic in Burp Suite and observed requests similar to GET /api/v1/patients/48213/documents/99871. The patient identifier and document identifier were both numeric and sequential.

We replayed the request with Patient B's document identifier while still authenticated as Patient A. The API returned the full document: a PDF visit summary containing Patient B's name, date of birth, medical record number, diagnoses, medications, and provider notes. Changing only the document ID, and leaving the patient ID unchanged, was enough. The API checked that the caller was logged in and that the patient ID in the path matched the session, but it never checked that the document actually belonged to that patient.

Why it happened

The middleware fetched documents from the EHR using a privileged backend service account rather than the patient's own scoped token. That design choice meant the EHR's built-in patient compartment enforcement was bypassed entirely. The portal assumed that because the URL contained the right patient ID, the request was legitimate. In reality, object-level authorization had to be enforced on the document itself, and nobody had written that check.

Impact

Because document IDs were sequential, an authenticated attacker with a single valid patient account could have enumerated documents for the entire patient population. Using a simple script, we confirmed in the test environment that thousands of documents were reachable within minutes. In production, this would have constituted a reportable breach under the HIPAA Breach Notification Rule.

Remediation we recommended

  • Enforce object-level authorization server-side: verify that every requested resource belongs to the authenticated patient or an authorized proxy.
  • Pass the patient's own SMART on FHIR access token to the EHR where possible, so the EHR's compartment rules apply.
  • Replace sequential identifiers with non-guessable values, as a defense-in-depth measure, not a fix on its own.
  • Add rate limiting and anomaly alerts for high-volume document access from a single session.

IDOR flaws like this are among the most common issues we uncover in healthcare apps, and they rarely appear in automated scan results. If your patient portal was built by a third party and has never been tested with multiple patient identities, it is worth scheduling a healthcare penetration test that focuses specifically on authorization logic.

Case Study 2: Broken Authentication in a FHIR API

The second engagement targeted a FHIR R4 API exposed by a care coordination platform integrated with a Cerner (Oracle Health) environment. The API served a mobile app used by patients and care managers, and it implemented its own authorization server instead of relying solely on the EHR's.

Testing the token lifecycle

We started by analyzing the JSON Web Tokens (JWTs) issued by the platform. Decoding the access token revealed claims for subject, patient context, scopes such as patient/*.read, and an audience value. We then ran a series of token manipulation tests:

  • Changing the alg header to none and removing the signature.
  • Modifying the patient claim to a different patient ID and re-signing with a guessed weak secret.
  • Replaying expired tokens and tokens issued for a different client application.
  • Presenting a token issued for the staging environment against the production-like test API.

What we found

Two issues combined into a critical finding. First, the API accepted tokens whose audience claim pointed to a different client application. Any valid token issued by the shared identity provider, including tokens for a low-privilege companion app, was accepted by the FHIR API. Second, the API trusted the patient claim inside the token for context, but when a request included an explicit patient search parameter, the parameter silently overrode the token context.

In practice, a request such as GET /fhir/Observation?patient=Patient/7731 made with a token scoped to a different patient returned that other patient's vitals, lab values, and care notes. The API validated that a token existed and was signed, but it did not validate who the token was for or which patient it was bound to.

Additional authentication weaknesses

  • Refresh tokens did not rotate and remained valid for 90 days, even after password change.
  • The login endpoint returned different error messages for unknown usernames versus wrong passwords, enabling account enumeration.
  • No rate limiting existed on the token endpoint, making credential stuffing practical.

Remediation we recommended

  • Strictly validate aud, iss, exp, and signature algorithm on every request, and reject unsigned tokens.
  • Bind every FHIR query to the patient context in the token, and reject any request where search parameters conflict with that context.
  • Enforce SMART scopes at the resource and interaction level, not just at the gateway.
  • Implement refresh token rotation and revocation on credential change.
  • Normalize authentication error messages and add rate limiting with lockout thresholds.

How to Test a FHIR API for Security Vulnerabilities

If you are planning EHR penetration testing internally or evaluating a vendor, these are the FHIR-specific test cases we consider non-negotiable.

Compartment and context enforcement

Query every exposed resource type with a token bound to Patient A while referencing Patient B through path parameters, search parameters, and references inside request bodies. Test chained searches such as Observation?subject.name= and reverse includes, which can pull in resources outside the intended compartment.

Scope enforcement

Request a token with narrow scopes, such as patient/Observation.read, and attempt to read MedicationRequest or write to Observation. Many implementations check scopes only for the primary resource and ignore resources returned through _include.

Bulk data and backend services

For the $export operation, verify that client credentials are protected by asymmetric keys, that group-level exports are restricted to authorized groups, and that export file URLs require authentication and expire quickly. We frequently find export files stored in cloud buckets with long-lived pre-signed URLs.

Write operations and input validation

Test create and update interactions for mass assignment, such as setting the subject reference of a new Observation to another patient. Fuzz free-text fields and attachments for stored cross-site scripting that could execute in clinician-facing views of the EHR.

Logging and audit trail verification

Confirm that every PHI access, including failed attempts, is logged with user identity, patient context, and timestamp. HIPAA requires audit controls, and during incident response, missing logs make it impossible to scope a breach accurately.

Common Mistakes in Epic and Cerner Integrated Apps

Across engagements, the same root causes keep appearing. Recognizing them early can save significant remediation effort.

Relying on the EHR vendor for security

Epic and Cerner provide strong controls within their own platforms, but those controls stop at the integration boundary. When a middleware service uses a privileged account to fetch data on behalf of users, every authorization decision becomes the integrator's responsibility.

Trusting the client application

Mobile apps and single-page portals often hide or disable UI elements that a user should not access. Attackers do not use the UI. Every authorization rule must be enforced server-side.

Treating non-production as out of scope

Test and staging environments frequently contain real or lightly masked PHI copied from production. We regularly find these environments exposed with weaker authentication and default credentials.

Testing once at go-live and never again

FHIR integrations evolve quickly as new resources, app versions, and vendor updates roll out. A clean test at launch says little about the state of the integration a year later. Pairing annual assessments with testing after major releases is a practical baseline, and regular HIPAA penetration testing also helps demonstrate ongoing risk management to auditors.

What a Good EHR Penetration Testing Report Should Include

Hospitals and health tech vendors should expect more than a scanner export. A useful report includes:

  • A clear data flow diagram showing where PHI is exposed and how each finding fits into that flow.
  • Reproducible proof of concept for every finding, including the exact requests and identities used.
  • Severity ratings that reflect PHI exposure, not just generic CVSS.
  • Mapping to HIPAA Security Rule safeguards and OWASP categories.
  • Specific, developer-ready remediation guidance and a retest to validate fixes.

Key Takeaways

EHR penetration testing is fundamentally about authorization. The two critical findings described here, an IDOR that exposed patient documents and a FHIR API that trusted any signed token, both came from the same mistake: assuming that because a user is authenticated, they are allowed to see the data they request. Neither issue would have been found by an automated scanner, and both would have resulted in reportable breaches if exploited in production.

  • Integrations around Epic and Cerner, not the EHRs themselves, are where most PHI exposure happens.
  • Object-level authorization and token validation must be enforced server-side on every request.
  • FHIR APIs need FHIR-aware testing: compartments, scopes, includes, bulk export, and write operations.
  • Map findings to HIPAA safeguards so security and compliance teams can act on the same report.
  • Retest after every significant integration change, not just at go-live.

If your organization is launching or maintaining Epic or Cerner-integrated apps, now is the time to test your EHR integration. Redfox Cybersecurity's team performs manual, FHIR-aware assessments built on OWASP and mapped to HIPAA requirements. Explore our healthcare penetration testing engagements or talk to us about HIPAA penetration testing to find the flaws in your patient portals and FHIR APIs before an attacker does.

Copy Code