# Arbitrary File Download as Shopmanager

WooCommerce only validates download file extensions for relative paths, so a shop manager can set a download to //path/wp-config.php and download arbitrary server files.

- Payout: hidden
- Severity: high
- Program: Automattic
- Found by: simonscannell
- Disclosed: 2019-12-19
- Write-up quality: 7/10
- Original: https://hackerone.com/reports/402473
- Library page: https://bugbountylibrary.com/r/h1%3A402473
- Tags: area:web domain:web impact:data-leak impact:privesc kind:bounty platform:hackerone sev:high tech:php technique:source-review vuln:access-control vuln:path-traversal

**Target:** WooCommerce downloadable product file handler (abstract-wc-product.php)
**Root cause:** is_allowed_filetype() returns true unconditionally when get_type_of_file_path() is not 'relative'; a path starting with '//' is classified 'absolute', skipping extension validation.
**Steps:**
1. As shop manager, edit a downloadable product and set the download file to `//home/simon/html/wordpress/wp-config.php`
2. set_downloads() calls is_allowed_filetype(), which sees an 'absolute' path and skips the extension check
3. file_exists() passes since the absolute path exists
4. Download the product file to retrieve wp-config.php contents
**How found:** Reading set_downloads() and is_allowed_filetype(), noticed extension validation only applies to relative paths; hypothesized an absolute path bypasses the check, then confirmed get_type_of_file_path() treats '//'-prefixed input as absolute.
**Exploitation:** Shop manager sets an absolute path (prefixed with //) as a downloadable product file, bypassing extension validation, then downloads the file through the normal product download flow to read wp-config.php and extract DB credentials.
**Escalation:** wp-config.php DB credentials enable database login (non-localhost DB) or, on shared hosting, obtaining space on the same server to reach the DB, leading to full WordPress compromise.
**Insight:** When a validator branches on path type (URL/absolute/relative), test each branch for skipped checks; a leading '//' is often classified as absolute while still resolving to a local filesystem path.

