Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

Remote Code Execution with XMPP Stanza Smuggling in Zoom- 851

ifratric - Project Zero (P0) Posted 3 Years Ago
  • XMPP is a messaging protocol based on XML. This is based upon short snippets of XML called stanzas. These messages are sent over the same stream connection as control messages to the server. XMPP allows the client to have full control of data within the <body> tag, including their false XML snippets.
  • If a user could escape this XML, to get into the control section of the message, they could add arbitrary stanzas into the data. The author dubbed this attack XMPP Stanza Smuggling. Since there are two points of parsing: server and client, the difference between these could cause problems. This is where the author searched for vulnerabilities at.
  • Between the server-side (Expat) and client-side (Gloox), there are two XML parsers: gloox and fast_xml (Expat). Both of these support UTF-8 but handle it differently. Expat is fully UTF-8 aware and handles errors appropriately. Gloox has only a minor effort to detect invalid characters, since it does the parsing character by character.
  • One the server-side, it will send aa\xeb><aa;. The \xeb designates a unicode character is being used, since this denotes the 3-byte prefix for UTF-8. Once Expat receives this, it does not check that the next two characters in the sequence at valid - it adds them to the XML tag as is by creating <aa\xeb><aa/> from our input.
  • Once Gloox receives the data, it will NOT see 0eB as the start of the 3-byte sequence. Instead, it is just another character in the tag name. It will read the data as two tags: <aa\xeb> and <aa/>. Neat! We have smuggled in a closing tag to the client.
  • As a result, the author believes it is possible to escape the <message> tag. To exploit this, they used a quirk within Gloox: smuggle in the tag <?xml ?> in order to completely reset the state of the parser, making our node the new root node. This is only possible because of the UTF-8 encoding bug talked about before. As, otherwise, it would remove the <?xml ?> data.
  • With the smuggling bug in the XML stanzas, how do we actually exploit this? Of course, we can know spoof users and control things that we normally cannot control. However, we can do better! Using the <stream:error> tag, we can specify all of the servers that the device be using, since we can control the endpoint this goes to. This effectively man in the middles the entire connection!
  • With the man in the middle position, we can exploit the update process to get code execution. This was done by first downgrading the Zoom client to an older version (that is still signed) then exploiting an unverified .cab file, which contains installation data. The replaced .cab file will NOT call Zoom as it should. Instead, it can call an arbitrary file, such as cmd.exe.
  • After posting this, the author found an additional smuggling bug unrelated to the previous finding. When the server uses Expat, it creates a parser with a newline as the delimiter between the namespace URI and the local part of the name. Since we can add arbitrary data into this (including newlines), we can confuse the two modes.
  • Since the parser believes we have added a delimiter (when we really haven't), we can smuggle in arbitrary XML tags. This leads to the same XML stanza smuggling bug as before. This was simply done by adding a newline!
  • Overall, I love this report because of the parsing differences between two XML parsers. Even without memory corruption, Zoom can still be compromised. I also enjoyed the downgrade attack, proving that cryptographic signatures are not enough (no wonder Apple limits versions on iOS).