How-to archive · Incident

Flashback (not functional)

A reconstruction of the foothold on the old Joomla site. The panels below are props. They do not submit, they do not call PHP, they do not talk to a backdoor.

  1. 1. Scan, don’t read the how-tos

    The interesting part to an automated scanner was never “How do I open XFDL on a Mac.” It was: is this Joomla, is it old, can I write a file under the web root. Once that answer is yes, the articles are just camouflage.

  2. 2. Hide in filenames the CMS already had

    The drops used boring names: help.php, option.php, file.php, footer.php, plus a “cache” file under contacts. A directory listing looks like Joomla. A human grepping for c99 or shell misses them.

  3. 3. Leave a door that does not need a login

    The tiny contacts “cache” file was the simple door. In words: if an HTTP POST arrived with a few fields filled in, PHP would treat one field as a function name and the others as arguments, then call it. No cookie, no admin user, no Joomla session. That is why a scanner loves it — one request, the language does the rest.

    The four larger files were the same idea with extra camouflage: a scrambled alphabet, lookups into $GLOBALS, so the source did not say eval in plaintext. Same job: run attacker-chosen PHP on this host.

  4. 4. What that door is for

    Once “call any function” works, the rest is ordinary PHP, not a special Joomla feature:

    • read or write files under the site
    • keep a second copy of the door if the first one is deleted
    • inject junk into templates (spam, fake “virus scan” pages, ads)
    • send mail from the server’s address
    • use the box as a hop so the next scan is not from the attacker’s IP

    The how-to HTML in the MySQL dump was not rewritten with iframes or miners. The live risk was the PHP the scanner could POST to.

  5. 5. The other scanner wins

    A host malware scanner later hashed those files, renamed them *.suspected, and the PHP site was taken down. That is the right ending for this story: do not keep serving a CMS that will execute a posted function name.

This Django archive does not run those files. It renders sanitized HTML from the dump. There is no POST-to-function endpoint here. Incident notes · Articles