Langsung ke konten utama

Apacolypse Now: Exploiting Windows Ten Inward A Local Network Amongst Wpad/Pac As Well As Jscript

by Ivan Fratric, Thomas Dullien, James Forshaw too Steven Vittitoe

Intro

Many widely-deployed technologies, viewed through 20/20 hindsight, seem similar an strange or unnecessarily risky idea. Engineering decisions inward information technology are ofttimes made amongst imperfect information too nether fourth dimension pressure, too some oddities of the information technology stack tin best live explained amongst “it seemed similar a expert thought at the time”. In the personal persuasion of some of the authors of this post, WPAD (“Web Proxy Auto Discovery Protocol” - too to a greater extent than specifically “Proxy Auto-Config”), is i of these oddities.

At some dot inward the really early on days of the Internet - prior to 1996 - engineers at Netscape decided that JavaScript was a expert linguistic communication to write configuration files in. The final result was PAC - a configuration file format that industrial plant equally follows: The browser connects to a pre-configured server, downloads the PAC file, too executes a particular Javascript role to determine proper proxy configuration. Why not? It surely is to a greater extent than expressive too less verbose than (let’s say) XML, too seems a reasonable way to render configurations to many clients.

PAC itself was coupled amongst a protocol called WPAD - a protocol that makes it unnecessary for the browser to remove hold a pre-configured server to connect to. Instead, WPAD allows the estimator to query the local network to determine the server from which to charge the PAC file.

Somehow this technology ended upwardly existence an IETF draft which expired inward 1999, too now, inward 2017, every Windows machine volition enquire the local network: “Hey, where tin I discovery a Javascript file to execute?”. This tin travel on via a number of mechanisms: DNS, WINS, but - mayhap most interestingly - DHCP.

In recent years, browser exploits remove hold mutated from existence primarily DOM-oriented to targeting Javascript engines directly, so the mere get upwardly that nosotros tin larn Javascript execution over the network without the browser was motivating. An initial investigation revealed that the JS Engine responsible for executing these configuration files was jscript.dll - the legacy JS Engine that also powered IE7 too IE8 (and is still reachable inward IE11 inward IE7/8 compatibility fashion if appropriate script attributes are used). This is both expert too bad - on the i hand, it agency that non every Chakra põrnikas is automatically a local network remote attack, but on the other hand, it agency that some pretty former code volition live responsible for executing our Javascript.

Security researchers remove hold previously warned about the dangers of WPAD. But, equally far equally nosotros know, this is the commencement fourth dimension that an assault against WPAD is demonstrated that results inward the consummate compromise of the WPAD user’s machine.

Windows is surely non the alone slice of software that implements WPAD. Other operating systems too applications practice equally well. For representative Google Chrome also has a WPAD implementation, but inward Chrome’s case, evaluating the JavaScript code from the PAC file happens within a sandbox. And other operating systems that back upwardly WPAD don’t enable it yesteryear default. This is why Windows is currently the most interesting target for this variety of attack.

Web Proxy Auto-Discovery

As mentioned above, WPAD volition query DHCP too DNS (in that order) to obtain a URL to connect to - plainly LLMNR too Netbios tin also live used if no response from DNS is available. Some peculiarities of WPAD-over-DNS enable surprising assault vectors.

Attack scenario: Local network via DHCP

In the most mutual scenario, a machine volition query the local DHCP server using alternative code 252. The DHCP server replies amongst a string - similar “http://server.domain/proxyconfig.pac”, which specifies a URL from which the configuration file should live fetched. The customer so proceeds to fetch this file, too execute the contents equally Javascript.
In a local network, an assailant tin just impersonate the DHCP server - either yesteryear ARP games or yesteryear racing the legitimate DHCP. The assailant tin so render a URL where the malicious Javascript file is hosted.

Attack scenario: Remote over the cyberspace via privileged seat too DNS

Aside from the local-network assault scenario, the fact that lookup for WPAD may also travel on via DNS creates a secondary assault scenario. Many users configure their computers to perform DNS lookups against i of the public, globally visible DNS servers (such equally 8.8.8.8, 8.8.4.4, 208.67.222.222 too 208.67.220.220). In such a scenario, a machine volition transportation DNS queries (such equally wpad.local) to the server which sits exterior of the local network. An assailant inward a privileged seat on the network (e.g. a gateway, or whatever other upstream host) tin monitor the DNS queries too spoof a reply, directing the customer to download too execute a malicious Javascript file.

Setups similar these seem to live mutual - according to this Wikipedia entry, a nontrivial proportion of the traffic that the DNS root servers consider are .local requests.

Attack scenario: Remote over the cyberspace via malicious wpad.tld

A particular oddity of WPAD is that it recursively walks the local machine hollo to discovery domains to query. If a machine is called “laptop01.us.division.company.com”, the next domains are supposedly queried inward order:

  • wpad.us.division.company.com
  • wpad.division.company.com
  • wpad.company.com
  • wpad.com

This has (according to this Wikipedia entry) inward the yesteryear led to people registering wpad.co.uk too redirecting traffic to an online auction site. Further quoting from that entry:

Through the WPAD file, the assailant tin dot users' browsers to their ain proxies too intercept too modify all of World Wide Web traffic. Although a simplistic prepare for Windows WPAD treatment was applied inward 2005, it alone fixed the work for the .com domain. Influenza A virus subtype H5N1 presentation at Kiwicon showed that the ease of the globe was still critically vulnerable to this safety hole, amongst a sample domain registered inward New Zealand for testing purposes receiving proxy requests from all over the province at the charge per unit of measurement of several a second. Several of the wpad.tld domain names (including COM, NET, ORG, too US) at nowadays dot to the customer loopback address to assist protect against this vulnerability, though some names are still registered (wpad.co.uk).
Thus, an administrator should brand sure that a user tin trust all the DHCP servers inward an organisation too that all possible wpad domains for the organisation are nether control. Furthermore, if there's no wpad domain configured for an organisation, a user volition travel to whatever external location has the next wpad site inward the domain hierarchy too utilisation that for its configuration. This allows whoever registers the wpad subdomain inward a particular province to perform a man-in-the-middle attack on large portions of that country's cyberspace traffic yesteryear setting themselves equally a proxy for all traffic or sites of interest.

The IETF draft, on the other hand, explicitly asks for clients to alone allow “canonical” (e.g. non-top-level domains). We remove hold non investigated to what extent clients implement this, or if second-level domains (such equally .co.uk) are the culprit inward the historical cases of traffic redirection.

Either way: Bugs inward the Javascript engine nether consideration tin live exploited remotely via the cyberspace if i manages to register wpad.$TLD for a given organization’s TLD, provided said TLD is non explicitly blacklisted yesteryear the customer implementation. Given that the IETF draft from 1999 refers to a listing of TLDs from 1994 (RFC1591), it is unlikely that clients remove hold been updated to reverberate the proliferation of novel TLDs.

Our attempts to register wpad.co.$TLD for a diverseness of TLDs were non (yet) successful.

Bugs

We spent some fourth dimension looking for bugs inward jscript.dll too employed both manual analysis too fuzzing. JScript initially posed some challenge because a lot of “features” useful for triggering bugs inward JavaScript engines can’t live used inward JScript, just due to it existence besides former to back upwardly them. For example:

  • There are no multiple arrays types (int array, float array etc.). Thus confusing i array type for some other is non possible.
  • There are non equally many optimizations (“fast paths”) equally inward the newer, faster JavaScript engines. These fast paths are ofttimes the source of bugs.
  • It is non possible to define a getter/setter on a generic JavaScript object. It is possible to telephone telephone defineProperty but alone on DOM objects which doesn’t piece of work for us equally at that spot won’t live a DOM inward the WPAD process. Even if at that spot were, a lot of JScript functions volition just neglect when called on a DOM object amongst a message “JScript object expected”.
  • It is impossible to alter an object’s epitome in i lawsuit it is created (i.e. at that spot is no “__proto__” property).

However, JScript does endure from to a greater extent than “old-school” vulnerability classes such equally use-after-free. JScript’s garbage collector is described inward this former MSDN article. JScript uses a non-generational mark-and-sweep garbage collector. Essentially, whenever a garbage collection is triggered, it marks all the JScript objects. Then it scans them starting from a laid of “root” objects (sometimes also referred to equally “scavengers”) too clears the grade from all the objects it encounters. All the objects that are still marked larn deleted. One recurring work is that local variables on the stack aren’t added to the listing of root objects yesteryear default, important that a programmer needs to retrieve to add together them to the garbage collector’s root list, particularly if those variables refer to objects that tin live deleted during the function’s lifetime.

Other possible types of vulnerabilities include buffer overflows, uninitialized variables etc.

For fuzzing, nosotros used the grammar-based Domato fuzzing engine too wrote a novel grammar specifically for JScript. We identified interesting built-in properties too functions to add together to the grammar yesteryear looking at EnsureBuiltin methods of diverse JScript objects. The JScript grammar has been added to the Domato repository here.

Between fuzzing too manual analysis nosotros identified vii safety vulnerabilities. They are summarized inward the tabular array below:

Vulnerability class
Vulnerabilities affecting IE8 mode
Vulnerabilities affecting IE7 mode
Use-after-free
Heap overflow
Uninitialized variable
Out-of-bounds read
Total
7
5

At the fourth dimension of publishing this weblog post, all the bugs remove hold been fixed yesteryear Microsoft.

The tabular array breaks downwards the vulnerabilities yesteryear degree too compatibility fashion required to trigger them. JScript inward WPAD is equivalent to running a script inward IE7 compatibility mode, which agency that, although nosotros establish 7 vulnerabilities, “only” v of them tin live triggered inward WPAD. However, the other vulnerabilities tin still live used against Internet Explorer (including IE11) when lay into IE8 compatibility fashion yesteryear a malicious webpage.

Exploit


Understanding JScript VARs too Strings

Since inward the balance of this blogpost we’re going to speak nearly JScript VARs too Strings a lot, it is useful to depict these earlier going deeper into how the exploits work.

JScript VAR is a 24-byte (on 64-bit builds) construction that represents a JavaScript variable too is essentially the same equally the VARIANT information construction described inward this MSDN article. In most cases (sufficient to follow the exploit) its retentiveness layout looks similar this:

Offset
Size
Description
0
2
Variable type, 3 for integer, v for double, 8 for string etc.
8
8
Depending on the type, either an immediate value or a pointer
16
8
Unused for most types

For example, nosotros tin correspond a double precision number yesteryear a VAR that has v written inward the commencement 2 bytes (indicating the double type), followed yesteryear an actual double value at offset 8. The in conclusion 8 bytes are going to live unused but they are going to live copied around if a value of some other VAR is copied from this VAR.

A JScript string is a type of VAR that has the type 8 too a pointer at offset 8. The pointer points into a BSTR construction described here. On 64-bit builds BSTR layout looks similar this:

Offset
Size
Description
0
4
Unused
4
4
String length inward bytes non counting the cypher grapheme at the end
8
length+2
String characters (16-bit) followed yesteryear a cypher character

A String VAR points direct to the grapheme array, which agency that, to obtain a String's length, the pointer needs to live decremented yesteryear four too the length read from there. Note that BSTRs are handled yesteryear OleAut32.dll too are allocated on a dissever heap (i.e. a different heap than is existence used for other JScript objects).

Freeing of BSTRs is also different than for most objects because, instead of direct freeing a BSTR, when SysFreeString is called, it commencement puts a string inward a cache controlled yesteryear OleAut32.dll. This machinery is described inward item inward Heap Feng Shui inward JavaScript.

Stage 1: Infoleak

The purpose of the infoleak volition live to obtain the address of a string inward retentiveness whose content nosotros fully control. We won’t live leaking whatever executable module addresses at this point, that volition come upwardly later. Instead, the goal is to defeat high-entropy heap randomization too brand the 2nd phase of the exploit reliable without having to utilisation heap spraying.

For the infoleak we’re going to utilisation this bug inward RegExp.lastParen. To empathise the põrnikas let’s commencement convey a closer aspect at the retentiveness layout of jscript!RegExpFncObj which corresponds to the JScript RegExp object. At offset 0xAC RegExpFncObj contains a buffer of twenty integers. Actually these are 10 pairs of integers: the commencement chemical ingredient of the pair is the start index into the input string too the 2nd chemical ingredient is the destination index. Whenever RegExp.test, RegExp.exec or String.search amongst a RegExp parameter come across a capturing grouping (parentheses inward the RegExp syntax), the start too destination index of the check are stored here. Obviously inward the buffer at that spot is infinite for alone 10 matches, so alone the commencement 10 matches are stored inward this buffer.

However, if RegExp.lastParen is called too at that spot were to a greater extent than than 10 capturing groups, RegExpFncObj::LastParen volition happily utilisation the number of capturing groups equally an index into the buffer, leading to out-of-bounds read. Here is a PoC:

 var r= novel RegExp(Array(100).join('()'));
 ''.search(r);
 alert(RegExp.lastParen);

The 2 indices (let’s telephone telephone them start_index too end_index) are read exterior the bounds of the buffer too tin hence live made arbitrarily large. Assuming this commencement out-of-bounds access doesn’t crusade a crash, if the values inward those indices are larger than the length of the input string, so a second out-of-bounds access is going to occur which allows us to read a exterior the bounds of the input string. The string content read out-of-bounds similar this is going to live returned to the caller inward a String variable where it tin live examined.

This 2nd out-of-bounds read is what we’re going to use, but commencement nosotros demand to figure out how to larn controlled information into start_index too end_index. Fortunately, looking at the layout of RegExpFncObj, at that spot is information nosotros command after the destination of the index buffer: RegExp.input value. By setting RegExp.input to an integer value too using a RegExp composed of 41 sets of empty parentheses, when  RegExp.lastParen gets called, start_index is going to live 0 too the end_index is going to live whatever value nosotros wrote to RegExp.input.

If nosotros brand an input string next to a freed string, so yesteryear reading after the bounds of input string, nosotros tin obtain the heap metadata such equally the pointers to the other gratis heap segments (Left, Right too Parent node inward the red-black tree of heap chunks, consider Windows 10 Segment Heap Internals for to a greater extent than information). Image 1 shows the relevant objects at the 2nd of infoleak.

Image 1: Heap infoleak layout

We are using 20000 bytes-long strings equally input inward social club for them not to live allocated on the Low Fragmentation Heap (LFH tin alone live used for allocations of 16K bytes too smaller) since the heap metadata for the LFH is different too does non include useful pointers inward Windows 10 Segment Heap. Additionally, LFH introduces randomness that would touching on our powerfulness to identify the input string next to a freed string.

By reading the heap metadata out of the returned string, nosotros tin obtain an address of a freed string. Then, if nosotros allocate a string of the same size equally the freed string, it powerfulness live placed at this address too nosotros achieved our goal, that is nosotros know the address of retentiveness of a string whose content nosotros control.

The whole infoleak procedure looks similar this:

  1. Allocate m 10000-character strings (note: 10000 characters == 20000 bytes).
  2. Free every 2nd one.
  3. Trigger the information leak bug. Use i of the remaining strings equally an input strings too read 20080 bytes.
  4. Analyze the leaked string too obtain the pointer to i of the freed strings.
  5. Allocate 500 strings of the same length equally the freed strings (10000 characters) amongst a specially crafted content.

The content of the specially crafted strings is non of import at this stage, but volition live of import inward the next one, so it volition live described there. Also banking company complaint that, yesteryear examining heap metadata, nosotros tin easily determine which heap implementation the procedure is using (Segment Heap vs NT heap).

Images 2 too 3 demo heap visualization created using Heap History Viewer at the fourth dimension around the infoleak. Green stripes correspond allocated blocks (occupied yesteryear strings), greyish stripes correspond allocated blocks that are so freed yesteryear later on allocated in i lawsuit again (the stings nosotros gratis too so reallocate after triggering the infoleak bug) too the white stripes correspond information that is never allocated (guard pages). You tin consider how strings larn allocated equally the fourth dimension passes, so one-half of them are freed (grey ones) too sometime later on larn allocated in i lawsuit again (the stripes travel green).

We tin consider that at that spot are going to live guard pages after every 3 allocations of this size. Our exploit is never genuinely going to touching whatever of these guard pages (it reads besides footling information yesteryear the destination of the string for that to occur) but inward ⅓ of the cases at that spot won’t live a gratis string after the input string for the infoleak so the expected heap metadata volition live missing. We can, however, easily discovery this instance too either trigger the infoleak põrnikas using some other input string or silently abort the exploit (note: nosotros didn’t trigger whatever retentiveness corruption upwardly to this point).

Image 2: Heap Diagram: Showing the development of the heap over time
Image 3: Step-by-step illustration of leaking a pointer to a string.

Stage 2: Overflow

In phase 2 of the exploit we’re going to utilisation this heap overflow bug inward Array.sort. In instance the number of elements inward the input array to Array.sort is larger than Array.length / 2, JsArrayStringHeapSort (called yesteryear Array.sort if a comparing role isn’t specified) is going to allocate a temporary buffer of the same size equally the number of elements currently inward the array (note: tin live smaller than array.lenght). It is so going to endeavour to retrieve the corresponding elements for every array index from 0 to Array.length and, if that chemical ingredient exists, add together it to the buffer too convert to string. If the array doesn’t alter during the lifetime of JsArrayStringHeapSort, this volition piece of work fine. However, JsArrayStringHeapSort converts array elements into strings which tin trigger toString() callbacks. If during i of those toString() callbacks elements are added to the array where they were previously undefined, an overflow is going to occur.

To empathise the põrnikas too its exploitability amend let’s convey a closer aspect at the construction of the buffer we’ll overflow out of. It is already mentioned that the array volition remove hold the same size equally the number of elements currently inward input array (to live exact, it is going to live number of elements + 1). Each chemical ingredient of the array is going to live 48 bytes inward size (in a 64-bit build) amongst the next structure:

Offset
Size
Descripion
0
8
Pointer to a string VAR after the original VAR at offset sixteen is converted to string
8
4
Index (int) of the electrical flow element
16
24
VAR holding the original array element
40
4
int 0 or 1 depending on the type of VAR at offset 16

During JsArrayStringHeapSort, each chemical ingredient of the array amongst index < array.length is retrieved, too if the chemical ingredient is defined the next happens:

  1. The array chemical ingredient is read into VAR at offset 16
  2. The original VAR is converted into a string VAR. Influenza A virus subtype H5N1 pointer to the string VAR is written at offset 0.
  3. At offset 8, the index of the electrical flow chemical ingredient inward array is written
  4. Depending on the original VAR type, 0 or 1 is written at offset 40

Looking at the construction of the temporary buffer, nosotros don’t command a lot of it directly. If an array fellow member is a string, so at offsets 0 too 24 we’re going to remove hold a pointer that, when dereferenced, at offset 8 contains some other pointer to the information nosotros control. This is, however, i aeroplane of indirection larger than what would live useful to us inward most situations.

However, if a fellow member of array is a double precision number, so at offset 24 (corresponding to offset 8 into the original VAR) the value of that number is going to live written too it is direct nether our control. If nosotros create a number amongst the same double representation equally the pointer obtained inward Stage 1, so nosotros tin utilisation our overflow to overwrite a pointer somewhere after the destination of the buffer amongst a pointer to the retentiveness nosotros direct control.

Now the enquiry becomes, what tin nosotros overwrite inward this way to advance the exploit. One of the possible answers presents itself if nosotros convey a closer aspect at how Objects piece of work inward JScript.

Each Object (more specifically, a NameList JScript object) is going to remove hold a pointer to a hashtable. This hashtable is just an array of pointers. When a fellow member chemical ingredient of an Object is accessed, a hash of the hollo of the chemical ingredient is computed. Then, a pointer at the offset corresponding to the lowest bits of the hash is dereferenced. This pointer points to a linked listing of object elements too this linked listing is traversed until nosotros reached an chemical ingredient amongst the same hollo equally the requested element. This is shown inward icon 4.

Image 4: JScript Object chemical ingredient internals

Note that, when the hollo of the chemical ingredient is less than four bytes, it is stored inward the same construction equally the VAR (element value). Otherwise, at that spot is going to live a pointer to the chemical ingredient name. Name lengths <=4 are sufficient for us so nosotros don’t demand to travel into the details of this.

An Object hashtable is a expert candidate to overwrite because:

  • We tin command which elements of it are dereferenced yesteryear accessing the corresponding object members. Elements nosotros overwrite amongst information nosotros don’t command volition just never live accessed.
  • We remove hold limited command over the hashtable size yesteryear controlling how many members the corresponding object has. For representative a hashtable starts amongst 1024 bytes, but if nosotros add together to a greater extent than than 512 elements to the object, the hashtable volition live reallocated to 8192 bytes.
  • By overwriting a hashtable pointer amongst a pointer to information nosotros control, nosotros tin create simulated JScript vars inward the information nosotros command too access them just yesteryear accessing the corresponding object members.

To perform the overwrite reliably nosotros practice the following:

  1. Allocate too gratis a lot of retentiveness blocks amongst size 8192. This volition plough on the Low Fragmentation Heap for allotment of size 8192. This volition ensure that the buffer nosotros are alluvion out of, equally good equally hashtable nosotros are alluvion into volition live allocated on the LFH. This is of import because it agency at that spot volition live no other allocations of other sizes nearby to spoil the exploit endeavour (since an LFH bucket tin alone incorporate allocations of a sure size). This inward plough ensures that nosotros volition live overwriting just what nosotros desire amongst high reliability.
  2. Create 2000 objects, each containing 512 members. In this state, each object has a hashtable of 1024 bytes. However, adding just i to a greater extent than chemical ingredient to i of these objects volition crusade its hashtable to grow to 8192 bytes.
  3. Add the 513 chemical ingredient to the commencement m objects, causing m allocations of 8192-byte hashtables.
  4. Trigger Array.sort amongst an array amongst length=300 too 170 elements. This allocates a buffer of size (170+1)*48=8208 bytes. Due to LFH granularity this object volition live allocated inward the same LFH bucket equally 8192-byte hashtables.
  5. Immediately (in the toString() method of the commencement array element) add together 513th chemical ingredient to the 2nd m objects. This makes us pretty sure that yesteryear at nowadays the variety buffer is neighboring i of the hashtables. In the same toString() method also add together to a greater extent than elements to the array which volition crusade it to grow out-of-bounds.

Image v shows heap visualization around the address of the variety buffer (red line). You tin consider the variety buffer is surrounded yesteryear allocations of similar size which all correspond to Object hashtables. You tin also observe the LFH randomness inward the feel that subsequent allocations are non necessarily on subsequent addresses, withal this makes no departure for our exploit.

Image 5: Heap visualization around the overflow buffer

As mentioned previously, nosotros crafted our overflow inward such a way that some of the hashtable pointers of an unlucky JScript object volition larn overwritten amongst pointers into the information nosotros control. Now finally what just nosotros lay into this information comes into play: nosotros crafted it inward such a way that it contains v (fake) JavaScript variables:

  • Variable 1 just contains number 1337.
  • Variable 2 is of special type 0x400C. This type basically tells JavaScript that the actual VAR is pointed to yesteryear pointer at offset 8, too this pointer should live dereferenced earlier reading or writing this variable. In our case, this pointer points sixteen bytes earlier Variable 1. This basically agency that the in conclusion 8-byte qword of Variable 2 too the commencement 8-byte qword of Variable 1 overlap.
  • Variable 3, Variable four too Variable v are uncomplicated integers. What is special nearly them is that they incorporate numbers 5, 8 too 0x400C inward their in conclusion 8 bytes, respectively.

The province of the corrupted Object after the overflow is shown inward icon 6.

Image 6: State of objects after the overflow. Red areas signal where the overflow occurred. Each box inward the bottom row (except those marked equally ‘...’) corresponds to 8 bytes. Data contained inward ‘...’ boxes is omitted for clarity

We tin access Variable 1 yesteryear just accessing the corrupted object at the right index (let’s telephone telephone it index1) too similarly for Variables 2-5. In fact, nosotros tin discovery which Object nosotros corrupted yesteryear accessing index1 of all objects too seeing which at nowadays has the value 1337.

Overlapping Variable 1 too Variable 2 has the upshot that nosotros tin alter the type (first WORD) of Variable 1 into v (double), 8 (string) or 0x400C (pointer). We practice this yesteryear reading Variable 2, 3 or four too so writing the read value into Variable 2. For representative the statement

corruptedobject[index2] = corruptedobject[index4];

Has the upshot that the type of Variable 1 volition live changed into a String (8), patch all other fields of Variable 1 volition rest unchanged.

This layout gives us several really powerful exploitation primitives:

  • If nosotros write some variable that contains a pointer into Variable 1, nosotros tin let on the value of this pointer yesteryear changing the type of Variable 1 to double (5) too reading it out
  • We tin let on (read) retentiveness at an arbitrary address yesteryear faking a String at that address. We tin accomplish this yesteryear commencement writing a double value corresponding to the address nosotros desire to read into Variable 1 too so changing the type of Variable 1 toString (8).
  • We tin write to an arbitrary address yesteryear commencement writing a numeric value corresponding to the address into Variable 1, so changing the type of Variable 1 to 0x400C (pointer) too finally writing some information to Variable 1.

With these exploit primitives, commonly getting the code execution would live pretty simple, but since we’re exploiting Windows 10 nosotros commencement demand to bypass the Control Flow Guard (CFG).

Stage 3: CFG bypass

There are in all likelihood other known bypasses nosotros could remove hold used here, but it turns out that at that spot are some really convenient bypasses (once assailant has a read/write primitive) specific to jscript.dll. We are going to exploit the facts that:

  • Return addresses are non protected yesteryear CFG
  • Some Jscript objects remove hold pointers to the native stack

Specifically, each NameTbl object (in Jscript, all JavaScript objects inherit from NameTbl), at offset 24 holds a pointer to CSession object. CSession object, at offset lxxx holds a pointer to close the top of the native stack.

Thus, amongst an arbitrary read, yesteryear next a chain of pointers from whatever JScript object, it is possible to retrieve a pointer to the native stack. Then, amongst an arbitrary write, it is possible to overwrite a render address, bypassing CFG.

Stage 4: Getting code execution equally Local Service

With all the exploit elements inward place, nosotros tin at nowadays travel along to getting the code execution. We are doing it inward these steps:

  1. Read the address of jscript.dll from a vtable of whatever JScript object
  2. Read the address of kernel32.dll yesteryear reading the import tabular array of jscript.dll
  3. Read the address of kernelbase.dll yesteryear reading the import tabular array of kernel32.dll
  4. Scan kernel32.dll for rop gadgets nosotros are going to need
  5. Get the address of WinExec from the export tabular array of kernel32.dll
  6. Leak the stack address equally explained inward the previous section
  7. Prepare the ROP chain too write it to the stack, starting amongst a render address closest to our leaked stack address.

The ROP chain nosotros are using looks similar this:

[address of RET]  //needed to align the stack to sixteen bytes
[address of POP RCX; RET] //loads the commencement parameter into rcx
[address of command to execute]
[address of POP RDX; RET] //loads the 2nd parameter into rdx
1
[address of WinExec]

By executing this ROP chain nosotros are calling WinExec amongst a command nosotros specified. For example, if nosotros run the command ‘cmd’ nosotros are going to consider a command prompt existence spawned, running equally Local Service (the same user WPAD service runs as).

Unfortunately, from a youngster procedure running equally Local Service, nosotros can’t speak to the network, but what nosotros tin practice is driblet our privilege escalation payload from retentiveness to a disk location Local Service tin write too execute it from there.

Stage 5: Privilege escalation

While the Local Service describe concern human relationship is a service account, it doesn’t remove hold administrative privileges. This agency the exploit is quite limited inward what it tin access too modify on the system, particularly to persist after exploitation or after the scheme has been rebooted. While there’s e'er probable to live an unfixed privilege escalation inward Windows nosotros don’t demand to discovery a novel vulnerability to escalate our privileges. Instead nosotros tin abuse a built-in characteristic to escalate from Local Service to the SYSTEM account. Let’s aspect at the privileges that the service describe concern human relationship for WPAD has been granted:

Image 7: Service Access Token’s Privileges showing Impersonate Privilege

We’ve alone got 3 privileges, but the highlighted privilege, SeImpersonatePrivilege is important. This privilege allows the service to impersonate other users on the local system. The argue the service has impersonate privilege is it accepts requests from all users on the local scheme too powerfulness demand to perform actions on their behalf. However, equally long equally nosotros tin larn an access token for the describe concern human relationship nosotros desire to impersonate nosotros tin larn the total access rights of the token’s user account, including SYSTEM which would give us administrator rights on the local system.

Abusing impersonation is a known number amongst the Windows safety model (you tin discovery to a greater extent than details yesteryear searching for Token Kidnapping). Microsoft remove hold tried to arrive harder to larn an access token for a privileged user but it’s virtually impossible to unopen all possible routes. For example, James discovered a vulnerability inward Windows’ implementation of DCOM which allows whatever user to larn access to a SYSTEM access token. While Microsoft fixed the direct privilege escalation vulnerability they didn’t, or mayhap couldn’t, prepare the token kidnapping issue. We tin abuse this characteristic to capture the SYSTEM token, impersonate the token, so completely compromise the system, such equally installing a privileged service.

There’s an existing implementation of the token kidnapping via DCOM (RottenPotato) withal the implementation was designed for utilisation amongst the Metasploit framework’s getsystem command which we’re non using. Therefore, nosotros implemented our ain simpler version inward C++ which direct spawns an arbitrary procedure amongst a SYSTEM token using the CreateProcessWithToken API. As a bonus nosotros were able to compile it to an executable of 11KiB inward size, much smaller than RottenPotato, which made it easier to driblet to disk too run from the ROP payload.

Tying it all together

When the WPAD service queries for the PAC file, nosotros serve the exploit file which exploits the WPAD service too runs WinExec to driblet too execute the privilege escalation binary. This binary so executes a command (hardcoded ‘cmd’ inward our case) equally SYSTEM.

The exploit worked pretty reliably inward our experiments, but it is interesting to banking company complaint that a 100% reliable exploit isn’t required - if the exploit crashes the WPAD service, a novel instance is going to larn spawned when a customer makes some other asking from WPAD service, so an assailant tin just assay again. There volition live no indication inward the UI that the WPAD service has crashed, although Window Error Reporting volition probable pick upwardly the crash too written report it to Microsoft, provided that the user didn’t disable it.

In fact, our exploit doesn’t create clean upwardly gracefully too volition crash the WPAD service in i lawsuit it runs its payload, so if nosotros hold serving the exploit PAC file after the service has been exploited, it volition just larn exploited again. You tin consider the upshot of that inward Image 7, which was taken after leaving the exploit server running for some minutes too making a lot of HTTP requests inward the victim machine.

Image 7: Did nosotros travel out the exploit running for besides long?

We’ll lay out the exploit source code inward the issue tracker shortly.

Conclusion

Executing untrusted JavaScript code is dangerous, too executing it inward an unsandboxed procedure is fifty-fifty to a greater extent than so. This is truthful fifty-fifty if it’s done yesteryear a relatively compact JavaScript engine such equally jscript.dll. We identified 7 safety vulnerabilities inward it too successfully demonstrated reliable code execution from local network (and beyond) against a fully patched (at the fourth dimension of writing) Windows 10 64-bit amongst Fall Creators Update installed.

Since the bugs are at nowadays fixed, does this hateful nosotros are done too tin travel home? Unlikely. Although nosotros spent a fair amount of time, effort too compute powerfulness on finding jscript.dll bugs, nosotros brand no claims that nosotros establish all of them. In fact, where at that spot are 7 bugs, at that spot is probable to live an 8th. So if something doesn’t alter it is quite possible we’ll consider a chain similar this used inward the wild someday (and that is, of course, optimistically assuming that attackers don’t remove hold this capability already).

So, what tin Microsoft practice to brand hereafter attacks similar this harder:

  • Disable WPAD yesteryear default. In fact, patch the other operating systems back upwardly WPAD, Windows is the alone i where it is enabled yesteryear default.
  • Sandbox the JScript interpreter within the WPAD service. Since the interpreter needs to execute a JavaScript role amongst good defined inputs too render the output string, sandboxing it should live pretty straightforward. Given the simplicity of the input-output model, it would live slap-up if Microsoft introduced a sandbox of comparable restrictiveness to seccomp-strict: Some processes genuinely practice non demand to a greater extent than privileges than “receive a chip of data”, “perform a chip of computation”, “return a chip of data”.

In instance you lot desire to convey activeness on your own, the alone way to foreclose this type of assault using new, currently unknown vulnerabilities, seems to live to completely disable the WinHttpAutoProxySvc service. Sometimes this can’t live done inward the Services UI (“Startup type” command volition live grayed out) due to other services depending on WPAD, but it tin live done via the corresponding registry entry. Under “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinHttpAutoProxySvc” alter the value of “Start” from 3 (manual) to four (disabled).

These are some of the advices commonly establish online when searching for “disabling WPAD” that did not piece of work to foreclose the assault inward our experiments:

  • Turning off “Automatically discovery settings” inward Control Panel
  • Setting “WpadOverride” registry key
  • Putting “255.255.255.255 wpad” inward the hosts file (this is going to halt the DNS variant but probable non the DHCP variant)

Komentar

Postingan populer dari blog ini

Exception-Oriented Exploitation On Ios

Posted past times Ian Beer, This postal service covers the regain in addition to exploitation of CVE-2017-2370 , a heap buffer overflow inwards the mach_voucher_extract_attr_recipe_trap mach trap. It covers the bug, the evolution of an exploitation technique which involves repeatedly in addition to deliberately crashing in addition to how to build alive meat introspection features using onetime meat exploits. It’s a trap! Alongside a large number of BSD syscalls (like ioctl, mmap, execve in addition to so on) XNU also has a pocket-sized number of extra syscalls supporting the MACH side of the meat called mach traps. Mach trap syscall numbers start at 0x1000000. Here’s a snippet from the syscall_sw.c file where the trap tabular array is defined: /* 12 */ MACH_TRAP(_kernelrpc_mach_vm_deallocate_trap, 3, 5, munge_wll), /* xiii */ MACH_TRAP(kern_invalid, 0, 0, NULL), /* xiv */ MACH_TRAP(_kernelrpc_mach_vm_protect_trap, 5, 7, munge_wllww), Most of the mach traps a

Lifting The (Hyper) Visor: Bypassing Samsung’S Real-Time Total Protection

Posted yesteryear Gal Beniamini, Traditionally, the operating system’s total is the concluding security boundary standing betwixt an assaulter together with total command over a target system. As such, additional aid must hold upwards taken inwards lodge to ensure the integrity of the kernel. First, when a organization boots, the integrity of its primal components, including that of the operating system’s kernel, must hold upwards verified. This is achieved on Android yesteryear the verified kicking chain . However, only booting an authenticated total is insufficient—what most maintaining the integrity of the total spell the organization is executing? Imagine a scenario where an assaulter is able to abide by together with exploit a vulnerability inwards the operating system’s kernel. Using such a vulnerability, the assaulter may endeavor to subvert the integrity of the total itself, either yesteryear modifying the contents of its code, or yesteryear introducing novel attacker-co

Chrome Bone Exploit: 1 Byte Overflow As Well As Symlinks

The next article is an invitee weblog post from an external researcher (i.e. the writer is non a or Google researcher). This post is most a Chrome OS exploit I reported to Chrome VRP inward September. The folks were squeamish to allow me do a invitee post most it, therefore hither goes. The study includes a detailed writeup , therefore this post volition have got less detail. 1 byte overflow inward a DNS library In Apr I constitute a TCP port listening on localhost inward Chrome OS. It was an HTTP proxy built into shill, the Chrome OS network manager. The proxy has at nowadays been removed equally component of a fix, but its source tin give notice nonetheless move seen from an one-time revision: shill/http_proxy.cc . The code is unproblematic in addition to doesn’t seem to incorporate whatever obvious exploitable bugs, although it is real liberal inward what it accepts equally incoming HTTP. It calls into the c-ares library for resolving DNS. There was a possible 1 byte ov