In a not very recent engagement, we were tasked to perform a penetration test of a secure environment. The environment consisted of an application that was published through Remote Desktop services. To be more precise it was accessed by users, through Remote Desktop Web Access which allows organizations to make Remote Apps accessible from the browser.
The scope of the engagement was for our team to login to the Remote Desktop Server (RDS) via Remote Web Access, launch the published Remote App and attempt to break out of the app and gain access to the RDS server’s operating system, or at least prove that it was possible. We had one constraint. We did not have any credentials to authenticate with the app and hence, we could only access its login screen. More like an internet kiosk escape. That could be fun we thought…. but little we knew of what was coming for us.
We logged in to the Remote Web Access portal and were greeted by a few published applications. We opened the main app and looked around the login screen to find ways/links/buttons that could help us execute additional functions and break out of the app, but there was nothing there. We opened the second app but we were also unlucky with that one. The third app was a web application that was opened through Internet Explorer (IE). This looked like a possible candidate that could assist us in our break out.
However, the browser window was missing all its toolbars, menus and buttons. Only the address bar was there. We tried right-clicking everywhere on the browser window but nothing useful was listed in the presented menus. We tried several shortcut keys like Ctrl + O to access the Open File window, the Sticky Keys trick and any other escape that we could think of. We consulted several guides available online and tried almost every trick in the book, but nothing worked. Until we followed all the links available on the web app’s login page and found one that was pointing to a non-existing website. As a result, we were greeted with the usual IE error that appears when there is a problem with the network connection to a website and the familiar button below the text that offers to “Diagnose Connection Problems”.
We clicked the button and a new window popped up showing information about the problem but nothing really useful for our case.
Until we noticed the little printer icon on the top right corner. We clicked the icon and we were presented with a small window asking us to choose one of the available printers in the list.
We explored the available menus, buttons and tabs and clicked the “Find Printer” button, which led us to another window.
The new window allowed the user to search the Active Directory domain for a printer. Ignoring the fact that we retrieved useful information from the Active Directory, we explored the main menu and selected “Save Search”.
Another window appeared, just like Windows Explorer, that had a left-hand pane with the usual Windows Explorer items in it (e.g. Quick Access list, This PC, Desktop, Downloads, etc.). However, no file system icons (e.g. C:, D:, etc.) were present in the list. Attempting to access C:\ by entering it in the address bar, generated an error saying it was not accessible. Accessing anything besides Desktop, Downloads, Documents, Picture and Videos generated the same error message. We managed however, to access %temp% and %appdata% when we realized that our user’s profile was a roaming one and it was actually located/stored on a different server.
We then decided to try another trick and entered a random string of characters in the search box located on the top right corner of the window.
This caused three icons to appear in the main pane of our window. Clicking the “Libraries” and “Computer” icons led nowhere, but the “Custom” icon opened the “Choose Search Location” window.
Unfortunately, no new locations were listed and off course, just like before, the useful ones (e.g. Computer) were not working.
When we added “C:” to the list of locations, the C drive file system tree appeared.
We could navigate the folder structure but we couldn’t see the files in them, nor their content. Our position improved a little bit but effectively we were still in the same lousy position we were before.
However, we noticed that in the list of locations there was one with our user profile name. Selecting it, made it appear in the “Summary of selected locations” box.
Right-clicking it and selecting the option “Open folder location” caused a Windows Explorer window to pop up.
That seemed like a major improvement for our position but quickly proved to be useless since nothing major happened.
The only change was the sudden appearance of a couple of shortcut icons in our Desktop folder that weren’t visible before. One of them was Mozilla’s Firefox browser, which we will discuss later in the post.
Disappointed but not ready to give up, we navigated through our profile directories and attempted to open any available files. To our surprise, we were presented with a message saying that the application was blocked by the administrator. This was a clear indication that the administrator had setup Application Whitelisting and/or Blacklisting. Our position had worsened dramatically.
Continuing our attempt to gain command execution, we found out that right-clicking or Shift + right-clicking the white background of our Desktop folder’s pane did not provide any useful options since the great majority of them were either missing from the menu or were greyed-out. We did however, have the “New” section available. This meant that we could create a new “Folder”, “Shortcut”, and a bunch of file types, such as “Bitmap image”, “Contact”, “Rich Text Format”, “Text Document” and “Compressed (zipped) Folder”.
We created new files of all these types and attempted to open them by double-clicking them but we were greeted with the blocked application message again. The administrators didn’t even allow us to open Notepad or WordPad.
They did though, allow us to create new shortcut files. By entering something like C:\Windows\System32\cmd.exe in the shortcut’s path, we could presumably open the Command Prompt window. Off course, as we expected, the cmd.exe application was blocked. Therefore, we tried numerous other application whitelisting bypass techniques using executables from the LOLBAS list (https://github.com/LOLBAS-Project/LOLBAS), but all of them were blocked. The only one we found working was rundll32.exe. We discovered this when we tried to use the Control_RunDLL exported function of shell32.dll to run the Control Panel file desk.cpl (Settings window).
This was a good thing for us because if the administrators missed restricting DLL files from being loaded from our user’s profile location, we could build our C2 payload as a DLL and load it using rundll32.exe. But there was a problem… How would such a file magically appear on a machine without Internet access, no other incoming or outgoing network connections allowed from and to the RDS server, no copy/paste functionality between our machine and the RDS, and no access to the physical server (i.e. to plug in an external USB storage device)? The answer was simple… we had to create the DLL file on the RDS server ourselves using whatever tools we could use (i.e. Living off the Land).
Therefore, using the shortcut trick, we proceeded to check if execution of the csc.exe .Net compiler was permitted. To our surprise it was. We quickly checked if msbuild.exe was also permitted but to our disappointment it wasn’t. You see, using msbuild.exe we could build our code and execute it at the same time. That was alright. We could still use csc.exe to compile a DLL and execute it with rundll32.exe. But as we already knew, rundll32.exe cannot run managed code DLLs because they are missing required exported functions.
Searching the web for an answer to our problem, we stumbled upon Adam “XPN” Chester’s blog post titled “RunDLL32 your .NET (AKA DLL exports from .NET)”. In his blog post, Adam describes how to compile C# source code into a DLL, extract the Intermediate Language (IL) code, edit it so that the required functions are exported and eventually recompile it back into the final DLL. This was very interesting, but we certainly couldn’t do all these things on the RDS server because of the Application Whitelisting restrictions. We didn’t even have a text editor on the system to write our source code, let alone having the ILSpy, dnSpy or ildasm tools installed.
What we could do though, was to somehow manually write the IL code on the RDS server and use ilasm.exe to compile it into a DLL. But was ilasm.exe a whitelisted application? We quickly verified that it was and hence our plan became a plausible one. But we had one last problem to solve. Where would we write the IL code, since we didn’t have access to any built-in text editors (e.g. Notepad)?
We began searching for ways to write text into a file using Internet Explorer, when we remembered that Firefox was also an option. We had previously used it in an attempt to access the C drive using a “Browse” button generated by typing the Data URL string data:text/html,<input type="file"> in the browser’s address bar and pressing Enter. We launched Firefox again and entered the aforementioned string into the address bar. To our surprise, we discovered that as soon as the string in the address bar was rendered by the browser, we could use the previously greyed-out “Save Page As” option from the “File Menu” to save a file in our user’s profile location. We could save a file but we couldn’t open it once it was written on disk, which meant we couldn’t re-edit it and make changes to it.
We also thought that if the save file functionality was enabled, maybe other functions were as well. We pressed the Ctrl+Shift+I keys and the Web Developer Tools pane appeared at the bottom of the browser window. Great!!! We could use the Inspector pane of the tools to write our IL code and save it using Firefox’s “Save Page As” menu option.
But we quickly realized that any changes to the HTML code done through the Inspector pane were temporary and could not be saved to a file.
We had no other choice. We had to write our IL code in the browser’s address bar prepended with data:text/plain, and save it to a file. Firefox 97 and newer versions allow data URL sizes of up to 32MB, which was plenty of space to host our IL code. We played around with the IL code and URL encoding of special characters, on our virtual lab environment, and found out that we could URL encode the CRLF bytes (%0d%0a) in the address bar and still have our IL code compile successfully. A few more tries and we found out that we didn’t even need the CRLF bytes in the IL code. We just needed to have a space character separating IL instructions.
When everything was ready, we typed our IL payload’s code in Firefox’s address bar as a single line of text and saved it in a file within our profile.
We then used the shortcut trick to compile it into a DLL using ilasm.exe.
We verified that the DLL file was generated successfully…
and we created another shortcut file to execute the DLL using rundll32.exe.
We then crossed our fingers and double-clicked the run_dll shortcut file. We were presented with the expected message “.Net Assembly Running”.
Our Proof-of-Concept code worked!!! We had proven that arbitrary code execution was achievable on the system and more advanced payloads could be crafted and executed on it (e.g. command execution, C2 payloads, privilege escalation, etc.). It was a good day and a worthy challenge for us.