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.
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.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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.
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.
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.
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:
alg header to none and removing the signature.patient claim to a different patient ID and re-signing with a guessed weak secret.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.
aud, iss, exp, and signature algorithm on every request, and reject unsigned tokens.If you are planning EHR penetration testing internally or evaluating a vendor, these are the FHIR-specific test cases we consider non-negotiable.
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.
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.
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.
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.
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.
Across engagements, the same root causes keep appearing. Recognizing them early can save significant remediation effort.
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.
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.
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.
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.
Hospitals and health tech vendors should expect more than a scanner export. A useful report includes:
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.
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.