当前位置:网站首页>Remote code execution in Win 11 using wpad / PAC and JScript 3

Remote code execution in Win 11 using wpad / PAC and JScript 3

2022-04-23 20:05:00 franket

Please note that , When the name of an element is less than 4 Bytes , It is associated with VAR( Element value ) Stored in the same structure . otherwise , There will be a pointer to the element name . Name length <=4 That's enough for us , So we don't need to elaborate .

The object hash table is a good overlay object , because :

  • We can control which elements are dereferenced by accessing the corresponding object members . Elements that we overwrite with data that we cannot control will never be accessed .
  • We limit the size of the hash table by controlling how many members the corresponding object has . for example , Hash table to 1024 Byte start , But if we add more than 512 Elements , The hash table will be reassigned to 8192 byte .
  • By overwriting the hash table pointer with a pointer to the data we control , We can create fake data in the data we control JScript var, And access them by accessing the corresponding object members .

In order to perform coverage reliably , We do the following :

  1. Allocate and release a large number of sizes 8192 Memory block . This will open the low fragmentation heap to allocate a size of 8192. This will ensure that our overflow buffer and our overflow hash table will be allocated LFH. It's important , Because this means that there will be no allocation of other sizes nearby to destroy the utilization attempt ( because LFH Buckets can only contain allocations of a specific size ). This in turn ensures that we will accurately cover what we want with high reliability .
  2. establish 2000 Objects , Each object contains 512 Members . In this state , Each object has one 1024 Byte hash table . however , Adding only one element to one of these objects will cause its hash table to grow to 8192 byte .
  3. take 513 Element is added to the front 1000 Objects , Lead to 1000 Sub distribution 8192 Byte hash table .
  4. The length used is 300 and 170 An array of elements triggers Array.sort. This assigns a size of (170+1)*48=8208 Byte buffer . because LFH Particle size , The object will be assigned in the same way as 8192 Same as byte hash table LFH In the barrel .
  5. immediately ( In the first array element toString() In the method ) Will be the first 513 Add one element to the second 1000 Objects . This makes us very sure , up to now , The sort buffer is adjacent to one of the hash tables . In the same toString() In the method , More elements will be added to the array , This will cause it to go out of range .

chart 5 Shows the buffer address around the sort ( Red thread ) Heap visualization for . You can see that the sort buffer is surrounded by allocations of similar size , These allocations correspond to the object hash table . You can also observe LFH Randomness , Because the subsequent allocation is not necessarily on the subsequent address , But this has no impact on our vulnerability exploitation .

chart 5: Visual heap overflow

As mentioned earlier , We designed the overflow in such a way , Unfortunately JScript Some hash table pointers of the object will be overwritten by pointers to the data we control . Now? , What we finally added to these data : We designed it carefully , To include 5 individual ( false )JavaScript Variable :

  • Variable 1 Numbers only 1337.
  • Variable 2 It's a special type 0x400C. This type basically tells JavaScript actual VAR Offset by 8 The pointer at points to , And the pointer should be dereferenced before reading or writing the variable . In our case , This pointer points to the variable 1 Previous 16 Bytes . This basically means that variables 2 Last 8 byte qword And variables 1 One of the first 8 byte qword overlap .
  • Variable 3、 Variable 4 And variables 5 Is a simple integer . What's special about them is their last 8 Each byte contains a number 5、8 and 0x400C.

The state of the damaged object after overflow is shown in the figure 6 Shown .

chart 6: Object state after overflow . The red area indicates where the overflow occurred . Each box in the bottom row ( Marked as “...” Except for the box ) Corresponding 8 Bytes . For clarity , omitted “...” The data in the box

We can simply access the corrupted object at the correct index ( We call it index1) To access variables 1, For variables 2-5 So it is with . in fact , We can access all objects by index1 And see which object's value is now 1337 To detect which object we damaged .

Put the variable 1 And variables 2 The effect of overlap is , We can put variables 1 The type of ( first WORD) Change to 5( Double precision )、8( character string ) or 0x400C( The pointer ). So , We read variables 2、3 or 4, Then write the read value to the variable 2. For example, statement

Damaged objects index2 = Damaged objects index4;

The effect is variable 1 The type of will be changed to string (8), Variables 1 All other fields of the will remain unchanged .

This layout provides us with several very powerful utilization primitives :

  • If we write something that contains a pointing variable 1 The pointer to the variable , We can do this by putting variables 1 Change the type of to double (5) And read it out to expose the value of the pointer
  • We can expose... By forging a string at that address ( Read ) Memory at any address . We can first write the double value corresponding to the address we want to read into the variable 1, And then the variables 1 Change the type of to string (8) To do this .
  • We can write to any address , First, write the value corresponding to the address into the variable 1, And then the variables 1 The type of is changed to 0x400C( The pointer ), Finally, write some data to the variable 1.

Use these exploit primitives , Usually the execution code will be very simple , But because we are using Windows 10, We first need to bypass control flow protection (CFG).

The first 3 Stage :CFG bypass

We may have used other known bypass methods here , But it turns out , There are some very convenient ways to bypass ( Once the attacker has read / Write primitive ) Specific to jscript.dll. We will take advantage of the following facts :

  • The return address is not affected by CFG Protect
  • some Jscript Object has a pointer to the native stack

say concretely , Every NameTbl object ( stay Jscript in , all JavaScript Objects are from NameTbl Inherit ) At offset 24 Save a pointer to CSession Object pointer .CSession object , At offset 80 Hold a pointer near the top of the native stack at .

therefore , Through arbitrary reading , By tracking from any JScript Pointer chain of object , The pointer to the local stack can be retrieved . then , Through arbitrary writing , To bypass CFG Overwrite return address .

The first 4 Stage : Execute code as a local service

With all the exploit elements , We can now continue to execute the code . Let's follow the steps below :

  1. From any JScript Object's vtable Read from jscript.dll The address of
  2. By reading the jscript.dll Import table read kernel32.dll The address of
  3. By reading the kernel32.dll Import table read kernelbase.dll The address of
  4. scanning kernel32.dll Looking for what we need rop gadgets
  5. from kernel32.dll Get... From the export table of WinExec The address of
  6. Leak stack address , As mentioned in the previous section
  7. Get ready ROP Chain and write it to the stack , Start with the return address closest to the stack address we leaked .

What we use ROP The chain is as follows :

RET The address of // You need to align the stack to 16 Bytes

POP RCX Address ;RET // Load the first parameter into rcx in

The address of the command to be executed

POP RDX Address ;RET // Load the second parameter into rdx

1

WinExec The address of

By performing this ROP chain , We call... With the command we specify WinExec. for example , If we run the command “cmd”, We will see a command prompt generating , Run as a local service ( Same user WPAD Service running ).

Unfortunately , From a child process running as a local service , We can't communicate with the network , But what we can do is to delete our privilege promotion payload from memory to the disk location where the local service can write and execute it .

Stage 5: Elevated privileges

Although the local service account is a service account , But it has no administrative rights . This means that the content that can be accessed and modified by vulnerability exploitation on the system is very limited , Especially after utilization or system restart . Although in Windows There may always be unrecovered privilege escalation in , But we don't need to find new vulnerabilities to improve our permissions . contrary , We can abuse the built-in function to upgrade from local service to system account . Let's take a look WPAD The service account for has been granted permissions :

chart 7: The privileges of the service access token display impersonation privileges

We have only three privileges , But the highlighted privileges SeImpersonatePrivilege Very important . This permission allows the service to impersonate other users on the local system . The reason this service has impersonation privileges is that it accepts requests from all users on the local system , And may need to perform operations on their behalf . however , As long as we can access the simulated account , We can get full access to the token user account , Include SYSTEM , This will give us administrator privileges on the local system .

Abuse simulation is Windows A known problem with the security model ( You can do this by searching Token Kidnapping Find more details ). Microsoft is trying to make it harder for privileged users to get access tokens , But it's actually impossible to close all possible routes . for example ,James stay Windows Of DCOM Found a in the implementation Loophole , The vulnerability allows any user to access SYSTEM The access token . Although Microsoft fixed the direct privilege escalation vulnerability , But they didn't , Or you may not be able to fix the token abduction problem . We can abuse this feature to capture SYSTEM token , Fake token , Then completely destroy the system , For example, install privilege Services .

One of them passed DCOM ( RottenPotato ) Implement existing implementations of token kidnapping , But the implementation is for what we don't use Metasploit Framework of the getsystem Designed for use with commands . therefore , We are C++ Implemented our own simpler version in , It USES CreateProcessWithToken API Generate directly with SYSTEM Any process of token . As a reward , We can compile it into 11KiB The size of the executable , Than RottenPotato Much smaller , This makes it possible to ROP It becomes easier to drag and drop payloads onto disk and run .

Tie them together

When WPAD Service query PAC When you file , We offer to take advantage of WPAD Serve and run WinExec To delete and execute the vulnerability exploitation file of the privilege promotion binary . Then the binary file is used as SYSTEM Execute an order ( In our example, it is hard coded 'cmd').

This vulnerability runs very reliably in our experiments , But here's the interesting thing , Unwanted 100% Reliable vulnerabilities - If the vulnerability causes WPAD Service breakdown , When the client from WPAD When another request is made , A new instance service will be generated , So the attacker can try again .UI Will not show WPAD The service has crashed , but Window Error Reporting You may find a crash and report it to Microsoft, If the user does not disable it .

in fact , Our exploits have not been cleaned up gracefully , Once it runs, its payload crashes WPAD service , So if we continue to provide vulnerability exploitation after the service is exploited PAC file , It will only be used again . You can see the picture 7 See its effect in , This is to let the exploit server run for a few minutes and send a large number of messages in the victim machine HTTP Shot after request .

chart 7: Whether we let the exploit run too long ?

We will soon be in Problem tracker Release exploit source code in .

Conclusion

Execute untrusted JavaScript Code is dangerous , It's more dangerous to execute it in a non sandbox process . Even if it is made of relatively compact JavaScript engine ( for example jscript.dll) Accomplished , So it is with . We found 7 Security holes , And successfully demonstrated from the local network ( And other networks ) Yes, it is installed Fall Creators Update Complete repair of ( At the time of writing )Windows 10 64 Bit reliable code execution .

Now that the error has been fixed , Does that mean we've finished and can go home ? Is unlikely to . Although we spend a lot of time 、 Energy and computing power to find jscript.dll error , But we don't claim that we found all these mistakes . in fact , If there is 7 A mistake , There is likely to be a second 8 individual . therefore , If something doesn't change , We are likely to see such a chain used in the wild one day ( Of course , Assume optimistically that the attacker does not yet have this capability ).

that , What can Microsoft do to make future attacks more difficult :

  • Default disabled WPAD. in fact , Although other operating systems support WPAD, but Windows Is the only operating system that has it enabled by default .
  • take JScript The interpreter sandboxed to WPAD In service . Because the interpreter needs to execute with well-defined input JavaScript Function and returns the output string , So the sandbox should be very simple . In view of the input - The simplicity of the output model , If Microsoft introduces one with seccomp-strict A rather restrictive sandbox , That would be great : Some processes really don't need to be better than “ Receive a little data ”、“ Perform a little calculation ” More permissions ”、“ Return a little data ”.

If you want to take action on your own , The only way to prevent such an attack with a new vulnerability that is currently unknown seems to be to disable it completely WinHttpAutoProxySvc service . Because other services depend on WPAD, Sometimes this can't be in service UI Finish in (“ Start type ” The control is grayed out ), But it can be done through the corresponding registry key . stay “HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WinHttpAutoProxySvc” Next , take “Start” From 3( Manual ) Change to 4( Ban ).

These are search “ Ban WPAD” Some common suggestions on the Internet , These suggestions did not stop the attack in our experiment :

  • Close... In the control panel “ Automatic detection settings ”
  • Set up “WpadOverride” Registry entries
  • take “255.255.255.255 wpad” Put it in the host file ( This will stop DNS variant , But it may not stop DHCP variant )

版权声明
本文为[franket]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231947044595.html