MSSQL连接数据库密码获取工具与原文数个错误纠正

原文链接:/tips/?id=1067

在测试时发现了一些问题,于是把解决方案与一些结论共享出来,以供需要。

0x00 原文提供的powershell脚本出错的解决方案


原文提供的脚本直接导入执行会抛出“数据无效”的错误,测试系统在查询分析器中获取到的密文为:

[ 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01, 0x15, 0xD1, 0x11, 0x8C, 0x7A, 0x00, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x2A, 0x0B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x51, 0x00, 0x4C, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x61, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, 0x0F, 0x27, 0xAB, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4C, 0xED, 0x01, 0x57, 0x33, 0x68, 0x06, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xE9, 0x20, 0xD6, 0x91, 0xCD, 0x70, 0xF2, 0xC4, 0x0F, 0xB4, 0x97, 0xF7, 0xBB, 0x7C, 0x68, 0x76, 0x4D, 0x1F, 0x9D, 0x6D, 0xC8, 0x56, 0xBF, 0x04, 0x14, 0x00, 0x00, 0x00, 0xEA, 0x60, 0x44, 0xBC, 0xAC, 0xA3, 0x92, 0x1D, 0x04, 0xCC, 0x5E, 0x6C, 0x47, 0xE5, 0x1B, 0x0D, 0xE1, 0xF9, 0x29, 0xD8]

长度为236字节。而在powershell中获取到的密文为:

[ 0x01, 0x00, 0x00, 0x00, 0xD0, 0x8C, 0x9D, 0xDF, 0x01, 0x15, 0xD1, 0x11, 0x8C, 0x7A, 0x00, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, 0x01, 0x00, 0x00, 0x00, 0xCD, 0x2A, 0x0B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, 0x04, 0x00, 0x00, 0x00, 0x4C, 0x00, 0x00, 0x00, 0x5F, 0x00, 0x5F, 0x00, 0x53, 0x00, 0x51, 0x00, 0x4C, 0x00, 0x53, 0x00, 0x65, 0x00, 0x72, 0x00, 0x76, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x39, 0x00, 0x2E, 0x00, 0x30, 0x00, 0x20, 0x00, 0x4D, 0x00, 0x61, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 0x20, 0x00, 0x4B, 0x00, 0x65, 0x00, 0x79, 0x00, 0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x63, 0x00, 0x72, 0x00, 0x79, 0x00, 0x70, 0x00, 0x74, 0x00, 0x69, 0x00, 0x6F, 0x00, 0x6E, 0x00, 0x00, 0x00, 0x03, 0x66, 0x00, 0x00, 0xA8, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, 0x0F, 0x27, 0xAB, 0xAC, 0x00, 0x00, 0x00, 0x00, 0x04, 0x80, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x4C, 0xED, 0x01, 0x57, 0x33, 0x68, 0x06, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xE9, 0x20, 0xD6, 0x91, 0xCD, 0x70, 0xF2, 0xC4] 

长度为196字节,少了40字节。经过多次测试发现问题处于查询语句中的len函数。

msdn(http://technet.microsoft.com/zh-cn/library/ms190329.aspx)上对len函数的说明是:返回指定字符串表达式的字符数,其中不包含尾随空格。

由于函数返回的是字符数,自然要涉及编码。老外的操作系统是英文,默认使用IBM437 (OEM United States) 编码,这个编码是单字节字符集(sbcs),0x00-0xff都被认为是一个字符,所以获取的字符长度与字节长度相等。而中文操作系统默认使用gb2312编码,属于双字节字符集(dbcs),大于0x7f的字节都将与其后的一个字节合并作为一个字符,于是在处理含有大于0x7f的字节数组时,len函数获取的长度与字节数并不相等,最终会由于密文不完整而出错。统计完整密文中大于0x7f的字节总数并排除连续两个的情况,正好是40.

解决方案:

将原脚本第74行、第100行共计三个len函数换为datalength函数(http://technet.microsoft.com/zh-cn/library/ms173486.aspx)。

0x01 原文错误的定论与拓展利用


原文中有两个错误的定论,而这两个定论在某些条件下恰好可以组合成为一个新的获取途径。

第一个错误的定论是存放熵的注册表键所属项权限,原文:“再次提醒,访问此表项需要本地系统的管理员权限。”的说法是完全错误的。

可以想象,如果sqlserver以低权限运行时不能访问这个注册表项,那么执行sp_addlinkedsrvlogin必然会抛出错误,而实际上无论sqlserver的权限是什么,这个键总可以被sqlserver所访问。

在默认情况下,此键所在项(HKLM\SOFTWARE\Microsoft\Microsoft SQL Server\[instancename]\Security)有以下四个权限:

system:完全控制,子项继承
administrators:完全控制,子项继承
creator owner:完全控制
SQLServerMSSQLUser$[机器名]$[实例名]:查询,修改,创建子项,枚举子项,通知,读取DAC  

前两个权限不必解释,第三个权限代表所有者,一般为system/administrator

第四项代表sqlserver实例用户组,每个实例对应一个。在修改sqlserver某个实例的服务登录帐户时,会自动将这个账户加入此组。

所以当某个程序的运行账户与sqlserver某实例服务账户相同,那么这个程序可以打开注册表并读取此实例的Entropy Key。实际上,真正起到验证作用的实际上只有第四项。

第二个错误的定论是DAC连接的条件,原文:“打开专用管理员连接有两个条件:一是需要有sqlserver的Sysadmin权限,二是本地服务器的管理员权限。”。

而实际上,打开DAC链接只需要属于sysadmin固定服务器角色成员,DAC是支持远程连接的。

于是有以下推论:

1.当某个程序的运行账户与sqlserver某实例服务账户相同,那么这个程序可以打开注册表并读取此实例的Entropy Key。  
2.由于实例服务账户所在用户组SQLServerMSSQLUser$[机器名]$[实例名]存在于sqlserver登陆名列表中并属于sysadmin固定服务器角色成员,于是这个凭据可用来打开DAC链接。  
3.由于实例服务账户属于本地组成员,所以可以打开MachineKey进行加密解密。  
4.连接服务器密码解密只依赖于Entropy Key,MachineKey和DAC链接  

最后得出结论:

当某个程序的运行账户与sqlserver某实例服务账户相同,则此程序可以获取到此sqlserver实例中所有链接服务器的密码。  

在实际利用上,一个典型例子就是iis。众所周知2003的iis默认应用程序池权限是Network Service,而一些管理员对sqlserver降权的做法也是将sqlserver实例服务账户更改为Network Service。于是在上述情况下,任何asp.net应用程序都可以通过windows验证方式直接作为sa登陆,同时解密并导出链接服务器密码。对于asp等由于使用了来宾帐户作为默认凭据,则需要执行额外的程序来获取。

如图:当sqlserver实例服务账户配置为network service运行时,默认iis应用程序池账户network service具有读取注册表的权限:

2014042501272227571.png

于是可以通过工具直接获取到链接服务器密码:

2014042501284933549.png

有了以上结论与原始的Powershell脚本,工具也就不难写了,Powershell脚本实际上就是.net类库的调用,略作修改即可。

lspwd.exe为一键获取工具,lspwd.js为源码,编译命令行:

jsc /r:system.xml.dll lspwd.js

在asp.net中利用的工具以AspxSpy插件形式提供,GetMSSQLLinkedServerPasswordPlugin.cs为源码,编译命令行:

csc /t:library GetMSSQLLinkedServerPasswordPlugin.cs

GetMSSQLLinkedServerPasswordPlugin.dllGetMSSQLLinkedServerPasswordPlugin.dll.Deflated分别为未压缩和压缩后的插件。

插件信息如下:

TypeName:Zcg.Test.AspxSpyPlugins.GetMSSQLLinkedServerPasswordPlugin
MethodName:Run
HTML Result:true
Params:null

输出:当前服务器所有能成功连接的sqlserver实例中所有链接数据库信息。

调用结果如图:

2014042501315093112.png

附件:mssql_linkedserver_pwd.7z

©乌云知识库版权所有 未经许可 禁止转载


30
kakui 2015-01-25 02:31:15

请问楼主 为什么在sysadmin连接上去 却无法读取出那个hash那个表呢 手工查找我不见 能否留下mail或者QQ联系呢? 这个东西搞得我头都大了 就是找不到表 。。。

30
bboy 2014-12-04 00:44:29

win03+mssql2008 r2 powershell v1执行lspwd.exe还是提示can not enum instances

30
QQ446755 2014-10-09 12:31:43

能不能出个详细的使用方式,搞了一天都不对

30
好基友一辈子 2014-05-04 18:23:27

不是我压缩的,就是你包里的那个

30
zcgonvh 2014-04-29 15:59:42

加载.Deflated压缩插件时需要勾选Deflate-Compressed选项,不然就会抛出BadImageFormatException.
另外你的插件大小不对,是自己压缩的?压缩包中的插件大小为4145字节,不是3297字节。

30
好基友一辈子 2014-04-29 15:34:08

aspx导入插件。。
System.BadImageFormatException: 未能加载文件或程序集“3297 bytes loaded from App_Web_khfrbeab, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null”或它的某一个依赖项。试图加载格式不正确的程序。
文件名:“3297 bytes loaded from App_Web_khfrbeab, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null” ---> System.BadImageFormatException: IL 格式不正确。
在 System.Reflection.Assembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection)
在 System.Reflection.Assembly.Load(Byte[] rawAssembly)
在 ASP._11_aspx.zcg_btnplgLoad_Click(Object sender, EventArgs e)

求解释

30
Comer 2014-04-27 19:53:06

板凳先,得空试试

30
zcgonvh 2014-04-26 16:36:10

没有权限访问entropy键,需要high mandatory lable管理员、system或sqlserver实例账户执行程序或设置iis应用程序池账户。

30
ss 2014-04-26 13:40:17

========result of instance: MSSQLSERVER========
error:
不允许所请求的注册表访问权。

30
有问 2014-04-26 13:08:32

谢谢。我去测试一下。昨天也找了一下没有相关键值。

30
zcgonvh 2014-04-25 19:19:38

第一个错误是我脑抽了,那个exe是个测试用的,里面键值不对,重新编译一遍吧,抱歉~
第二个错误表示不能读取entropy键,sqlserver2000没有security子项,同时也不支持DAC链接,所以工具不支持。换用2005或更高版本的sqlserver测试吧。

30
zcgonvh 2014-04-25 17:40:02

感谢~

30
有问 2014-04-25 17:36:56

本地测试了一下。2003+iis+mssql2000环境。
第一个exe工具运行了显示如下:
C:\wmpub>lspwd
can not enum instances
第二个用加载那个dll文件然后输出显示如下:
========result of instance: MSSQLSERVER========
error:
can not get regkey

请问错在哪里???谢谢

30
流星warden 2014-04-25 16:15:05

赞一个

30
c4bbage 2014-04-25 14:41:13

。!。

30
瞌睡龙 2014-04-25 14:30:07

已在文末添加附件 :)

30
zcgonvh 2014-04-25 14:14:07

昨天晚上意志模糊,居然忘了加上下载链接。
下载链接:1hqxatz2 密码:6qzj

30
瞌睡龙 2014-04-25 12:42:48

赞研究精神!~

感谢知乎授权页面模版