今年在 AIS3 2023 研究了一些與 PHP HTML to PDF 相關的 library 的漏洞,主要是找到可觸發反序列化的點。透過研究過去已經修復好的洞,我們透過繞過他的 patch,讓 1day 再次變為 Github CVSS 9.8 的 0day,回報給作者後也完成修補,也順便在路上撿到一個有趣的 DoS 的洞。
對於今年我在這場專題做到最重要的事,就是帶著我沒有任何白箱經驗的隊友們,一起來 code review,透過一些指導,讓他們有了白箱的能力,找到了 0day。這是我自去年 AIS3 以來一直想做的事,拿到最佳專題及一些 0day 就是這次計畫成功的證明。
專題
之後有空的時候來寫,先放上簡報 。
後續
在 AIS3 2023 結束後,我把我們繞過 CVE-2023-28115 的 patch 的漏洞報告寄給了作者,在一個多月後取得了回信。
大約兩天後,他們修復 了這個洞,發布了 security advisory ,漏洞編號 CVE-2023-41330,Github CVSS 9.8。
他的修補方式與我建議的相同,對於使用者提供的 $filename
的 scheme,採用白名單機制過濾而非原先的黑名單機制,這樣可讓攻擊者受到很大的限制。然而這樣修卻衍生出了新的問題 。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| protected function prepareOutput($filename, $overwrite) { if (false === $parsedFilename = \parse_url($filename)) { throw new InvalidArgumentException('The output filename is invalid.'); }
$scheme = isset($parsedFilename['scheme']) ? \mb_strtolower($parsedFilename['scheme']) : ''; if ($scheme !== '' && $scheme !== 'file') { throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected \'\' or \'file\' but got \'%s\'.', $scheme)); } if ($this->fileExists($filename)) { } }
|
修補後的問題
因為修補的方式採用白名單,連正常的使用也受到影響,他們現在只允許 scheme 是 file
或 空,採用判斷 scheme 是使用 PHP 的 parse_url
,但在 Windows 底下的 drive-letter 也會被認定 scheme,所以也會被擋下來。
1 2 3 4 5
| > parse_url('c:\your\path\...') = [ "scheme" => "c", "path" => "\your\path\...", ]
|
過了幾天之後,作者放上了這個問題的修補 。在作業系統是 Windows 的情況下,一個 ascii_letter 的 scheme 且檔名符合 WINDOWS_LOCAL_FILENAME_REGEX
也會被白名單允許。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| abstract class AbstractGenerator implements GeneratorInterface, LoggerAwareInterface { use LoggerAwareTrait; protected const ALLOWED_PROTOCOLS = ['file'];
protected const WINDOWS_LOCAL_FILENAME_REGEX = '/^[a-z]:(?:[\\\\\/]?(?:[\w\s!#()-]+|[\.]{1,2})+)*[\\\\\/]?/i'; protected function prepareOutput($filename, $overwrite) { if (!$this->isProtocolAllowed($filename)) { throw new InvalidArgumentException(\sprintf('The output file scheme is not supported. Expected one of [\'%s\'].', \implode('\', \'', self::ALLOWED_PROTOCOLS))); } protected function isProtocolAllowed($filename) { if (false === $parsedFilename = \parse_url($filename)) { throw new InvalidArgumentException('The filename is not valid.'); }
$protocol = isset($parsedFilename['scheme']) ? \mb_strtolower($parsedFilename['scheme']) : 'file';
if ( \PHP_OS_FAMILY === 'Windows' && \strlen($protocol) === 1 && \preg_match(self::WINDOWS_LOCAL_FILENAME_REGEX, $filename) ) { $protocol = 'file'; }
return \in_array($protocol, self::ALLOWED_PROTOCOLS, true); } }
|
Timeline
2023/08/03: 回報漏洞給作者。
2023/09/05: 作者回信說正在 working on it。
2023/09/06: 釋出 v1.4.3 ,修補好這個漏洞。
2023/09/13: 釋出 v1.4.4 ,修好修補漏洞造成 Windows drive-letter 無法正常使用的問題。