科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件面对IE保护模式的开发者生存之道

面对IE保护模式的开发者生存之道

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

这篇文章假定你已经熟悉C++、GUI和COM编程。示例代码是使用Visual Studio 2005、WTL 7.5和Windows SDK建立的。

作者:ITPUB 来源:ITPUB 2007年12月6日

关键字: 生存之道 开发者 IE保护模式

  • 评论
  • 分享微博
  • 分享邮件

在微软开发者大会上看到Vista和IE 7之后,我已经表示它们的保护模式不仅仅阻挡了间谍软件,也让合法的IE插件变得非常困难。当我试用了Vista beta 2之后,我体验到了这种困难——我的产品之一是一个IE工具栏,保护模式破坏了它的许多主要功能,因为这个工具栏需要与IE之外的另一个进程进行通信。经过多次尝试,我最终让这些功能又可以正常使用了。关于如何在这种安全模式下对自己的应用程序做出必要的修改,我根据自己的经历总结出一些经验,希望和有这方面需求的朋友分享。

这篇文章假定你已经熟悉C++、GUI和COM编程。示例代码是使用Visual Studio 2005、WTL 7.5和Windows SDK建立的。如果你想更多的了解WTL,可以查看我的关于WTL的系列文章(http: //www.codeproject.com/wtl/wtl4mfc1.asp)。WTL只用于图形化界面;本文介绍的概念适用于所有应用程序,没有依赖于任何类库。

 一.介绍保护模式

IE浏览器的保护模式是Vista中的一个新功能,是类似用户帐号控制(UAC)的一种安全功能。在保护模式下,通过限制运行在IE进程下的代码不能修改系统部分文件,从而来保护计算机的安全。这样,即使一个恶意网页利用了IE或IE插件中的一个代码注入漏洞,注入的代码也不能够对系统造成破坏。

在我们深入了解保护模式对IE插件开发者意味着什么之前,我们需要先快速了解一下相关的安全功能。

 1.完整性级别和UIPI

Vista引入了一种叫做强制完整性级别的安全对象新属性。分为四个级别:

 系统:被操作系统组件使用,不应被应用程序所使用;
 高:在提升的完全管理权限下运行的进程;
 中:正常方式启动的进程;
 低:被IE和Windows Mail使用来提供保护模式。

Windows中关于进程的信息包含它是使用哪一个完整性级别启动的。一旦该进程启动后这个级别永远不会发生改变,它只能在进程被创建的时候被设定。一个进程的完整性级别具有以下三个主要的作用:

(1)这个进程所创建的任何安全对象具有与它相同的完整性级别。
(2)这个进程不能够存取完整性级别比它高的资源。
(3)这个进程不能发送Windows消息到具有更高完整性级别的进程。

这不是一个完整的列表,但是以上所列的三个是对插件具有最大影响的。前两条防止一个低完整性的进程篡改IPC资源,例如共享内存,包含敏感数据或一个应用程序正常运行所需要的数据。最后一条被称为用户界面特权隔离(UIPI),被设计来防止类似粉碎窗口攻击(shatter attack)之类的攻击,在粉碎窗口攻击中,攻击者通过发送给进程一个它不希望收到的消息,从而导致它运行非信任的代码。

 启用你的插件和其他应用程序之间的通信

看到这儿,我们已经可以使用运行在IE进程中的代码来处理所有文件系统和注册表了。下面我们看一个更复杂的话题,它也需要一个更复杂的解决方案:运行在一个更高完整性级别的另一个进程的IPC。我们将介绍两种不同形式的IPC:内核对象和windows消息。

1.创建一个IPC对象

当一个插件和一个单独的进程希望通信的时候,这种通信发生在两个代码之间,而不用经过IE封装。NT安全API和强制性完整级别现在可以发挥它们的作用了,默认情况下从一个插件到一个单独的应用程序的通信是被阻挡的,因为这个应用程序运行在比IE更高的完整性级别。

如果这个单独的应用程序创建了一个插件需要使用的内核对象(例如,一个事件或互斥对象),在插件存取它们之前,这个应用程序必须降低这个对象的完整性级别。这个应用程序可以使用安全API来修改对象的ACL来降低它的完整性级别。下面的代码是从MSDN的文章“Understanding and Working in Protected Mode Internet Explorer”摘取的,将一个HANDLE赋给一个内核对象,并设置它的完整性级别为低。
// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity LPCWSTR LOW_INTEGRITY_SDDL_SACL_W = L"S:(ML; ; NW; ; ; LW)";

bool SetObjectToLowIntegrity( HANDLE hObject, SE_OBJECT_TYPE type = SE_KERNEL_OBJECT)
{
bool bRet = false;

DWORD dwErr = ERROR_SUCCESS; PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL;

BOOL fSaclPresent = FALSE; BOOL fSaclDefaulted = FALSE;
if ( ConvertStringSecurityDescriptorToSecurityDescriptorW ( LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD, NULL ) )
{
if ( GetSecurityDescriptorSacl ( pSD, &fSaclPresent, &pSacl, &fSaclDefaulted ) )
{
dwErr = SetSecurityInfo ( hObject, type, LABEL_SECURITY_INFORMATION, NULL, NULL, NULL, pSacl );
bRet = (ERROR_SUCCESS == dwErr);
}
LocalFree ( pSD );
}
return bRet;
}

这个示例代码使用了两个mutex,其目的是让这个插件告诉什么时候这个应用程序在运行。当这个进程启动的时候DemoAPP EXE创建了它们,当你点击其中一个Open Mutex按钮的时候这个插件尝试去打开它们。Mutex 1具有默认的完整性级别,而mutex 2则通过上面所说的SetObjectToLowIntgrity()函数设置到低完整性级别。这意味着当保护模式启用的时候,这个插件将只能存取 mutex 2。以下是当你点击两个Open Mutex按钮时所看到的结果:

 运行时检测保护模式

为了判断我们的插件是否运行在一个保护模式IE进程中,我们使用IEISProtectedModeProcess():
HRESULT IEIsProtectedModeProcess(BOOL* pbResult);

如果返回值是一个成功的HRESULR和*pbResult是True,那么保护模式就被启用了。根据在*pbResult中返回的值,你可以在你的代码中采取不同的操作:
HRESULT hr;

BOOL bProtectedMode = FALSE;

hr = IEIsProtectedModeProcess ( &bProtectedMode );
if ( SUCCEEDED(hr) && bProtectedMode ) // IE is running in protected mode else // IE isn't running in protected mode

示例band插件在一启动的时候调用了这个API,并显示了关于保护模式状态的一个消息。

 2.写文件系统

当保护模式被启用的时候,扩展插件只能对用户配置下的几个目录进行写操作。只有在Temp、Temporary、Internet Files、Cookies和Favorites目录下的几个特定低完整性目录可以进行写操作。IE还有某些兼容性补偿功能,它虚拟化其他常用目录。对这些目录的写操作将被重定向到Temporary Internet Files的子目录中。如果一个扩展插件试图对一个敏感进行写操作的话,例如对windows目录,这个操作将会失败。

当一个扩展插件希望写这个文件系统的时候,它应该使用IEGetWriteableFolderPath()这个API,而不是GetSpecialFolderPath()、GetFolderPath()或SHGetKnownFolderPath()。
IEGetWriteableFolderPath ()可以发现保护模式,如果一个插件请求一个不允许写的目录,IEGetWriteableFolderPath()将返回 E_ACCESSDENIED。IEGetWriteableFolderPath()的原型如下:

HRESULT IEGetWriteableFolderPath(GUID clsidFolderID, LPWSTR* lppwstrPath);

  保护模式中的其他限制

 1.运行其他应用程序

 IE具有另一个防止恶意代码启动或与其他进程通信的机制。如果一个插件试图启动另一个进程,IE将在启动这个进程前要求该用户同意。举个例子来说,使用查看源代码命令会引起如下提示:

如果你的插件需要运行一个单独的EXE,你可以增加一个注册表键值来告诉IE你的EXE可以被信任并能够无须提示就被运行。这个控制这种行为的注册表键值是HKLM\Software\Microsoft\Internet Explorer\Low Rights\ElevationPolicy。创建一个新的GUID,然后在名称为那个GUID的ElevationPolicy下增加一个键值。在这个新的键值中,创建三个值:

 AppName:可执行文件的文件名,例如“DempApp.exe”。
 AppPath:EXE所在的目录。
 Policy:设置成3的DWORD值

如果你的安装没有创建一个类似的键的话,当你选择对话框中的“Do not show me the warning for this program again”,IE自己将创建一个。

 2、拖拽到其他应用程序

如果你试图从一个网页的内容拖拽到另一个应用程序中,会出现一个类似的提示窗口:

这个提示窗口也可通过一个注册表键来禁止。格式如上面所述,但是你的应用程序的键应该放在DragDrop下,而不是前面的ElevationPolicy。

DemoApp作为一个拖拽的对象来演示,如果你在IE中选择了一些文本内容,并把它拖拽到DemoApp对话框中,它将显示一个消息来表示它已经收到这个拖拽动作.

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章