This is the third part of our study about the Common Log File System (CLFS) and five vulnerabilities in this Windows OS component that have been used in ransomware attacks throughout the year. Please read the previous parts first if you haven’t already.
You can skip to the other parts using this table of contents or using the link at the end of this part.
Exploit #2 – September 2022
Two CLFS vulnerabilities were fixed in September 2022: CVE-2022-35803 and CVE-2022-37969. The last one was discovered as a zero-day exploited in the wild and it was reported by Quan Jin with DBAPPSecurity, Genwei Jiang with Mandiant, FLARE OTF, CrowdStrike, Zscaler ThreatLabz with Zscaler. We didn’t see it used in any attacks on our customers when it was a zero-day and we assume it was found when someone uploaded it to VirusTotal. While there appears to be no information about the attacks and the threat actor who used it, researchers from Zscaler have published an article about the exploit itself. Based on the details published in that blog post, we can assume that this zero-day was created by the same person who created a previously described 1-day exploit for CVE-2022-24521.
But in this part we want to discuss a different exploit. The exploit that we found was based on the code of a previously described 1-day exploit for CVE-2022-24521, it was also patched in September 2022, but it differs from the one described by Zscaler. It is more similar to the publicly described exploit for the previous CVE-2022-24521.
As mentioned in part one of our study that discussed CLFS internals, BLF files are written/read in 0x200 byte sectors, the last two bytes of the sector are used to store the sector signature, and the original bytes are stored in the location specified by the SignaturesOffset field in the block header. For legitimate BLF files, the arrays with original bytes are located in the last sectors of the blocks. The ClfsEncodeBlock and ClfsDecodeBlock functions are responsible for writing the signatures and original bytes into their locations. They are called when the code reads blocks from disk or flushes them to disk.
The exploit patches many bytes in the GENERAL_SHADOW block, in short:
- The exploit creates “fake” CLFS_BASE_RECORD_HEADER and CLFS_CONTAINER_CONTEXT structures somewhere in the BLF.
- The exploit moves the legitimate CLFS_CLIENT_CONTEXT structure so that the offset of one of the fields matches the offset of the sector signature.
- The exploit patches CLFS_LOG_BLOCK_HEADER->SignaturesOffset and moves the array with the original bytes from the last sector where it should be, to the first sector where the block header is located (offset before patch: 0x7980, offset after patch: 0x10).
The result of the changes made in step 3 is shown in the image below.
Overlap of new signature data array with existing block header
Because of these changes, the record offset now overlaps the location of the original bytes for sector #12. Sector #12 is the one whose signature now overlaps one of the CLFS_CLIENT_CONTEXT fields due to the changes made in step 2.
Overlap of CLFS_CLIENT_CONTEXT->fAttributes field with signature for sector #12
This CLFS_CLIENT_CONTEXT field, which now overlaps the sector #12 signature, is called fAttributes. As mentioned in the part about CLFS internals, the fAttributes field contains FILE_ATTRIBUTE flags associated with the BLF file.
Because of these patches made to the BLF file, the RecordOffsets[0] and fAttributes fields are now connected by the signature of sector #12, and this is what it leads to:
- When opening a BLF file, the ClfsDecodeBlock function will copy the original bytes from CLFS_LOG_BLOCK_HEADER->RecordOffsets[0] to the position of the sector #12 signature (which is also CLFS_CLIENT_CONTEXT->fAttributes).
- To trigger the vulnerability, the exploit calls the SetLogArchiveMode function with a mode parameter equal to CLFS_LOG_ARCHIVE_MODE::ClfsLogArchiveEnabled.
- The driver will call the SetLogFileInfo and FlushMetadata
- CLFS_CLIENT_CONTEXT->fAttributes will be set equal to FILE_ATTRIBUTE_ARCHIVE (0x20), and so it will also change the original bytes where the sector #12 signature should be.
- FlushMetadata will also call the WriteMetadataBlock/ClfsEncodeBlock functions to encode the blocks and then write the changes to disk.
- ClfsEncodeBlock will copy the updated original bytes from the position of the sector #12 signature to where it should be stored, overwriting CLFS_LOG_BLOCK_HEADER->RecordOffsets[0].
- From now on, instead of a legitimate record, a “fake” malicious record will be used.
The pointer to the CClfsContainer class in the malicious CLFS_CONTAINER_CONTEXT structure, assigned to the “fake” malicious entry, has a preset value of 0x5000000. As a result, further exploitation is almost identical to the first exploit.
Use the following link to read the next part: