if __name__ == '__main__': app.run(debug=False, host='0.0.0.0', port=5557)
As you can see above, this application recieve SVG from user and validate it using lxml library. It only returns only either a boolean result from SVG validation, or error message within the process. We need to verify a few things to know what technique will be used. If we check the lxml version used in the app, it uses lxml==4.9.3, Then if we look into the lxml version in this documentation, the resolve_entities argument by default sets to false only starting from vesion 5.0.0.
LP#1742885: lxml no longer expands external entities (XXE) by default to prevent the security risk of loading arbitrary files and URLs. If this feature is needed, it can be enabled in a backwards compatible way by using a parser with the option resolve_entities=True. The new default is resolve_entities=’internal’.
Indeed we can utilize an External XML Entity Injection attack. But we can’t directly read the output file since it only returns either boolean or error message. Next if we see the is_valid_svg function:
1 2 3 4
defis_valid_svg(file_path): tree = etree.parse(file_path) root = tree.getroot() return root.tag.endswith('svg')
the no_network is not set, default value is true, which means we can’t use OOB technique to import external dtd, limitting our options to error based attack using internal dtd, but how can we do that?
Normally, if our SVG file didn’t have any error, the is_valid_svg will returns boolean output and then the app will remove the file. Otherwise, if there’s an error within the process, the app will only return error message, but not removed the SVG. We can utilize this SVG as internal dtd payload that read the flag and trigger error which contains the flag content.
Solution
Create first payload, that contains the arbitrary file read and triggering error:
1 2
<!ENTITY % fileSYSTEM"file:///app/flag.txt"> <!ENTITY % huh"<!ENTITY content SYSTEM '%gg;/%file;'>">
this XML contain file, and huh entity. The file entity will import the /app/flag.txt content, and huh entity will containt the content of %gg;/%file. Entity %gg; is not existing, this non-exists entity will trigger an error. 2. Submit the first payload:
Create second payload that will import internal dtd:
this XML will import internal dtd fb756b72d004f9b74a0cd26e260bf6b1805d4947f1d9b7880af33aa040723cd0.svg
the fb756b72d004f9b74a0cd26e260bf6b1805d4947f1d9b7880af33aa040723cd0.svg hash is the name of the first payload that generated within the validation process
then import the huh entity which will triggers the error mentioned above.