Windows信息搜集篇(五)之DPAPI 数据加密与Dns域传送漏洞利用
DPAPI 数据加密
00x01 什么是DPAPI
DPAPI
是Windows
系统级对数据进行加解密的一种接口,无需自实现加解密代码,微软已经提供了经过验证的高质量加解密算法,提供了用户态的接口,对密钥的推导,存储,数据加解密实现透明,并提供较高的安全保证。
DPAPI
提供了两个用户态接口,CryptProtectData
加密数据,CryptUnprotectData
解密数据,加密后的数据由应用程序负责安全存储,应用无需解析加密后的数据格式。但是,加密后的数据存储需要一定的机制,因为该数据可以被其他任何进程用来解密,当然CryptProtectData
也提供了用户输入额外数据来参与对用户数据进行加密的参数,但依然无法放于暴力破解。
总体来说,程序可以使用DPAPI
来对自己敏感的数据进行加解密,也可持久化存储,程序或系统重启后可解密密文获取原文。如果应用程序,对此敏感数据只是暂存于内存,为了防止被黑客dump
内存后进行破解,也对此数据无需进行持久化存储,微软还提供了加解密内存的接口CryptProtectMemory
和CryptUnprotectMemory
。加解密内存的接口,并可指定Flag对此内存加解密的声明周期做控制,详细见Memory
加密及优缺点章节。
00x02 DPAPI的会话密钥推导
DPAPI
使用的会话密钥由MasterKey
和随机数的HASH
推导产生,而MasterKey
的保护由用户登录密码HASH
,随机数,和迭代次数通过可靠的PBKDF2
密钥推导算法生成。其中迭代次数可以修改, MasterKeyIterationCount
存储在 HKEY_LOCAL_MACHINE\Software\Microsoft\Cryptography\Protect\Providers\GUID
允许系统管理员增加此迭代计数的密钥中。但是,它不能减少到4000以下。
为了防止篡改MasterKey
,它使用HMAC
进行散列。DPAPI
再次使用SHA-1
作为HMAC
和用户的密码来派生HMAC
密钥。然后使用来自上面的密码派生加密密钥和Triple-DES
来加密MasterKey
和MasterKey
的HMAC
。salt
和迭代计数都是非秘密值,因此与加密的MasterKey
一起存储,但未加密。这允许DPAPI
在给定用户密码的情况下轻松解密MasterKey
。
如上图所示,会话密钥的推导使用了MasterKey
,随机数,和可选的系统登录密码,用户密码推导生成。16字节的随机数,会以明文的形式存储于加密后的BLOB
中,MasterKey
是受推导的加密密钥保护。
00x03 DPAPI密钥备份恢复
恢复密钥是在用户选择从用户的控制面板创建密码重置磁盘(PRD
)时生成的。首先,DPAPI
生成一个2048
位RSA
公钥/私钥对,它是恢复密钥。然后使用公钥将当前密码加密并存储在用户的配置文件中,同时将私钥存储到PRD
,PRD
实际上可以是任何可移动媒体,然后从内存中移除。私钥只存储在PRD
中,而其他任何地方都不存在,所以用户将PRD
保存在安全的地方非常重要。
如果用户输入错误的密码,Windows
会询问他们是否想要使用PRD并重置密码。如果他们选择,运行向导会提示输入新密码,并使用PRD上的私钥解密旧密码并进行更改。
00x04 DPAPI接口调用
- 对数据进行加密:
DATA_BLOB DataIn;
DATA_BLOB DataOut;
DATA_BLOB BlobKey;
DataIn.pbData = const_cast(cbDataIn); //明文数据
DataIn.cbData = nLen; //明文数据长度
if(key)
{
BlobKey.pbData = const_cast(key); //可选用户密码
BlobKey.cbData = lenKey; //可选用户密码长度
}
CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
promp.szPrompt = L"测试加密";
promp.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_PROTECT;
promp.hwndApp = NULL;
if(!CryptProtectData(&DataIn, L"敏感数据", key ? &BlobKey:NULL, NULL, &promp, 0, &DataOut))
return false;
*encLen = DataOut.cbData; //返回密文数据长度
*encData = malloc(DataOut.cbData);
memcpy(*encData, DataOut.pbData, DataOut.cbData); //加密后数据
LocalFree(DataOut.pbData);
- 对数据进行解密:
DATA_BLOB DataIn;
DATA_BLOB DataOut;
DATA_BLOB BlobKey;
LPWSTR pDescrOut = NULL;
if(key)
{
BlobKey.pbData = const_cast(key); //可选用户密码
BlobKey.cbData = lenKey; //可选用户密码长度
}
DataIn.pbData = (BYTE *)const_cast<void *>(encData); //待解密数据
CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
DataIn.cbData = encLen; //待解密数据长度
CRYPTPROTECT_PROMPTSTRUCT promp; //是否与用户交互输入可选的用户密码
promp.cbSize = sizeof(CRYPTPROTECT_PROMPTSTRUCT);
promp.szPrompt = L"测试解密";
promp.dwPromptFlags = CRYPTPROTECT_PROMPT_ON_UNPROTECT;
promp.hwndApp = NULL;
if (!CryptUnprotectData(&DataIn, &pDescrOut, key ? &BlobKey:NULL, NULL, &promp, 0, &DataOut))
return false;
*nLen = DataOut.cbData;
*cbDataIn = malloc(DataOut.cbData);
memcpy(*cbDataIn, DataOut.pbData, DataOut.cbData); //解密后的数据明文
LocalFree(DataOut.pbData);
-
交互弹框提示
-
加密前提示设置加密等级
- 加密等级分类
- 加密等级设置为高时输入用户密码
- 解密时要求输入用户密码
- 输入错误的用户密码提示
00x05 Memory加密及优缺点
Memory
加解密微软也提供了两个接口,CryptProtectMemory
内存加密,CryptUnprotectMemory
内存解密。一般用于即时加解密用户敏感的数据,如用户密码等。内存加解密用于防止他人在您的进程查看敏感信息,如黑客远程dump
你的进程内存,分析和破解你的敏感数据。
通常,您使用CryptProtectMemory
函数来加密您的进程正在运行时将要解密的敏感信息。请勿使用此功能保存稍后要解密的数据; 如果计算机重新启动,您将无法解密数据。要将加密数据保存到文件以便稍后解密,请使用CryptProtectData
函数。
加解密提供了三种标志:
Flag | 说明 |
---|---|
CRYPTPROTECTMEMORY_SAME_PROCESS | 只能在当前进程内加解密,进程重新运行会无法解密 |
CRYPTPROTECTMEMORY_CROSS_PROCESS | 可以跨进行加解密,系统重启后失效 |
CRYPTPROTECTMEMORY_SAME_LOGON | 使用相同的登录凭据来加密和解密不同进程中的内存,系统重启后失效 |
如果需要持存储密文数据,可选用DPAPI
的接口。如果临时缓存下敏感数据,可选用对Memory
加解密的接口。
还有一个致命的缺陷:最低系统版本要求vista
及以上系统版本,所以win xp
不支持该接口。
00x06 扩展DPAPI加密等级
- 程序内置用户密码
- 程序使用物理硬件信息作为用户密码
- 结合PKI技术实现加密用户密码
- 或者以上的组合
00x07 附录
Dns域传送漏洞利用
DNS分类
A记录 IP地址记录,记录一个域名对应的IP地址
AAAA记录 IPv6地址记录,记录一个域名对应的IPv6地址
CNAME记录 别名记录,记录一个主机的别名
MX记录 电子邮件交换记录,记录一个邮件域名对应的IP地址,比如my[at]lijiejie.com
后面的部分lijiejie.com,邮件服务器对应的IP地址
NS记录 域名服务器记录 ,记录该域名由哪台域名服务器解析
PTR记录 反向记录,也即从IP地址到域名的一条记录
TXT记录 记录域名的相关文本信息
SOA记录 start of anthorization 开始授权,是一种比较难以理解的记录值,一般二级域名才会有
DNS域传送
作为重要的互联网基础设施,难免成为黑客的重点攻击目标,服务的稳定性尤为重要。DNS
服务器分为:主服务器、备份服务器和缓存服务器。在主备服务器之间同步数据库,需要使用“DNS
域传送”。域传送是指后备服务器从主服务器拷贝数据,并用得到的数据更新自身数据库。
若DNS
服务器配置不当,可能导致匿名用户获取某个域的所有记录。造成整个网络的拓扑结构泄露给潜在的攻击者,包括一些安全性较低的内部主机,如测试服务器。凭借这份网络蓝图,攻击者可以节省很少的扫描时间。
大的互联网厂商通常将内部网络与外部互联网隔离开,一个重要的手段是使用Private DNS
。如果内部DNS
泄露,将造成极大的安全风险。风险控制不当甚至造成整个内部网络沦陷。
DNS域传送漏洞检测
常用的三种检测方法: nslookup
命令, nmap
命令,dig
命令,下面将分别演示如何用三种方法检测dns
域传送漏洞
利用nslookup
命令发现DNS
域传送命令
C:\Users\21r000>nslookup
默认服务器: UnKnown
Address: 10.211.55.12
> server 21r000.org
默认服务器: 21r000.org
Address: 10.211.55.12
若是不存在漏洞的主机,则可能提示错误Query Refused
:
> ls 21r000.org
[21r000.org]
如存在漏洞的DNS
服务器则会显示,如下
操作基本的步骤是:
输入nslookup命令进入交互式shell
Server 命令参数设定查询将要使用的DNS服务器
Ls命令列出某个域中的所有域名
攻击者能获取的敏感主要包括:
1)网络的拓扑结构,服务器集中的IP地址段
2)数据库服务器的IP地址
3)测试服务器的IP地址,
4)VPN服务器地址泄露
5)其他敏感服务器
使用nmap
扫描DNS
域传送泄露漏洞
nmap --script dns-zone-transfer --script-args dns-zone-transfer.domain=thnu.edu.cn -p 53 -Pn dns1.thnu.edu.cn
对上述命令命令说明如下:
nmap –script dns-zone-transfer
表示加载nmap
文件夹下的脚本文件dns-zone-transfer.nse
,扩展名.nse
可省略
–script-args dns-zone-transfer.domain=zonetransfer.me
向脚本传递参数,设置列出记录的域是nwpu.edu.cn
-p 53
设置扫描53
端口
-Pn
:设置通过Ping
发现主机是否存活
利用dig
检测dns
域传送漏洞
这里涉及dig
一个重要的命令axfr
:
axfr
是q-type
类型的一种: axfr
类型是Authoritative Transfer
的缩写,指请求传送某个区域的全部记录。
我们只要欺骗dns
服务器发送一个axfr
请求过去, 如果该dns
服务器上存在该漏洞,就会返回所有的解析记录值
第一步: 找到解析域名的dns
服务器(Server
服务器), 我们可以发送一个ns
类型解析请求过去
┌──(root💀kali)-[~/桌面]
└─# dig thnu.edu.cn ns
; <<>> DiG 9.16.15-Debian <<>> thnu.edu.cn ns
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30258
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 2
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; MBZ: 0x0005, udp: 4000
;; QUESTION SECTION:
;thnu.edu.cn. IN NS
;; ANSWER SECTION:
thnu.edu.cn. 5 IN NS dns2.thnu.edu.cn.
;; ADDITIONAL SECTION:
dns2.thnu.edu.cn. 5 IN A 222.160.127.38
第二步: 然后向该域名发送axfr
请求:
┌──(root💀kali)-[~/桌面]
└─# dig axfr @dns1.thnu.edu.cn thnu.edu.cn
感言:
唔,该复习了,孩子要挂科了呜呜呜!