对内网爆破的一些思考

admin 2023年2月12日11:45:04评论169 views字数 3215阅读10分43秒阅读模式

前言

众所周知,密码复用是内网大杀器之一,但在实际渗透过程中,对账号密码搜集是一个持续性的工作,所以拿这些账号密码去检测复用情况成为一个重复性的劳动,之前一直想写个工具解决这个问题,刚好这段时间有空就完成了。

其实思路很简单,通过监控配置文件来自动化去进行复用检测。而在工具语言上我选择了go,跨平台很不错,并且有不少的代码可以学习借鉴,例如fscan、x-crack、LadonGo等等。

当然实际上应用要考虑的情况不少,并且出于对市面上爆破工具的不称心,又加入了一些自己的想法,例如对同目标同协议的延时、防止重复任务等等情况,再加上测试,所以耗了一段时间。并且其中也遇到了不少问题,这里仅做记录和学习。

MongoDB的检测问题

对于MongoDB 数据库可以进行未授权的检测、以及账号密码的爆破。

在启动MongoDB的时候,如果没有加auth参数,那么是存在未授权的。

3.0之前版本的MongoDB,默认监听在0.0.0.0,3.0及之后版本默认监听在127.0.0.1。

3.0之前版本,如未添加用户管理员账号及数据库账号,使用--auth参数启动时,在本地通过127.0.0.1仍可无需账号密码登陆访问数据库,远程访问则提示需认证;

3.0及之后版本,使用--auth参数启动后,无账号则本地和远程均无任何数据库访问权限。

但是当我使用最新的Mongo 6的时候,无法使用fscan的POC检测到它的未授权,但是对Mongo 5是可以的。

而在fscan的POC中可见,它的检测方法是通过直接发送指令字节给mongodb的

对内网爆破的一些思考

查看Mongo6 的返回的信息发现:

  �                         �   ok         errmsg �   Unsupported OP_QUERY command: getLog. The client driver may require an upgrade. For more details see https://dochub.mongodb.org/core/legacy-opcode-removal code codeName
UnsupportedOpQueryCommand

出现这种问题一般是驱动版本太低,导致的错误。使用"gopkg.in/mgo.v2"的ladon也没办法适应最新的mongo6。

最后的解决方法是使用了官方的驱动"go.mongodb.org/mongo-driver/mongo",可以检测大部分mongo的未授权与爆破。相关代码如下:

对内网爆破的一些思考

爆破的逻辑其实差不多。

另外就是踩坑了,在mongo的连接字符串中,特殊符号需要转义,否则会报错。

需要转义的符号如下:

  {"!""%21",
  "@""%40",
  "#""%23",
  "$""%24",
  "^""%5e",
  "&""%26",
  "*""%2a",
  "%""%25",
  "(""%28",
  ")""%29",
  "_""%5f",
  "+""%2b",
  "=""%3d",
  }

可以使用url.QueryEscape函数直接转义。

winrm

在第一版完成常见协议ssh,rdp,smb,ftp,redis,mgo,mysql,mssql,oracle,vnc,ela,psql的爆破插件后,我准备添加一些其他协议。

首先研究了一下winrm,本来以为有github.com/masterzen/winrm库,应该会很简单,很快就能写好了,顺便写个go版的evil-winrm应该也不难。结果现实是很快就被打脸了。

根据官方文档,很快写出一个爆破函数,关键代码如下:

对内网爆破的一些思考很简单的代码,但是在测试的时候失败了(server2016,默认状态的winrm服务)。返回状态码是401未认证。

http response error: 401 - invalid content type  

而当我使用evil-winrm的时候,却十分顺利地连接上去了,并且使用windows自带地winrm与winrs也十分正常。就偏偏使用这个包的时候连接不上。

于是开始了漫长的排错之旅,在经过测试分析后,发现只要将服务器winrm的service的AllowUnencrypted设置"true",使用该包就可以连接上目标了。

winrm set winrm/config/service @{AllowUnencrypted="true"}

而它其实在默认的服务器上是false,其实从这个参数的作用来看,它的作用是不允许未加密的连接。但由于知道winrm其实是通过http协议传输数据,所以一开始难以理解这里的加密是怎么个意思,5986的https倒是加密了,但是默认是不开启的。

于是抓包看了一下,这是winrs的数据包:

对内网爆破的一些思考这是go的winrm发出的数据包:

对内网爆破的一些思考在不断对比二者的区别中,排除了许多的错误答案,比如一开始以为是ntlm的sign标志符导致的认证失败等等。在最后终于发现其实是固有思路限制了我,它的意思还真是对http的加密——在翻阅pywinrm的时候找到了答案。

在ms-wsmv协议文档中2.2.9.1.1NegotiateEncryptedMessage 一节中指出,在使用简单且受保护的GSS-API协商(SPNEGO)时可以使用此消息来对上下文进行加密。

对内网爆破的一些思考这里来看一个winrs发出加密连接:

对内网爆破的一些思考根据文档,他的Content-Type必须为

multipart/encrypted;protocol="application/HTTP-SPNEGO-session-encrypted";boundary="Encrypted Boundary"

(话说这种winrm的应该流量设备都有规则吧,太容易检测了),其他的字段也是符合该扩展格式的。

对内网爆破的一些思考

再来看通过masterzen/winrm包发出的数据包:

对内网爆破的一些思考

可见并没有进行加密。

所以现在已经找到了问题所在。

无论是winrm、winrs这类系统自带的应用,还是使用ruby编写的evil-winrm,使用python编写的pywinrm。对5985的winrm都实现了 Negotiate/SPNEGOKerberosCredSSP的加密上下文。这种加密说的更简单一些,其实就是将原来的内容加密后又封装成了http消息。

masterzen/winrm并没有实现该扩展消息,也就是说以该库为基础的winrm爆破基本没啥意义,总不能指望非默认配置吧。以

multipart/encrypted;protocol="application/HTTP-SPNEGO-session-encrypted";boundary="Encrypted Boundary"

为关键字在github搜索,发现go的话只有一个库https://github.com/bodgit/ntlmssp 貌似实现了该消息,但是经过测试该库并不好用,也并没有成功。各位大佬们可以试试,或许是我姿势不对。

对内网爆破的一些思考

所以到了这里,真实原因找到,解决方法也可以想到:

  • 于研究学习、追求完美的角度,可以自己实现改造一下原来的winrm,加入加密消息的扩展。


  • 调用winrs去爆破,简单粗暴,仅限在windows平台。


后续的话,暂且会使用winrs解决,前者有趣,但从做过相关工作,可能比较费时间,所以会有时间再去做。

总结:早点抓包、早点看文档早找到问题。

参考资料

  1. MongoDB未授权访问漏洞分析及整改建议
  2. https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-wsmv/055dc36b-db2a-41ae-a47b-82cbfa0b4a92


原文始发于微信公众号(无界信安):对内网爆破的一些思考

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年2月12日11:45:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   对内网爆破的一些思考http://cn-sec.com/archives/1549718.html

发表评论

匿名网友 填写信息