PatchDay Alert
Analysis · 4 min read · 719 words By analysis-desk

Drupalgeddon: when a data structure is allowed to name a function to call

Drupal's Form API lets a renderable array carry a callback, that's a feature. Drupalgeddon (CVE-2018-7602) let an attacker put their own callback in, and Drupal called it: exec, passthru, system. Powerful framework metaprogramming plus untrusted input equals RCE.

Drupalgeddon: when a data structure is allowed to name a function to call

Drupal’s render system is genuinely powerful: pages are built from “renderable arrays,” nested data structures that describe what to render, and those structures can include directives like #pre_render or #post_render that name a function for Drupal to call. That’s a feature, the framework’s expressiveness. Drupalgeddon (CVE-2018-7602, alongside the closely-related CVE-2018-7600) is what happened when attacker input reached those structures: an attacker could inject a render array that named a PHP function like exec, passthru, or system with attacker-controlled arguments, and Drupal would dutifully call it. A data structure that’s allowed to specify a function to invoke is, in the presence of untrusted input, a remote-code-execution primitive.

What the bug is

The flaw lives in Drupal’s Form API and render pipeline (Drupal 7 and 8). Through certain request paths, notably AJAX form requests, an attacker could smuggle a malicious renderable array into processing, and the render system would resolve the embedded callback into actual code execution on the server. Drupal patched it in versions 7.59, 8.4.8, and 8.5.3 in April 2018. CISA lists it with the ransomware flag. The exploitation that followed was a textbook mass-scanning event: Imperva observed that the large majority of Drupalgeddon2 traffic was scanning, with a slice dropping backdoors and cryptocurrency miners like XMRig. Because Drupal powers a meaningful share of the web, the vulnerable population was large, and unpatched Drupal sites kept getting hit for years afterward.

The lesson: expressive frameworks and the callback-in-data pattern

The deeper issue isn’t unique to Drupal. Many powerful frameworks let data structures carry behavior, callbacks, lazy-evaluation directives, magic keys that trigger code, because it makes the framework flexible and concise for developers. That same expressiveness is a liability the instant untrusted input can reach those structures, because “data that can name a function to call” plus “attacker controls the data” equals “attacker names the function.” It’s the same family of problem as server-side template injection and unsafe deserialization: the framework was designed to do something powerful with the data it’s given, and the boundary between data and code is thinner than it looks.

The defensive principle for builders: keep a hard boundary between untrusted input and any structure that can carry executable directives. User input should be values inside a structure you control, never the structure itself or its control keys. Audit the paths where request data flows into render arrays, deserialization, or template contexts, and treat any place where input can influence a callback, a class name, or a control directive as critical.

What to do

  • Patch Drupal, and keep it patched. Get to a fixed core version (well past 7.59 / 8.5.3); current Drupal is fine, the risk is the unmaintained sites. Drupal core security updates are exactly the kind that need to be applied quickly, because Drupalgeddon proved how fast and broad the exploitation gets.
  • Retire or isolate abandoned Drupal sites. A huge part of the long Drupalgeddon tail is forgotten Drupal installs, marketing microsites, old project pages, that nobody patches. Inventory your Drupal footprint and decommission what you don’t maintain.
  • Assume compromise on long-exposed, unpatched sites. Hunt for web shells, the PHP process spawning shells or miners, XMRig and similar, and unexpected outbound connections. A Drupal site unpatched since 2018 should be treated as breached until proven otherwise.
  • For developers on any expressive framework: audit input-to-callback paths. Render arrays, deserialization, template contexts, and dynamic dispatch are all places where untrusted input must never reach a control directive.

The reframe is to be suspicious of framework features that blur data and behavior. Drupal’s renderable arrays are elegant, and elegance that lets a data structure name a function becomes remote code execution the moment an attacker can shape that structure. Patch Drupal on its security clock, retire the sites you’ve forgotten, and in your own code keep untrusted input firmly on the data side of the line. We flag the framework-injection entries, render arrays, templates, deserialization, as a family, because they all spring from the same place: a powerful feature meeting input it was never meant to evaluate.

Sources

Share

Related field notes

One email, every weekday morning.

You're in. Check your inbox.

Get the digest

Free. Weekday mornings. Plain English CVE triage.

Check your inbox to confirm.