Offensive Security and Application Security Perspectives

Vulnerability Research

XML External Entity Injection (XXE) in OpenCats Applicant Tracking System

Vendor’s Vulnerability Announcement


Internet Facing OpenCats: Google Dork

OpenCats is an open-sourced applicant tracking system that is used to track job applicants. Versions before 0.9.4-3 suffer from a XML External Entity Injection vulnerability that allows unauthenticated job applicants to read arbitrary files after uploading a resume with a docx or odt file extension.

Vulnerability Walk through

Opencats has a Careers Portal page that lists jobs for applicants to view and apply for any available jobs.

Careers Portal

For this demonstration, I have created a position titled “Pen Tester”. After clicking on the position, I have the option to import a resume which will convert a resume to text. The text will make the contents of a resume searchable by the recruiter or hiring manager after applying for a position.

The “Import a Resume” feature

This feature can be exploited with a .docx or .odt file. I will use a .docx file for this blog post. Create a docx file with your favorite document editor, Google Docs, or use Python.

Google Docs: This is a very short resume with only my name in it. Go to “File > Download as > Microsoft Word (.docx)”.

Also, you can create a docx file with this simple python script. I know this is basic stuff, but I’m just providing a few different options.

This python script will create a properly formatted docx file.
After running the script, resume.docx was created.

At this point, our docx file is not malicious and if it were to be uploaded, it would just show my name since that is the only text in my very simple resume (if you can even call it that).

After uploading resume.docx, it shows my name as the only text that was found.

A Docx file is mostly just zipped up xml files. We need to unzip the resume.docx file and modify the contents in “word/document.xml”. Then, save our changes back to resume.docx.

The file is unzipped and the “word/document.xml” that needs to be modified is highlighted.

Two modifications are needed in document.xml. For the first modification, add this line under line one to read /etc/passwd:

<!DOCTYPE test [<!ENTITY test SYSTEM 'file:///etc/passwd'>]>
Adding the XXE payload to read /etc/passwd.

For the second modification, we need to find and change my name which was the only content that was in the resume. We will swap out my name with this:

My name was found on line three within some XML tags.
This is how the line looks after swapping out my name.

That’s it! The modifications to document.xml need to be saved to the resume.docx file now.

Saving changes to document.xml within the docx file.

Once the malicious .docx file is uploaded then the contents of /etc/passwd can be read.

Reading /etc/passwd on the operating system.

At this point, you can pillage the file system to find plaintext passwords and other interesting information that you could reuse elsewhere. To read the Opencats config.php file to recover plaintext passwords, you will need to base64 encode the contents.

Base64 encoding config.php that contains the database and other credentials. This change is saved to resume.docx.
The base64 encoded contents of config.php are returned.
After decoding the base64 in Burp Suite, the config.php that contains various plain-text credentials can be viewed.


  • June 28, 2019 – Disclosed to OpenCats
  • June 28, 2019 – OpenCats acknowledged the issue.
  • July 1, 2019 – OpenCats released a fixed version (0.9.4-3).
  • July 5, 2019 – MITRE assigned a CVE.
  • July 7, 2019 – Published.