[BRLY-2022-009] The arbitrary write vulnerability leads to arbitrary code execution during PEI phase on Intel platform.
Summary
BINARLY efiXplorer team has discovered a arbitrary write vulnerability on Intel platforms allowing a possible attacker to execute arbitrary code during PEI phase.
Vulnerability Information
- BINARLY internal vulnerability identifier: BRLY-2022-009
- Intel PSIRT assigned CVE identifier: CVE-2022-36372
- AMI PSIRT assigned CVE identifier: CVE-2022-40262
- CERT/CC assigned case number: VU#158026
- FwHunt rule: BRLY-2022-009
- CVSS v3.1: 8.2 High AV:L/AC:L/PR:H/UI:N/S:C/C:H/I:H/A:H
Affected Intel firmwares with confirmed impact by Binarly team
Device/Firmware | File Name | SHA256 (File PE32 section) | File GUID |
---|---|---|---|
Intel Server Board M10JNP2SB | S3Resume2Pei | 7bb29f05534a8a1e010443213451425098faebd45948a4642db969b19d0253fc | 89E549B0-7CFE-449D-9BA3-10D8B2312D71 |
Potential impact
A potential attacker can execute an arbitrary code at the time of the PEI phase and influence the subsequent boot stages. This can lead to the mitigasions bypassing, physical memory contents disclosure, discovery of any secrets from any Virtual Machines (VMs) and bypassing memory isolation and confidential computing boundaries. Additionally, an attacker can build a payload which can be injected into the SMRAM memory.
Vulnerability description
The pseudocode for vulnerable function is shown below:
int sub_FFEBFB2C()
{
// [COLLAPSED LOCAL DECLARATIONS. PRESS KEYPAD CTRL-"+" TO EXPAND]
DataSize = 4;
S3PerformanceTablePointer = 0;
Status = sub_FFEC0607(&EFI_PEI_READ_ONLY_VARIABLE2_PPI_GUID, &This);
if ( Status >= 0 )
{
Status = This->GetVariable(
This,
L"FPDT_Variable_NV",
&AMI_GLOBAL_VARIABLE_GUID,
0,
&DataSize,
&S3PerformanceTablePointer);
if ( Status >= 0 )
{
Status = S3PerformanceTablePointer;
// Extracted from memory pointed by FPDT_Variable_NV variable value
AcpiS3PerformanceTable = S3PerformanceTablePointer->AcpiS3PerformanceTable;
if ( *S3PerformanceTablePointer->AcpiS3PerformanceTable == 'TP3S' )
{
if ( *&S3PerformanceTablePointer->ResumeCount )
{
if ( !AcpiS3PerformanceTable->S3Resume.Header.Type )
{
S3ResumeTotal = MultU64x32(__rdtsc(), *&S3PerformanceTablePointer->ResumeCount);
LODWORD(v3) = S3ResumeTotal;
HIDWORD(v3) = HIDWORD(S3ResumeTotal) % 0xF4240;
FullResumeLo = v3 / 0xF4240;
FullResumeHi = HIDWORD(S3ResumeTotal) / 0xF4240;
v6 = __PAIR64__(HIDWORD(S3ResumeTotal) / 0xF4240, FullResumeLo)
+ AcpiS3PerformanceTable->S3Resume.AverageResume * AcpiS3PerformanceTable->S3Resume.ResumeCount;
ResumeCount = AcpiS3PerformanceTable->S3Resume.ResumeCount + 1;
LODWORD(v3) = v6;
HIDWORD(v3) = HIDWORD(v6) % ResumeCount;
Status = v3 / ResumeCount;
AcpiS3PerformanceTable->S3Resume.ResumeCount = ResumeCount;
LODWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = Status;
HIDWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = HIDWORD(v6) / ResumeCount;
LODWORD(AcpiS3PerformanceTable->S3Resume.FullResume) = FullResumeLo;
HIDWORD(AcpiS3PerformanceTable->S3Resume.FullResume) = FullResumeHi;
}
}
}
}
}
return Status;
}
The AcpiS3PerformanceTable
pointer is controlled by the attacker:
S3PerformanceTablePointer
value is occured from value ofFPDT_Variable_NV
NVRAM variableAcpiS3PerformanceTable = S3PerformanceTablePointer->AcpiS3PerformanceTable
(extracted from memory pointed by FPDT_Variable_NV variable value)
Thus the memory pointed to by AcpiS3PerformanceTable
can be overwritten with predictable values:
AcpiS3PerformanceTable->S3Resume.ResumeCount = ResumeCount;
LODWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = Status;
HIDWORD(AcpiS3PerformanceTable->S3Resume.AverageResume) = HIDWORD(v6) / ResumeCount;
LODWORD(AcpiS3PerformanceTable->S3Resume.FullResume) = FullResumeLo;
HIDWORD(AcpiS3PerformanceTable->S3Resume.FullResume) = FullResumeHi;
This can lead to arbitrary write during the PEI stage.
The primitive described above allows to perform privilege escalation from the PEI to the DXE/SMM phase (or from PEI to the SMM during S3 sleep/wake up circle). In turn, code execution in PEI allows the disable security features that are initialized at the PEI-DXE junction (like PPAM or Intel BIOS Guard).
Disclosure timeline
This bug is subject to a 90 day disclosure deadline. After 90 days elapsed or a patch has been made broadly available (whichever is earlier), the bug report will become visible to the public.
Disclosure Activity | Date |
---|---|
Intel PSIRT is notified | 2022-03-22 |
Intel PSIRT confirmed reported issue | 2022-07-28 |
Intel PSIRT assigned CVE number | 2022-07-28 |
BINARLY public disclosure date | 2022-08-10 |
Acknowledgements
BINARLY efiXplorer team