ImageId Format Injection in Image Upload Endpoint
Medium
L
Lichess
Submitted None
Actions:
Reported by
oblivionsage
Vulnerability Details
Technical details and impact analysis
# Summary
Hello Again Lichess Team,
I found an input validation issue in the image upload endpoint that lets me inject special characters into the `rel` parameter. This breaks the expected ImageId format that the application uses to identify uploaded images. While testing upload functionality, I noticed that colon characters aren't properly sanitized, which could cause parsing issues in other parts of the application
# Description
The `/upload/image/user/{rel}` endpoint doesn't validate the `rel` parameter properly. This parameter gets combined with random strings to create an ImageId that should follow a specific format: `{rel}:{random12}:{random8}.{extension}`
The issue is that the application accepts colon characters in the `rel` parameter without sanitization. This happens because the validation only checks for MongoDB injection patterns (like `$ne`) but misses format-breaking characters
Looking at the code in `modules/memo/src/main/Picfit.scala`:
```bash
val image = PicfitImage(
id = ImageId(s"$rel:${ThreadLocalRandom.nextString(8)}.$extension"),
// rel parameter used directly without validation
rel = rel,
// ...
)
```
So when I inject colons, instead of getting the expected 3-part format, I get multiple parts that could break parsing logic elsewhere
# Steps to Reproduce
1. Login to Lichess and grab your session cookie
2. Create a small test image file (test.png)
```bash
# Create a small test image (1x1 pixel PNG)
echo -e '\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x02\x00\x00\x00\x90wS\xde\x00\x00\x00\x0cIDATx\x9cc\xf8\x00\x00\x00\x01\x00\x01\x00\x00\x00\x00\x16\x1d\xb3\x00\x00\x00\x00IEND\xaeB`\x82' > test.png
```
3. Send this request:
```bash
curl -X POST "https://lichess.org/upload/image/user/test:evil:format:break" \
-b "lila2=YOUR_SESSION_COOKIE" \
-H "Origin: https://lichess.org" \
-H "Referer: https://lichess.org/" \
-F "[email protected]"
```
**Expected Result**: The application should reject the request or sanitize the colons
**Actual Result**: The request succeeds and returns:
Normal Request :
{F4409970}
{F4409974}
Actual Request with inject :
{F4409975}
{F4409976}
```bash
{"imageUrl":"https://image.lichess1.org/display?...&path=test:evil:format:break:ePU9oRLnNvCz:iFZRITKQ.png&..."}
```
Notice how the ImageId now has 6 parts instead of the expected 3: `test:evil:format:break:ePU9oRLnNvCz:iFZRITKQ.png`
https://cwe.mitre.org/data/definitions/20.html
# Mitigation
To fix this, you should sanitize the `rel` parameter in the image upload handler. Something like:
```bash
// Validate rel parameter format
val sanitizedRel = rel.replaceAll("[^a-zA-Z0-9_-]", "_")
```
Or add validation in the `uploadSource` method in `PicfitApi.scala` to reject `rel` values containing colons or other format-breaking characters.Also consider documenting the expected ImageId format since the current code assumes a specific structure that could break if the format changes.
## Impact
An attacker could potentially cause issues in other parts of the application that expect ImageIds to follow the standard 3-part format. I noticed there's regex parsing logic in `findInMarkdown` that might not handle malformed ImageIds correctly .This could cause issues in logging, image lookup, or markdown parsing where the format of imageId is implicitly assumed. In production environments with chained handlers or analytics relying on this structure, this might lead to edge-case bugs or silent failures
However, I couldn't demonstrate concrete security impact beyond breaking the data format. The images still upload successfully and get stored properly
Thank you for your time and reviewing my report
Report Details
Additional information and metadata
State
Closed
Substate
Resolved
Submitted
Weakness
Improper Input Validation