Show Notes

217 - Insecure Firewalls, MyBB, and Winning with WinRAR

A fairly simple processing bug in WinRAR resulting in code execution with benign seeming interaction with an archive; unfortunately this one was seen being exploited in the wild to spread malware.

The normal flow when double clicking on a file inside of an archive inside of WinRAR is that the selected file will be extracted into a temporary directory and then it will be executed using a call to ShellExecuteExW which will look at the filename and open it using the default handler.

There is a potential issue is that when you double-click on a file, WinRAR may end up not only extracting the selected file but any file that starts with the same text. Seems like a weird behavior to me, but it also feels fairly intentional that it exists so I’m not sure this aspect is strictly speaking a bug. The end result though is that if you have a file named xyz.jpg and a directory names xyz.jpg/ if you double-click on xyz.jpg then that file will be extracted along with all the files under the directory. Though the actual xyz.jpg/ is not created, just the files extracted.

The primary issue is in this extraction process where the function that actually creates the output file will try to fix up the filename a bit, if the filename inside of the archive ends with a ` ` or some other characters, the dangling characters will be trimmed from the output filename. On its own this isn’t too bad, but the rest of the system isn’t informed that the filename changed, so later when ShellExecuteExW is called, it is called with the filename that has not been trimmed. If there is another file in the same directory that does start with that non-trimmed filename, it will be executed instead.

So the attack relies on a archive structure similar to the follow:

  • example.png
  • example.png /example.png .cmd

In this case, double-clicking on example.png will result in two files being extracted into the temporary folder. example.png (the trailing space will be trimmed) and example.png .cmd. Then when ShellExecuteExW is set to execute the example.png file it will match the .cmd file instead of the .png resulting in whatever code inside of the .cmd file being executed.

While the bug does take user-interaction limiting its impact severely the fact that the actual user interaction is seemingly benign and is a fairly common action makes this seem like a reasonably likely scenario. Adding to that this sort of last-minute filename sanitizing/changing is a bug that can creep up in many places and is a bit of a code-smell to keep an eye out for. It won’t always lead to code execution but file-confusions are an interesting primitive to have in any environment.

Awesome abuse of an Regex DoS to bypass a security check in MyBB resulting in an RCE.

Take a look at the following code from MyBB’s check_template function:

<?php 
// ...
if(preg_match("~\\{\\$.+?\\}~s", preg_replace('~\\{\\$+[a-zA-Z_][a-zA-Z_0-9]*((?:-\\>|\\:\\:)\\$*[a-zA-Z_][a-zA-Z_0-9]*|\\[\s*\\$*([\'"]?)[a-zA-Z_ 0-9 ]+\\2\\]\s*)*\\}~', '', $template)))
{
  return true;
}

In this case its basically just trying to take the original template, and then remove all the normal looking variable expansions inside of it like {$xyz} will be removed by the preg_replace but anything more complex than a variable access will not be removed. Then the preg_match looks if there are any remaining expansions, if they are they are unsafe.

Logically the check should work, but the preg_* functions will return error values rather than raising an exception, these errors should always be checked though. By abusing the backtracking present in the regex. Once the backtracking limit is reached, preg_replace will simply return null. So the preg_match will be matching against nothing, which natually passes as it finds no matches.

Allowing for a template containing the backtracking and a problematic state to bypass the security check.


Because we haven’t covered ReDoS in a podcast summary before I want to touch on how you can determine if a regex is vulnerable:

The general rule for determining if a regex is vulnerable to backtracking issues is to see if the regex meets the following conditions:

  1. Repetition operators are applied to a sub-expression: (abc)+ or (x)*
  2. The sub-expression can match the same input value multiple times: (a|a)+ or (a+)*
  3. There must be a match case following the sub-expression that isn’t matched by the sub-expression: (a+)*b

The problematic sub-expression in this case is towards the end: ((?:-\>|\:\:)\$*[a-zA-Z_][a-zA-Z_0-9]*|\[\s*\$*([\'"]?)[a-zA-Z_ 0-9 ]+\2\]\s*)specifically the second case after the | (or) operator: \[\s*\$*([\'"]?)[a-zA-Z_ 0-9 ]+\2\]\s* Looking at the three conditions:

  1. It ends with a * which is a repetition operation
  2. The subexpression can match the same input for example: [0][0][0] the same expression would match [0] or [0][0] from that input
  3. The last part of the regex is to match a }

So by repeating that array access you can get the regex engine into an exponential backtracking situation. Atleast that’s how I understand this regex, no one likes reading this stuff. Most of the time I’ll toss things into a ReDos detector like: https://devina.io/redos-checker though there are plenty of other options too that provide other features.