true_web_assembly
From XSS to RCE in AsmBB v2.9.1
Update (May 2023)
This vulnerability was assigned a CVE!
CVE-2023-30334 AsmBB v2.9.1 was discovered to contain multiple cross-site scripting (XSS) vulnerabilities via the MiniMag.asm and bbcode.asm libraries.
Description
https://board.asm32.info/asmbb-v2-9-has-been-released.328/
From the post:
“AsmBB is very secure web application, because of the internal design and the reduced dependencies. But it also supports encrypted databases, for even higher security.”
“Download, install and hack”
Yes
Solution
The challenge is to attack the latest version of AsmBB, a web-based message board implemented entirely in x86 assembly. The provided Dockerfile builds the asmbb engine using the source files from the asmbb and freshlib repositories.
# Get source files for asmbb
RUN wget https://asm32.info/fossil/asmbb/tarball/4c91cddaec/asmbb-4c91cddaec.tar.gz -O asmbb.tar.gz && \
/bin/bash -c "echo 'b1e621d1ae988b35e836ec9142ccc6ce6cf7c24a090c4d973894770a62fa4ddc asmbb.tar.gz' | sha256sum --check" && \
tar -xf asmbb.tar.gz || true && \
mv asmbb-* asmbb
# Get source files for freshlib
# AsmBB uses functions from freshlib
RUN wget https://fresh.flatassembler.net/fossil/repo/fresh/tarball/6636a57441/Fresh+IDE-6636a57441.tar.gz -O fresh.tar.gz && \
/bin/bash -c "echo '5ba395b0e957536bd66abc572414085aab5f2a527d28214881bbba72ec53e00d fresh.tar.gz' | sha256sum --check" && \
tar -xf fresh.tar.gz && \
mv Fresh* Fresh
# Build the asmbb engine
RUN lib=/Fresh/freshlib TargetOS=Linux /fasm/fasm -m 200000 /asmbb/source/engine.asm /engineGaining XSS
The forum is the main feature of AsmBB, and the default build uses a custom markdown-like parser called MiniMag. Our goal is to achieve a GET-based XSS on the admin user, and subsequently abuse admin features for RCE.

Let's take a look at the AsmBB source. render2.asm contains a "hash table" of commands used by the templating engine, mapped to their routines.
We can see this in action in post_view.tpl where the post is rendered. Depending on format, the post content is either parsed with minimag or bbcode, and the final output is rendered as HTML.
Although the client-side UI only allows us to write content in the MiniMag format, the POST request to submit the post does include a format parameter.
When set to 1, the format parameter allows us to use the BBCode parser instead. This uses the bbcode command, which calls the .cmd_bbcode routine.
Since the BBCode parser was a newer parser introduced after MiniMag, and isn't enabled by default, we thought this would be the best place to start looking for parser vulnerabilities.
The TranslateBBCode routine from bbcode.asm (found in FreshLib) is then used to parse the BBCode content. Here we see a table of supported BBCode tags.
BBCode is an old markup language that has a rather simple syntax. Tags are enclosed by square brackets, and some tags can have attributes, such as the following URL tag:
The main loop of the parser is found at .loop. For each character, the logic goes:
if the end of the text has been reached, exit the loop
if it is a newline or space character, skip it
if it is
[, process the tag at.start_tagif it is the start of an emoji, process the emoji
Otherwise, we go to .continue, where the character is HTML encoded.
Notice that unless the current character is part of an emoji or part of an opening/closing tag, we will reach the HTML-encoding logic. This is done through a simple text substitution that sanitizes angle brackets, quotes, and ampersands.
Since everything outside the opening/closing tag are HTML-encoded, let's take a closer look at the tag-processing logic. When a tag is matched, a string substitution is performed based on the table below.
The 2nd, 3rd, and 4th columns correspond to the start of the tag, end of the attribute, and end of the tag respectively. For instance, the following markup
becomes
The attribute value and the content in between the opening/closing tags are processed separately from the tag itself, and are thus subject to HTML-encoding. If there's any parsing bug to be found, it would probably have to be while parsing the tag.
What if we just don't close the tag?
Since the tag isn't being encoded while it is processed, there might be an edge case where the unencoded content is reflected in the absence of a closing ].
Voilà, the following markup
translates to
which when rendered on a browser, pops an alert!

Honourable Mentions
We also found two POST-based XSS vectors, which unfortunately were unusable in this challenge in the absence of an open redirect (since the admin bot is only able to visit the challenge page, and no other page).
The first was a POST request to !post. This would have reflected the XSS payload in the page <title>.

The second is a HTTP response splitting attack. The !skincookie endpoint reflects form data in the Set-Cookie header, and allows for for CRLF injection. In addition to XSS, this can be used to set arbitrary cookies and response headers.

Gaining RCE
Armed with admin privileges, one would see a suspiciously named setting in /!settings.

A setting called "Pipe the emails through" sure sounds promising for RCE. Looking for the form key smtp_exec shows us that this option is being used in commands.asm when sending a user activation email.
Looks like our smtp_exec option is being passed to Exec2. A quick look at process.asm reveals that this spawns a child process with our input. Great!
All we have to do now is to change this option to a payload that sends us the flag.
Putting It All Together
Here's the final exploit that we will serve to the admin. Here, I used a first-stage payload to keep the exploit small, but serving the whole exploit in one payload would work as well.
is converted to base64 and eval-ed:
which then executes the RCE payload:
Once the admin visits our exploit page, just register a new user and the flag will be sent to us!
Last updated
Was this helpful?