Windows 客户端渗透测试
目录
- 目录
- 1 客户端信息收集
- 2 客户端常见漏洞
- 2.1 信息泄露
- 2.2 程序加固
- 2.3 不安全的组件
- 2.4 缓冲区溢出
- 2.5 IFEO 注入
- 2.6 进程注入
- 2.7 符号链接攻击
- 2.8 EXE 劫持
- 2.9 COM 劫持
- 2.10 DLL 劫持
- 2.11 安全配置
- 2.12 Weak Named Pipe
- 3 客户端常见框架测试
- 3.1 .NET
- 3.2 Electron
- 静态分析-解包审计入口 JS
- 静态分析-搜索关键字找敏感信息
- 动态分析-调试主进程
- 动态分析-开发者工具
- 动态分析-收集其他信息
- 漏洞利用-RCE 利用链
- 案例分析-某多媒体教室控制系统
- 案例分析-蚁剑 RCE⚒️
- 防御
- 3.3 CEF
- 3.4 PowerBuilder⚒️
- 参考链接
1 客户端信息收集
通过 DIE 查壳和开发技术
Process Monitor(ProcMon) 监控应用的所有操作
Process Hacker 查看进程和命令行参数
regshot,注册表备份工具,可以用来对比两次备份的区别,导出不同的部分,看看应用改了那些注册表。
directory monitor 实时监控客户端对文件的更改。
IDA 静态分享
OD 动态调试
https://learn.microsoft.com/en-us/sysinternals/downloads/strings 字符串搜索
1.1 架构&语言&框架
https://en.wikipedia.org/wiki/Thin_client
https://en.wikipedia.org/wiki/Thin_client
软件架构:
CS 架构
BS 架构
客户端架构:
两层 :客户端 -> 数据库
三层:客户端 -> Server -> 数据库
顺带就了解了是什么语言开发,或者用的什么框架。
1.2 服务
1.3 注册表
Custom Protocol
Custom Protocol 也有叫它伪协议,通过这种方式在浏览器或者其他运行程序的地方唤醒 App,在启用应用的时候传递参数。
custom://121/12312
搜索 registerFileProtocol 或 setAsDefaultProtocolClient 方法。
如果 Electron 有 Mac 版本可以搜索 CFBundleURLSchemes 找注册的 Schema。
pseudo-protocals-digger 可以枚举出注册表
HKEY_CLASSES_ROOT 中注册的伪协议。
但它是 Python2 编写的,适配 Python3 有几处需要修改,一是 _winreg 模块在 Python3 中叫 winreg,二是 print 方法需要加上圆括号。
import winreg as _winreg
def enum_all_subkey() :
root_key=_winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,'')
key_index=0
return_key_list=[]
try :
while True :
key_name=_winreg.EnumKey(root_key,key_index)
key_index+=1
return_key_list.append(key_name)
except :
pass
return return_key_list
def is_pseudo_protocal_key(input_key_name) :
key=None
try :
key=_winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,input_key_name)
except : # Cannot Open This Key ..
return False
key_index=0
value_index=0
exist_value=False
exist_key=False
try :
while True :
value_name,value_value,value_type=_winreg.EnumValue(key,value_index)
value_index+=1
if 'URL Protocol'==value_name :
exist_value=True
except :
pass
try :
while True :
key_name=_winreg.EnumKey(key,key_index)
key_index+=1
if 'shell'==key_name :
try :
pseudo_protocal_command=_winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,input_key_name+'\\shell\\open\\command')
exist_key=True
except :
pass
except :
pass
if exist_value and exist_key :
return True
return False
def get_pseudo_protocal_shell(key_name) :
pseudo_protocal_command_key=_winreg.OpenKey(_winreg.HKEY_CLASSES_ROOT,key_name+'\\shell\\open\\command')
try :
value_name,value_value,value_type=_winreg.EnumValue(pseudo_protocal_command_key,0)
return value_value
except :
return '<except>'
if __name__=='__main__' :
for subkey_index in enum_all_subkey() :
if is_pseudo_protocal_key(subkey_index) :
print(subkey_index)
print(' Path:',get_pseudo_protocal_shell(subkey_index))
'''
# Test Case ..
print is_pseudo_protocal_key('asd')
print is_pseudo_protocal_key('tdsp')
print is_pseudo_protocal_key('telnet')
print is_pseudo_protocal_key('Tencent')
'''
1.4 进程
运行获取版本信息。Electron UA 请求头有遇到过携带版本信息,可以观察 window 对象。
获取程序运行参数 Console 输出 console.log(process.argv)
用 ProcessHacker 也能查进程命令行参数
观察控制台打印日志
使用命令行查看有没帮助信息,例如 –help /? 之类的
1.5 网络
网络连接目标和防火墙规则。
文章不要局限在 Electron 也可以介绍其他客户端代理 https://parsiya.net/categories/thick-client-proxying/
最常见的就是 HTTP,也有那种私有协议来传数据,对于其他协议就用 Wireshark 分析,或者 Echo Mirage 拦截 TCP 协议流量。
HTTP 抓包相对简单,应用如果有代理功能那最方便了,直接设置即可,不然就优先使用系统全局代理和 ProxyFier 代理流量。
现在好多客户端里面都是嵌个 Chromium 浏览器,可以在命令行启用应用时加上浏览器 --proxy-server 选项就能加上代理,本质上和启动浏览器一样,这是浏览器启动参数。
--proxy-server=address:port
如果是 Electron 这种 NodeJS 类应用,可以选择直接在入口代码中加全局代理。
const {app} = require('electron');
app.commandLine.appendSwitch('proxy-server', '127.0.0.1:8080');
不然就得设置 NodeJS 代理。
# 设置代理
npm config set proxy http://localhost:8080
npm config set https-proxy http://localhost:8081
# 恢复 NodeJS 代理
npm config rm proxy
npm config rm https-proxy
设置了代理还是抓不到请求?有些客户端必须插硬件 Key,客户端读取 Key 中的证书,输入正确的密码才能登录使用,这说明启用了双向认证,无法抓包。这种情况下要么导出 Key 里面的证书,去 BurpSuite 的 Network -> TLS -> Client TLS certificates 添加证书,不然只能尝试 BurpSuite 导入证书时的选择硬件智能卡功能,这样自动会读取 Key 中的证书。
要实在抓不到包尝试动态调试客户端,找找发请求的位置下断点看请求参数和 URL。
1.6 命名管道
1.7 文件和目录权限
1.8 配置文件
2 客户端常见漏洞
方法论:
https://www.darkrelay.com/challenge-page/thick-client-penetration-testing
https://www.darkrelay.com/post/thick-client-penetration-testing#viewer-4n0pt
https://owasp.org/www-project-desktop-app-security-top-10/
https://www.cyberark.com/resources/threat-research-blog/thick-client-penetration-testing-methodology
2.1 信息泄露
日志
配置文件
硬编码
内存中存在敏感信息。用 ProcessHacker 打开进程信息 Memory 选项卡 Strings 功能。
在 Filter 中支持普通搜索和正则匹配。
如果你用不到这么复杂的搜索功能,Win + Shift + Esc 打开任务管理器右键转储进程内存也行。
注册表中存在敏感信息。
客户端缓存(存在敏感信息)。不是纯文本的可以用 010 Editor 查看、搜索。
客户端凭证。现在很多客户端开发都是用的框架,而框架中就是嵌了浏览器,如果使用的是 Cookie、LocalStorage 这种存储用户信息,就能直接获取到凭证。
2.2 程序加固
动态分析
静态分析
未加壳,或者是混淆代码可以还原
静态分析-反编译
当时用 dnspy 发现方法名和方法体都是混淆的,通过 die 查对应特征用 .NET Reactor 做的保护。
最后通过 .NETReactorSlayer 能够大部分还原出代码。
C-Sharp deobfuscator/deobfuscation de4dot 工具
反混淆工具收集项目 https://github.com/NotPrab/.NET-Deobfuscator
2.3 不安全的组件
2.4 缓冲区溢出
Stack Buffer Overflow
2.5 IFEO 注入
2.6 进程注入
2.7 符号链接攻击
2.8 EXE 劫持
2.9 COM 劫持
2.10 DLL 劫持
在权限维持文章中写过 2.4 DLL Hijacking and Proxying
DLL 劫持。自动化提示有哪些 dll 可能存在劫持 https://github.com/sensepost/rattler/releases/tag/v1.0
2.11 安全配置
https://github.com/trailofbits/winchecksec
签名检测。用 DigitalSignCheck.exe
程序编译安全标志
学习:
https://www.netspi.com/blog/technical/thick-application-penetration-testing/
https://www.darkrelay.com/challenge-page/thick-client-penetration-testing
https://www.darkrelay.com/post/thick-client-penetration-testing
2.11.1 未引用的服务路径
在提权文章中有写过 Unquoted Service Path。
2.12 Weak Named Pipe
https://www.cyberark.com/resources/threat-research-blog/thick-client-penetration-testing-methodology
Weak Graphical User Interface
During our work as pentesters, we might encounter thick client applications that serve numerous users with different privileges. The user interface might include operations for administrators, that have been disabled for low privileged users.
For example, imagine an admin user who logs in to a thick client application with administrative functionalities in his user interface. For a regular user, those functionalities will be disabled, because regular users do not have the appropriate permission for the administrative functionalities.
Therefore, to test for user interface vulnerabilities as a low privileged user, we will need to use various tools to manipulate window objects in Windows, such as:
Buttons
Menu bars
Text boxes
OCX controls
Basically, anything that can be located as a child window and has an active window handle can be manipulated with some predefined attributes.
The following table presents a set of weak GUI control tools that can be used:
Tool Name Description
1 WinSpy++ A tool whose purpose is to help you view and modify the properties of any window in your system with great ease.
2 WinManipulate A simple tool to manipulate window objects in Windows.
3 Windows Enabler A simple tool that lets you activate functions your thick client application has blocked.
3 客户端常见框架测试
3.1 .NET
https://github.com/DarkRelay-Security-Labs/VWA
靶子:https://github.com/srini0x00/dvta
https://github.com/NetSPI/BetaFast
dnspy 直接 patch,或者下断点动态调试,静态反编译看代码。
3.2 Electron
Electron 用 Chromium 和 Node.js 开发跨平台应用——类似相同技术还有 Chromium Embedded Framework(CEF),使用它编写的软件有 VSCode、Typora、AntSword......
拿到一个安装包如何判断它是 Electron 开发的?
- 查看安装目录 resources/ 下有没打包文件 app.asar。
- 查看应用目录有没 LICENSE.electron 等特征文本文件。
静态分析-解包审计入口 JS
app.asar 是 HTML、CSS、JS 打包后的文件,类似于 Linux 下 tar 包。
1.安装 asar 工具
npm install -g asar
如果机器没网,可以下载离线工具使用 https://github.com/aardio/WinAsar
2.解压 app.asar 到指定目录
asar extract app.asar dest-folder
3.打包 app.asar
当改完代码后可以重新打包回来
asar pack <folder> app.asar
解压完成后可以在目录内找到 package.json,这里存着关于应用配置的信息,其中 "mian" 属性是可能是对应 main.js,此文件是 Electron 程序控制入口。
如果没打包恭喜你可以愉快开始审计,如果打包请查看有没 SourceMap。
静态分析-搜索关键字找敏感信息
bash shell 下使用 EdOverflow.txt 里面的关键字搜索 app.asar。
for txt in `cat Desktop/EdOverflow.txt`; do grep -Rin $txt app.asar; done
EdOverflow.txt 内关键字以行分隔。
GITHUB_TOKEN=
PATH=
CODECLIMATE_REPO_TOKEN=
DOCKER_PASSWORD=
NPM_TOKEN=
......
动态分析-调试主进程
https://mp.weixin.qq.com/s/XNcUXz640wKJq0pHIGshgQ
https://www.electronjs.org/zh/docs/latest/api/command-line-switches#--inspecthostport
1.浏览器标签打开 chrome://inspect,配置好端口,默认为 localhost:9229。
2.使用 –-inspect 启动应用 main.exe –-inspect
将自动连接到 localhost:9229,如果不是 9229 可以使用 --inspect=[Port] 指定端口。
3.应用成功连接点 inspect 调用开发者工具,这样下断点分析 JS 没问题,但是没有 NetWork 和 Elements 选项卡,API 支持不全。
一般会有混淆或者通过 WebPack 打包,你可以将 JS 直接拖进浏览器,找到 Sources 直接格式化代码。
动态分析-开发者工具
有时人家已经在代码开启了开发者模式,默认是 F12 开启,Windows 用户直接 Ctrl + Shift + I 启动,MacOS 用户 Option + Command + i。有时应用也会注册自定义快捷键,这种情况需要在 main.js 里搜索 openDevTools
方法看具体按键。
如果就是没开启调试模式,我们还可以直接改代码,在创建窗口后调用窗口对象 openDevTools 方法自动打开,最后重新打包即可。
这里有个技巧,遇到前端静态资源打包的应用,不方便看代码,但是有些关键的方法不会被混淆,我一般都会搜索 loadFile(
,这个方法是加载某些 HTML 作为窗口样式,能够调这个方法的肯定是窗口对象,那么直接在创建窗口的地方添加 windowObject.webContents.openDevTools()
即可。
create: function (e) {
l = new s({
width: 400,
height: 300,
webPreferences: {
nodeIntegration: !0,
enableRemoteModule: !0
},
show: !1
}),
l.loadFile(r.resolve(__dirname, '../../renderer/pages/client/index.html'));
l.webContents.openDevTools(); // 打开开发者工具
},
动态分析-收集其他信息
另外也可以
自动化扫描
https://github.com/doyensec/electronegativity
Electron 错误弹框,需从 Electron import dialog
// 使用前先导入
const { dialog } = require('electron');
// 使用方式1
dialog.showMessageBox({
type:'warning',
title:'随便弹个窗辣',
message:'噢噢',
buttons:'确定'
}), (index) => {
console.log(index);
});
//使用方式2
dialog.showErrorBox('错误', "raingray error msg");
- console.log(process.versions.electron) // electron 版本
- console.log(process.versions.electron) // nodejs 版本
- console.log(process.argv) // 程序运行运行参数
- 使用命令行打开程序看有没日志信息
- 观察开发者工具 Console 日志
漏洞利用-RCE 利用链
测试方法:
https://www.certik.com/resources/blog/technology/vulnerability-electron-based-application-malicious-code-execution
https://remyhax.xyz/posts/only-a-sith-deals-in-absolutes/
Open Redirect
XSS
Custom Protocol
测试 Electron RCE 思路是通过 XSS 调用 Node 执行命令的方法。
直接看创建窗口时 webPreferences 内 nodeIntegration 是不是 true。
usersWindow = new BrowserWindow({
modal: true,
frame: false,
resizable: false,
show: false,
x: locationX,
y: locationY,
width: info.width,
height: info.height,
transparent: false,
webPreferences: {
nativeWindowOpen: true,
nodeIntegration: true // 看这里
}
});
为 true 则 JavaScript 可以使用 require 调 NodeJS 功能。此时重心应该放在寻找 XSS 上,有 XSS 就形成 XSS 到 RCE 的效果。
RCE Payload:
require('child_process').exec('calc');
require('electron').shell.openExternal('file:C:/Windows/System32/calc.exe')
可以通过 XSS 调 require。
<img src=# onerror="require('child_process').exec('calc')">
任意文件读取
检查 contextIsolation
案例分析-某多媒体教室控制系统
一个 Electron 编写的教师端和学生端,用来上课用,其中教师对所有学生发送消息的功能,学生不能发消息,下面是 Electron 渲染的前端页面。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>聊天</title>
<style>
</style>
<script src="./massText.js"></script>
<link rel="stylesheet" href="./massText.css">
<style>
html,
body {
height: 100%;
width: 100%;
margin: 0;
}
</style>
</head>
<body>
<div class="massTextBox">
<div class="massTextBar">
<span class='massTextTitle'>聊天</span>
<!-- <img onClick={this.endMassTextModal} width={16} alt="" src={require('../image/X.png').default} style=" cursor: 'pointer' "></img> -->
</div>
<div class="massTextMessage" id="contentBox"></div>
</div>
</body>
</html>
massText.js
let { ipcRenderer } = require('electron')
ipcRenderer.on('masstext', (events, data) => {
console.log('data====>', data);
let newDom = document.createElement('div')
newDom.innerHTML = `
<div class='masterMessageBox'>
<div class="masterIcon">
<span style=" font-size: 12px;font-weight: 500;color: #666; display: block; text-align: center ">教师</span>
</div>
<div class="messageBox">
<div class="messageTitle">
<span class="titleText">计算机名称${data.hostName}</span>
<span class="titleText" style=" margin-left: 20px ">IP${data.IP} </span>
<span class="titleText" style=" margin-left: 20px ">${data.time}</span>
</div>
<div class="messageContent">
<span>${data.text}</span>
</div>
</div>
</div>
`
document.getElementById('contentBox').appendChild(newDom);
let newDomBottom = document.createElement('div')
//滑动至最低端
document.getElementById('contentBox').removeChild(document.getElementById('msg_end'))
newDomBottom.innerHTML = '<div id="msg_end" style="height: 0;overflow: hidden"></div>'
document.getElementById('contentBox').appendChild(newDomBottom);
let msg_end = document.getElementById('msg_end')
msg_end.scrollIntoView();
})
可以看到学生端 massText.js 创建了 div 标签,用模板字符串替换内容 <span>${data.text}</span>
innerHTML 写入消息,最后 append 到页面上。
典型的 DOM XSS,这里直接调计算器。
<img src=# onerror="require('electron').shell.openExternal('file:C:/Windows/System32/calc.exe')">
虽然可以执行命令,但是不可能直接走到教师端电脑上输入。测试过程中发现可以同时运行多个教师端,它们都能对学生端群发消息,因此可以伪装成教师端控制所有机器。
案例分析-蚁剑 RCE⚒️
防御
- 有时候 nodeIntegration 必须要用,那么只能结合前端框架语法避免 XSS。
- 在应用上需要将代码打包,增加代码阅读难度,防止代码被审计。
3.3 CEF
cef 可以原生使用,也可以用一些包装过后的,如 cefSharp。
开启开发者工具
方便调试
尝试反编译
在项目中经常遇到用 .NET 编写的 CEF 应用。
动态分析-JS 调用客户端方法
确认客户端开发技术,寻找 RCE 利用思路。
可以通过开发者工具来获得 CEF 绑定的 JS 对象,通过 JS 对象能调客户端的功能。结合 dnspy 动态调试客户端,找找有没敏感内容。另外要专注客户端的反序列化功能,看看使用时有没配置问题,可能造成反序列化漏洞。
CEF RCE
- https://github.com/adobe/brackets/issues/14149
- https://book.hacktricks.xyz/linux-unix/privilege-escalation/electron-cef-chromium-debugger-abuse
- https://blog.chromium.org/2011/05/remote-debugging-with-chrome-developer.html,远程调试
- https://chromedevtools.github.io/devtools-protocol/,远程调试 HTTP EndPoint 官方文档
- https://embracethered.com/blog/posts/2020/chrome-spy-remote-control/,远程调试利用
遇到监听 --remote-debugging-port
首先看又没办法 RCE。
其次尝试通过审计客户端 JS 来获取敏感信息。
再透过 chrome://inspect/#devices
链接到调试端口开始获取敏感信息。
3.4 PowerBuilder⚒️
参考:某某发行项目买回
确认 PowerBuilder 创建的应用是哪个版本编译的。
- 用文本编辑器打开 exe 应用,搜索 PBVM,确认其 dll 版本
- 去网上搜此 dll 对应版本,如 PBVM100.dll 就是 PB 10 构建的。
- 或者你直接编辑器打开 PBVM100.dll 搜索看能不能得到 PB 版本。
- 搜 PBVM100.dll PowerBuilder runtime files 找官方文档也可以。根据观察 pbvm.dll 是 2022 年的,PBVM105.DLL 是 PowerBuilder 10.5 版本,pbvm190.dll 是 2019 版本,pbvm170.dll 是 pb2017r2,pbvm90.dll 是 powerbuilder09,pbvm100.dll 是 PB10。
参考连接:https://answers.sap.com/questions/12113487/how-to-determine-the-version-of-powerbuilder-which.html
PowerBuilder 目录文件后缀都是什么意思?
- pbl,源码;
- pbd,编译后的代码;
- pbw,WorkSpace;
- pbx,
pb使用记录 关于pbl、pbt、pbr、pbd
最近使用pb修改程序,遇到一些基础问题,之前有过了解但是几年没有碰过PB有些忘了,简单记录一下。
关于pbl、pbt、pbr、pbd
pbt (powerbuilder target)是8以后的版本引入的东西,文件中自记录着该程序的工作空间所包含的pbl,相当于pbl目录。当点击
pbw (powerbuilder workspace)文件时,pbw就读取当前目录下pbt中的LibList目录加载pbl文件。在PB中选择打开workspace也是一样的道理。没有pbt时,可以打开pbw,但是workspace下是空白。
pbd是pbl编译后(Build runtime library)的文件。当把程序生成执行文件(exe)后,执行文件就调用pbd文件中的伪代码进行操作。
pbl是源代码,源代码是人写的,给人看的。伪代码是源代码被开发程序的编译器编译之后形成的,是给机器看的,机器按代码执行操作。
pbr (powerbiulder resourse)是PB的资源文件,记录PB的某个项目用的资源名称(图片名等),是个文本文件来的,可用记事本打开来修改。创建时将项目需要用的图标、图像文件等按照一个格式每行书写保存在txt文件中,最后将txt文件后缀改为pbr。
————————————————
版权声明:本文为CSDN博主「d60637663」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/d60637663/article/details/106438943
PBD,PowerBuilder动态库,作为本地DLL的一个替代物。
PBD是必须有PB虚拟机才能执行的程序文件。
PBD文件也可以理解成类似于DLL的文件。只是DLL是机器码,PBD是伪代码。
在编译的时候如果设置成PCODE,并在某个PBL文件后打勾,编译之后就会产生PBD文件。通常一些大型软件编译的时候都会编译成好多个PBD,这样方便软件的维护,由于PBD是伪代码,所以必须有PB的虚拟机PBVM60.DLL的支持。
https://product.pconline.com.cn/itbk/software/wjgs/1112/2607540.html
这个论坛有很多 pb 安装包 https://www.sybasebbs.com/thread-5568-1-1.html
反编译 http://pbkiller.ltd/pageen.html
PowerBuilder 连接数据库
- https://blog.csdn.net/lu930124/article/details/44346769
- https://blog.csdn.net/sms15732621690/article/details/73564972
PowerBuilder 数据库 ODBC 介绍
应用部署
- https://docs.appeon.com/pb2019/pbug/ch33s01.html
- https://docs.appeon.com/pb2019/application_techniques/ch34s02.html#d0e23895
编译:
- https://jingyan.baidu.com/article/91f5db1b277d901c7e05e373.html
- https://blog.csdn.net/wybshyy/article/details/106348864
参考链接
- 从Web攻击视角看客户端漏洞挖掘-DC0571.pdf
- https://www.cobalt.io/blog/cobalt-core-academy-thick-client-pentesting
- 被忽视的暗面:客户端应用漏洞挖掘之旅//mp.weixin.qq.com/s/JAp8EyEz4y1_IuGXwgtbTQ
- https://payatu.com/blog/hariprasad/An-Intro-To-Electron
- https://blog.doyensec.com/2018/07/19/instrumenting-electron-app.html
- https://blog.yeswehack.com/yeswerhackers/exploitation/pentesting-electron-applications
最近更新:
发布时间: