阅读:3210回复:0
MSSQL连接数据库密码获取工具与原文数个错误纠正
原文链接:http://drops.wooyun.org/tips/1067。
在测试时发现了一些问题,于是把解决方案与一些结论共享出来,以供需要。 ◆0 原文提供的powershell脚本出错的解决方案 原文提供的脚本直接导入执行会抛出“数据无效”的错误,测试系统在查询分析器中获取到的密文为: [ ◆1, ◆0, ◆0, ◆0, 0xD0, 0x8C, 0x9D, 0xDF, ◆1, 0x15, 0xD1, 0x11, 0x8C, 0x7A, ◆0, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, ◆1, ◆0, ◆0, ◆0, 0xCD, 0x2A, ◆B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, ◆4, ◆0, ◆0, ◆0, 0x4C, ◆0, ◆0, ◆0, 0x5F, ◆0, 0x5F, ◆0, 0x53, ◆0, 0x51, ◆0, 0x4C, ◆0, 0x53, ◆0, 0x65, ◆0, 0x72, ◆0, 0x76, ◆0, 0x65, ◆0, 0x72, ◆0, 0x20, ◆0, 0x39, ◆0, 0x2E, ◆0, 0x30, ◆0, 0x20, ◆0, 0x4D, ◆0, 0x61, ◆0, 0x73, ◆0, 0x74, ◆0, 0x65, ◆0, 0x72, ◆0, 0x20, ◆0, 0x4B, ◆0, 0x65, ◆0, 0x79, ◆0, 0x20, ◆0, 0x45, ◆0, 0x6E, ◆0, 0x63, ◆0, 0x72, ◆0, 0x79, ◆0, 0x70, ◆0, 0x74, ◆0, 0x69, ◆0, 0x6F, ◆0, 0x6E, ◆0, ◆0, ◆0, ◆3, 0x66, ◆0, ◆0, 0xA8, ◆0, ◆0, ◆0, 0x10, ◆0, ◆0, ◆0, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, ◆F, 0x27, 0xAB, 0xAC, ◆0, ◆0, ◆0, ◆0, ◆4, 0x80, ◆0, ◆0, 0xA0, ◆0, ◆0, ◆0, 0x10, ◆0, ◆0, ◆0, 0x4C, 0xED, ◆1, 0x57, 0x33, 0x68, ◆6, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, ◆0, ◆0, ◆0, 0xE9, 0x20, 0xD6, 0x91, 0xCD, 0x70, 0xF2, 0xC4, ◆F, 0xB4, 0x97, 0xF7, 0xBB, 0x7C, 0x68, 0x76, 0x4D, 0x1F, 0x9D, 0x6D, 0xC8, 0x56, 0xBF, ◆4, 0x14, ◆0, ◆0, ◆0, 0xEA, 0x60, 0x44, 0xBC, 0xAC, 0xA3, 0x92, 0x1D, ◆4, 0xCC, 0x5E, 0x6C, 0x47, 0xE5, 0x1B, ◆D, 0xE1, 0xF9, 0x29, 0xD8] 长度为236字节。而在powershell中获取到的密文为: [ ◆1, ◆0, ◆0, ◆0, 0xD0, 0x8C, 0x9D, 0xDF, ◆1, 0x15, 0xD1, 0x11, 0x8C, 0x7A, ◆0, 0xC0, 0x4F, 0xC2, 0x97, 0xEB, ◆1, ◆0, ◆0, ◆0, 0xCD, 0x2A, ◆B, 0x54, 0x64, 0x6A, 0xBC, 0x4B, 0xB0, 0x99, 0xF1, 0xE6, 0x3D, 0x93, 0x9E, 0x6E, ◆4, ◆0, ◆0, ◆0, 0x4C, ◆0, ◆0, ◆0, 0x5F, ◆0, 0x5F, ◆0, 0x53, ◆0, 0x51, ◆0, 0x4C, ◆0, 0x53, ◆0, 0x65, ◆0, 0x72, ◆0, 0x76, ◆0, 0x65, ◆0, 0x72, ◆0, 0x20, ◆0, 0x39, ◆0, 0x2E, ◆0, 0x30, ◆0, 0x20, ◆0, 0x4D, ◆0, 0x61, ◆0, 0x73, ◆0, 0x74, ◆0, 0x65, ◆0, 0x72, ◆0, 0x20, ◆0, 0x4B, ◆0, 0x65, ◆0, 0x79, ◆0, 0x20, ◆0, 0x45, ◆0, 0x6E, ◆0, 0x63, ◆0, 0x72, ◆0, 0x79, ◆0, 0x70, ◆0, 0x74, ◆0, 0x69, ◆0, 0x6F, ◆0, 0x6E, ◆0, ◆0, ◆0, ◆3, 0x66, ◆0, ◆0, 0xA8, ◆0, ◆0, ◆0, 0x10, ◆0, ◆0, ◆0, 0x3F, 0xDA, 0x14, 0xC2, 0xE9, 0x3E, 0xC7, 0xDE, 0x3A, 0x5C, 0xC2, 0xAE, ◆F, 0x27, 0xAB, 0xAC, ◆0, ◆0, ◆0, ◆0, ◆4, 0x80, ◆0, ◆0, 0xA0, ◆0, ◆0, ◆0, 0x10, ◆0, ◆0, ◆0, 0x4C, 0xED, ◆1, 0x57, 0x33, 0x68, ◆6, 0x7E, 0x81, 0x4D, 0xB9, 0xF7, 0x13, 0xC6, 0x30, 0x34, 0x18, ◆0, ◆0, ◆0, 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),◆0-0xff都被认为是一个字符,所以获取的字符长度与字节长度相等。而中文操作系统默认使用gb2312编码,属于双字节字符集(dbcs),大于0x7f的字节都将与其后的一个字节合并作为一个字符,于是在处理含有大于0x7f的字节数组时,len函数获取的长度与字节数并不相等,最终会由于密文不完整而出错。统计完整密文中大于0x7f的字节总数并排除连续两个的情况,正好是40. 解决方案: 将原脚本第74行、第100行共计三个len函数换为datalength函数(http://technet.microsoft.com/zh-cn/library/ms173486.aspx)。 ◆1 原文错误的定论与拓展利用 原文中有两个错误的定论,而这两个定论在某些条件下恰好可以组合成为一个新的获取途径。 第一个错误的定论是存放熵的注册表键所属项权限,原文:“再次提醒,访问此表项需要本地系统的管理员权限。”的说法是完全错误的。 可以想象,如果sqlserver以低权限运行时不能访问这个注册表项,那么执行sp_addlinkedsrvlogin必然会抛出错误,而实际上无论sqlserver的权限是什么,这个键总可以被sqlserver所访问。 在默认情况下,此键所在项(HKLMSOFTWAREMicrosoftMicrosoft 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 于是可以通过工具直接获取到链接服务器密码: 图片:2014042501272227571.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.dll和GetMSSQLLinkedServerPasswordPlugin.dll.Deflated分别为未压缩和压缩后的插件。 插件信息如下: TypeName:Zcg.Test.AspxSpyPlugins.GetMSSQLLinkedServerPasswordPlugin MethodName:Run HTML Result:true Params:null 输出:当前服务器所有能成功连接的sqlserver实例中所有链接数据库信息。 调用结果如图: 图片:2014042501272227571.png 附件:mssql_linkedserver_pwd.7z |
|