Как я могу защитить свои частные функции от рефлексии? - PullRequest
12 голосов
/ 02 декабря 2011

Увидев это: Влияет ли модификатор доступа на отражение?

Я пытался использовать это, но это не работает: enter image description here

Как я могу помешать рефлексии выполнять мои личные методы?

Ответы [ 9 ]

26 голосов
/ 02 декабря 2011

Если кто-то в настоящее время может использовать рефлексию в ваших личных методах, то у него уже есть достаточный доступ, чтобы обойти все, что вы им мешаете. Запуск с меньшим доверием может быть вариантом, но это только для того, чтобы запретить таким вещам, как плагины, слишком большой доступ - это не остановит пользователя с (скажем) доступом администратора к блоку, который может просто повысить доступ.

Если вы не хотите, чтобы код выполнялся, не размещайте его в зоне досягаемости злоумышленника; храните его на веб-сервисе или подобном. Любой код, доступный пользователю, может быть использован напрямую или косвенно путем его декомпиляции (и деобфускирования при необходимости). Вы можете использовать некоторые приемы, чтобы встать у них на пути (проверка вызывающего абонента через трассировку стека и т. Д.), Но это не остановит кого-то определенного.

24 голосов
/ 02 декабря 2011

Как я могу защитить свои частные функции от выполнения отражения?

Вы можете изменить свою политику безопасности, чтобы у кода не было разрешения на "частное отражение" при его запуске..

Конечно, это повлияет только на вашу машину.Если вы хотите повлиять на чужой компьютер, отправьте электронное письмо администратору своего компьютера и попросите администратора изменить политику безопасности пользователя, чтобы у него не было разрешения на "личное отражение".Это человек, которому принадлежит машина и сеть, в которой он работает;очевидно, у вас нет возможности изменять настройки безопасности в сети, которой вы не владеете.

Обратите внимание, что права более мощные , чем частное отражение, также должны быть ограничены.Не имеет смысла устанавливать политику, которая говорит, например, «права на частное отражение запрещены, но право на изменение политики безопасности предоставлено».Затем пользователь может просто изменить политику безопасности, чтобы повторно предоставить частное отражение для себя.

Вам также придется ограничить возможность доступа к диску.Кто-то, кто может получить доступ к диску, может просто прочитать код из сборки, изменить личные метаданные на общедоступные и загрузить сборку в обычном режиме.

Итак, ваша миссия состоит в том, чтобы убедить всех администраторов машин в мире не давать своим пользователям доступ к их собственным дискам.Я подозреваю, что вы потерпите неудачу;Я предлагаю вам найти другой способ защитить свои функции от злоупотреблений.

18 голосов
/ 16 ноября 2016

Это поздний ответ, но я считаю его обновлением, поскольку все ответы были написаны до выпуска .NET 4.6 в середине 2015 года, в котором представлен новый атрибут сборки под названием DisablePrivateReflection .

С этим атрибутом, помеченным в вашем AssemblyInfo.cs, вы можете отключить отражение над закрытыми элементами этой сборки.

Пример:

namespace DisablingPrivateReflection
{
    public class Singleton
    {
        private Singleton()
        {

        }
    }
}

И в вашем AssemblyInfo.cs добавить эту строку:

[assembly: DisablePrivateReflection]

Тогда в вашей клиентской сборке, которая ссылается на вышеупомянутую сборку, этот код завершится с ошибкой во время выполнения:

var singleton = Activator.CreateInstance(typeof(Singleton), true);

Сгенерировано исключение типа MethodAccessException с сообщением:

Попытка метода «Program.Main (System.String [])» для доступа к методу «DisablingPrivateReflection.Singleton..ctor ()» завершилась неудачей.

8 голосов
/ 02 декабря 2011

Модификаторы доступа не являются механизмом безопасности.

Если , если , вы можете запретить вызов своей функции с помощью отражения, пользователь может просто декомпилировать вашу программураспакуйте эту функцию, поместите ее в новую сборку и выполните.

1 голос
/ 14 декабря 2013
using System;
using System.Reflection;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;

class Person
{
    private string SayInternalSecure()
    {
         if (!PrivacyHelper.IsInvocationAllowed<Person>())
            throw new Exception("you can't invoke this private method");
         return "Internal Secure";
    }

    private string SayInternal()
    {
         return "Internal";
    }

    public string SaySomething()
    {
         return "Hi " + this.SayInternal();
    }

    public string SaySomethingSecure()
    {
        return "Hi " + this.SayInternalSecure();
    }

    public void BeingCalledBy()
    {
            Console.WriteLine("I'm being called by: " + new StackTrace().GetFrame(1).GetMethod().Name);
    }
}

public class MethodBaseComparer : IEqualityComparer<MethodBase> 
{
     private string GetMethodIdentifier(MethodBase mb)
     {
      return mb.Name + ":" + String.Join(";", mb.GetParameters().Select(paramInfo=>paramInfo.Name).ToArray());
     }

     public bool Equals(MethodBase m1, MethodBase m2) 
     {
        //we need something more here, comparing just by name is not enough, need to take parameters into account
        return this.GetMethodIdentifier(m1) == this.GetMethodIdentifier(m2);
     }

     public int GetHashCode(MethodBase mb) 
     {
             return this.GetMethodIdentifier(mb).GetHashCode();
     }
}

class PrivacyHelper
{
static Dictionary<Type, MethodBase[]> cache = new Dictionary<Type, MethodBase[]>();
public static bool IsInvocationAllowed<T>()
{
    Type curType = typeof(T);
    if (!cache.ContainsKey(curType))
    {
        cache[curType] = curType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).ToArray();
    }
    //StackTrace.GetFrame returns a MethodBase, not a MethodInfo, that's why we're falling back to MethodBody
    MethodBase invoker = new StackTrace().GetFrame(2).GetMethod();
    return cache[curType].Contains(invoker, new MethodBaseComparer());
}
}

public class App
{
public static void CheckCaller()
{
    Person p = new Person();

    Console.WriteLine("- calling via delegate");
    Action action = p.BeingCalledBy;
    action();

    Console.WriteLine("- calling via reflection");
    MethodInfo method = typeof(Person).GetMethod("BeingCalledBy", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine(method.Invoke(p, null));

    Console.WriteLine("- calling via delegate again");
    action = (Action)(Delegate.CreateDelegate(typeof(Action), p, method));
    action();
}

public static void Main()
{
    Console.WriteLine("Press key to run");
    Console.ReadLine();

    CheckCaller();

    Person p = new Person();
    Console.WriteLine(p.SaySomething());
    Console.WriteLine(p.SaySomethingSecure());

    MethodInfo privateMethod = typeof(Person).GetMethod("SayInternal", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine("invoking private method via Reflection:");
    Console.WriteLine(privateMethod.Invoke(p, null));

    Console.WriteLine("----------------------");

    privateMethod = typeof(Person).GetMethod("SayInternalSecure", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
    Console.WriteLine("invoking secured private method via Reflection:");
    try
    {
        Console.WriteLine(privateMethod.Invoke(p, null));
    }
    catch(Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
}
1 голос
/ 23 апреля 2012

Хотя я абсолютно согласен с идеей, что модификаторы доступа не являются функцией безопасности, просто ради программирования я немного об этом подумал, и у меня есть простой, но не очень полезный механизм борьбы с отражением с отражением: -)

Имейте в виду, это просто глупое доказательство концепции, я не принимаю во внимание универсальные методы, для этого потребуются изменения ...

Идея состоит в том, что в начале каждого частного метода, который вы хотите защитить от "незаконного" вызова, вы просто проверяете через Reflection, что вас вызывают из другого метода в этом классе, а не извне. Таким образом, вы будете использовать: новый StackTrace (). GetFrame (1) .GetMethod (); чтобы получить MethodBase вашего вызывающего и сравнить его со списком MethodInfos для вашего класса.

Вы можете добавить его во вспомогательный класс (в любом случае вам понадобится IEqualityComparer для сравнения MethodBases ...

Одна из проблем заключается в том, что вы также препятствуете некоторым правильным вызовам, таким как вызов его через делегата или через Reflection из другого вашего метода ... так что вы должны быть осторожны при его использовании.

Вы можете мою реализацию здесь

1 голос
/ 02 декабря 2011

Вы не можете, модификаторы предназначены только для разработчиков, чтобы иметь надлежащую инкапсуляцию. Во время выполнения может быть грустно, что все находится на одном уровне.

Механика отражения, обычно используется приложением, которому необходимо вызывать некоторые предварительно настроенные методы (более старые ORM) или отображать их (IDE). Было бы очень трудно, если бы этот механизм не смог этого сделать.

1 голос
/ 02 декабря 2011

Нет способа сделать это.Почему вы хотите предотвратить выполнение ваших личных функций?Обычно, если кто-то использует отражение, он знает, что делает.

0 голосов
/ 26 сентября 2018

Я бы попытался разобрать трассировку стека (https://docs.microsoft.com/en-us/dotnet/api/system.diagnostics?redirectedfrom=MSDN&view=netframework-4.7.2) и проверить динамический вызов ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...