Some months ago, while analyzing a client’s web application, I came across a file conversion feature that transformed documents in any format into PDF and published them on the company’s SharePoint through a convenient graphical interface.
This functionality, managed by the client’s internal application, had an issue that allowed reading local system files when converting HTML documents to PDF. Obviously, I reported this problem as a high-impact finding, complete with PoC and evidence. During the final presentation call with the client, the project lead thanked me for identifying the issue and candidly informed me that the web.config file shown in the screenshots I had provided was not from one of their systems, as they were only using a wrapper of the official Microsoft’s APIs, and he suggested to report the bug directly to Microsoft
After finishing the call, I rushed into our Microsoft 365 SharePoint instance to figure out how to trigger and replicate the issue. I then spent my Friday night submitting the bug to MSRC, and 4 months later I have been rewarded with a $3000 bounty for this issue (Severity: Important ) ! Hereafter, the details of the finding that now has been (obviously) remediated by Microsoft.
The Microsoft Graph APIs allowed users to download uploaded files in a variety of formats. Specifically, as stated in the official documentation under the Format options section, it was possible to convert Microsoft Office files to PDF, or other formats to HTML. The desired output format was specified via the format
HTTP parameter.
The officially supported formats for PDF conversion included: csv, doc, docx, odp, ods, odt, pot, potm, potx, pps, ppsx, ppsxm, ppt, pptm, pptx, rtf, xls, and xlsx. However, it turned out there was an undocumented behavior that allowed converting from HTML to PDF files.
In addition, by embedding specific tags (<embed>, <object>, and <iframe>) into the HTML content, an attacker could force the inclusion of local files from the server’s file system into the resulting PDF—even files located outside the server’s root directory.
This effectively opened the door to a Local File Inclusion (LFI) attack during the conversion process. An attacker exploiting this behavior could have accessed sensitive server-side data—such as Microsoft secrets, database credentials, or potentially application’s source code. However, I have only been able to read some common files, such as web.config, win.ini, and a few others. I could speculate that in certain edge cases, if an attacker managed to guess or discover the path to temporary files handled by the application, there was even the potential for cross-tenant data exposure in multi-tenant environments.
Once the vulnerability was discovered, exploitation was quite easy as you can see in the following steps:
- Upload of the malicious HTML file via the graph API:
2. Request the file in PDF format:
3. The file can be dowloaded with the requested local resource included using the URL provided in the server response:
I hope you enjoyed this short article! Cheers 🥂 🤑