T05 · Unauthorized Access and Privilege Escalation
- Location
scripts/publish_article.py:459- Finding
Arbitrary Local File Upload Through Unrestricted Image Paths
- Content
View full analysis
]*src=["\']([^"\']+)["\'][^>]*>' matches = re.findall(img_pattern, content, re.IGNORECASE) uploaded_images = {} processed_content = content image_counter = 1 for src in matches: is_url = src.startswith(('http://', 'https://')) temp_path = None try: if is_url: print(f" [{image_counter}] {src[:60]}... - External URL, downloading...") temp_path = await self._download_url_to_temp(src) image_path = temp_path display_name = src.split('/')[-1].split('?')[0] or f'url_image_{image_counter}' else: if os.path.isabs(src): image_path = src else: image_path = os.path.join(base_dir, src) display_name = os.path.basename(src) result = await self.upload_image(image_path, is_thumb=False) ``` ### Technical Analysis The script extracts image paths directly from article HTML and uses them as local filesystem paths. Absolute paths are explicitly accepted, while relative paths are joined to `base_dir` without canonicalization or containment validation. Consequently, traversal sequences such as `../` can escape the intended content directory. The later extension check only verifies the filename suffix and does not establish that the caller is authorized to read or upload the file. Any readable local file with an accepted image extension can therefore be transmitted to the configured API endpoint. ### Attack Path 1. An attacker supplies or influences Markdown or HTML article content. 2. The content includes an image such as: ```html
```
An absolute path can also be used.
3. `process_content_images()` joins the path to `base_dir` or accepts it directly.
...[truncated 646 chars]- Remediation
View remediation
