【.net 深呼吸】限制执行代码的权限

前面好几篇文章,老周都跟大伙伴们聊了跟应用程序域有关的话题,干脆咱们一聊到底吧,做学问就应该这样,有恒心。

App Domain的创建新应用程序域的方法中,有一个特殊的重载:

public static AppDomain CreateDomain(string friendlyName, Evidence securityInfo, AppDomainSetup info, PermissionSet grantSet, params StrongName[] fullTrustAssemblies);

这个重载比较特殊,它与咱们今天扯的话题接近,因为它的参数列表中有一个是 PermissionSet 类型的,它表示一个权限的集合,当创建应用程序域时,通过这个权限集合,限制在新应用程序域中执行的代码的权限。在各个CreateDomain方法的重载中,只有这个有设置权限集的参数。

运用这个重载方法,可以将你觉得要限制权限的代码放到这个新的应用程序域中执行,即创建一个“沙箱”。比如,你拿到别人写的一个类库A,不过你不知道这个类库A在执行过程中会干什么,于是,你希望在使用这个来路不明的类库时,可以限制一下它,例如不让它读写文件,或者说只允许它访问某些目录和文件。

为了偷工减料,写出豆腐渣程序,老周举的这个例子,是把做测试用的代码写到主程序集中。它有一个类,类中有一个方法,调用之后,会在“文档”库中创建一个文件,然后写入一些见不得人的内容。

    public class Demo : MarshalByRefObject
    {
        public void WirteFile()
        {
            string myDoc = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            string filePath = Path.Combine(myDoc, Guid.NewGuid() + ".txt");
            using (FileStream fs = File.Open(filePath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.Read))
            {
                byte[] data = Encoding.UTF8.GetBytes("卖假药啦。");
                fs.Write(data, 0, data.Length);
            }
        }
    }

然后,创建一个新的应用程序域,再在新域里面执行刚刚写好的类。之所以继承MarshalByRefObject类,是希望可以跨应用程序域调用,并且是按引用传递。

调用如下:

            // 添加程序集凭据
            // 此处是为了装逼,才写以下几行
            // 其实你可以直接用 AppDomain.CurrentDomain.Evidence
            Evidence evd = new Evidence();
            Assembly currAss = Assembly.GetExecutingAssembly();
            Hash hsevd = new Hash(currAss);
            evd.AddAssemblyEvidence<Hash>(hsevd);

            // 准备相关信息
            AppDomainSetup setup = new AppDomainSetup();
            setup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase;

            // 准备权限
            PermissionSet ps = new PermissionSet(PermissionState.None);
            // Execution 权限必须,不然连代码都不能执行了
            SecurityPermission secps = new SecurityPermission(SecurityPermissionFlag.Execution);
            ps.AddPermission(secps);

            // 创建新域
            AppDomain newAppdm = AppDomain.CreateDomain("good", evd, setup, ps);
            // 创建测试对象实例
            Demo d = (Demo)newAppdm.CreateInstanceAndUnwrap(currAss.FullName, $"{nameof(TestApp)}.{nameof(Demo)}");
            d.WriteFile();

            d = null;
            AppDomain.Unload(newAppdm);

Evidence这东西比较抽象,你可以理解为程序集用来证明它是合法身份的一些信息,比如这里,我用当前程序集的 Hash 值来做为证明,因为这个 Demo 类是写在当前程序集中的(刚刚说了,为了偷工减料)。

注意权限集合是 PermissionSet 类,它是个容器,你可以根据需要,向里面添加权限声明。在上面代码中,我加了一个最基本的安全权限——SecurityPermission,这个你得加,因为它是最最最基本的权限,如果不加,连代码都执行不了,那就等于这段代码是废的,用 SecurityPermissionFlag 枚举来描述代码应具有的基础权限,这些值可以组合使用,Execution表示允许执行代码,如果你连这个权限也不给,干脆把 Demo 类开除算了。

顺便说一下,在new出PermissionSet 实例时,构造函数会要求一个 PermissionState值,你应该把它设置为 None,这样权限才会对代码进行限制,如果用了Unrestricted ,表示不做限制。

调用 CreateInstanceAndUnwrap 方法时,是在新的应用程序域中创建 Demo 实例,但可以通过引用,把实例封送到当前应用程序域中,这样可以跨域调用,实际上 WriteFile 方法是在新的应用程序域中执行的。

如果你要允许代码访问文件和目录,你必须加上FileIOPermission权限,但这里我没加,看看运行后会如何。

因为我不给它权限,所以它没办法写入文件了。

现在我们来改一下代码,在创建应用程序域前,向权限集合添加 FileIOPermission 权限。

            string docPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            FileIOPermission fps = new FileIOPermission(FileIOPermissionAccess.AllAccess, docPath);
            ps.AddPermission(fps);

再执行一下,如果执行成功,会发现“文档”库里面多了一个文件。

好了,今天就扯到这里了。

示例代码下载地址

时间: 2024-10-10 17:53:44

【.net 深呼吸】限制执行代码的权限的相关文章

ubuntu Gitolite管理git server代码库权限

公司代码库用Git,全部用SSH认证,多个代码库多个用户,权限管理是个头疼的问题,今天终于有空测试下Gitolite, Gitolite是在Git之上的一个授权层,依托sshd或者httpd来进行认证.(概括:认证是确定用户是谁,授权是决定该用户是否被允许做他想做的事情). Gitolite允许你定义访问许可而不只作用于仓库,而同样于仓库中的每个branch和tag name.你可以定义确切的人(或一组人)只能push特定的"refs"(或者branches或者tags)而不是其他人.

sqlserver授予用户查看执行计划的权限

sqlserver查看语句的执行计划是非常重要的,可以提高开发人员代码的质量.所以有必要授予开发人员对数据库查看执行计划的权限. 查看执行计划的权限属于数据库一级别的权限,具体例子如下 use test:--选择需要授权的数据库 grant showplan to user;--授权给对应的用户

Linux平台中设置文件的执行、写权限

最近在开发过程中遇到一个问题,进行文件拷贝的时候,某些可执行文件在linux平台中会出现权限丢失的现象,例如:一个exe文件在windows平台上不涉及权限,通过Java代码拷贝到Linux中就会出现权限丢失的问题.最后只能通过文件复制之后,再通过代码进行权限设置例如文件的读写与执行权限等. /** * 功能描述:设置文件的执行.写权限,linux用<br> * @param fileName * @param able * @param ownerOnly * @return boolean

IntelliJ IDEA 提高执行代码速度的好办法

idea是神器,用过后再也不想回到eclipse去了,但是有一点不明白,为什么运行速度这么慢 后面慢慢发现原来是每次执行前都需要build,即编译,所以就是这个编译时间让运行速度显得特别慢.怎么办呢? 很简单 在compiler找到自动编译,勾选auto compile.然后在 每次执行代码前取消build就会达到和eclipse一样的速度了!

第六周 可执行代码 以及 PSP 燃尽图 等等

转眼已经第六周了.这周主要内容有下:(CHECKLIST) 1.完成未完成的功能点. 2.PSP. 3.站立会议(待开). 4.燃尽图. 5.各种图(折线,饼图). 6.checkList 具体任务如下: 1. i.将用户做过的题目整理到习题本中. ii.习题本可以记录用户当时填写的答案. iii.规范算式(4个数字). iv.将做过的题目去重. v.再次规范化输出算式(生成数目多少,括号位置,括号对数). vi.支持分数运算. vii.结果用分数显示. viii.结果显示分数的最简形式. iX

第五周可执行代码 以及 Canvas 制作个人PSP分类饼图

第五周可执行代码已经上传github,地址是https://github.com/yanyige/CourseWork/tree/master/Week4.以及效果在http://yanyige.github.io/Week4/中展示. 这里使用Canvas绘图制作PSP饼图,整个实现方法参考JavaScript高级程序设计第三版 P449 页的内容. 这里是实现结果: 代码地址是https://github.com/yanyige/CourseWork/tree/master/Week5,效果

jQuery滚动延迟加载执行代码

滚动条延迟加载 jQuery(function($){ var topicBoxTopHeight = jQuery('#topicBox').offset().top; var topicBoxTopHeight_show = 1 $(window).scroll(function(event){ if($(this).scrollTop() > topicBoxTopHeight-$(window).height()-200 && topicBoxTopHeight_show==

给PE文件增加执行代码

最近想写一个软件壳,需要给PE文件增加一个区段(Section),来执行一些初始化的工作.只要先学习一下PE文件的格式和结构,有个大概了解后,我想就能很容易写出相关代码.网上有很多PE格式的介绍,这里就不多介绍,直入主题. 增加的执行代码有两个地方可以放,一个是现有PE文件区段在数据对齐时有一些空隙,这样的空隙一般只能存放比较小块的代码,优点是对原有的PE文件数据改动比较小,大小也不会改变:另一个就是增加一个新的区段,这样可以放任意你想放置的代码,发挥的空间也大一些.本文的方法是先判断是否有足够

CVE-2013-1347Microsoft Internet Explorer 8 远程执行代码漏洞

[CNNVD]Microsoft Internet Explorer 8 远程执行代码漏洞(CNNVD-201305-092) Microsoft Internet Explorer是美国微软(Microsoft)公司发布的Windows操作系统中默认捆绑的Web浏览器.         Internet Explorer 访问尚未正确初始化或已被删除的对象的方式中存在一个远程执行代码漏洞,该漏洞可能以一种攻击者可以在当前用户的上下文中执行任意代码的方式损坏内存.攻 击者可能拥有一个特制的网站,