What are the security implications for accepting anonymous methods (Action<>, Func<>) as parameters?
Asked Answered
C

2

6

Just as the title says: What, if any, are the security implications that need to be considered when using and/or passing around anonymous methods (Action<>, Func<>) in C#?

A method which accepts Action<>/Func<> seems to be a potential way for foreign code to be injected into a program. For the record, I understand that the injected method or function is not able to do inherently unsafe things in the sense of arbitrary memory access, but I would think that it could allow the calling code to call e.g. arbitrary .Net framework functions, corrupt data, or otherwise cause the application to misbehave.

Is this assumption wrong?

If it is not, what should be done to lock these down? Additionally, is there any way to validate the /Func<> that is passed into a method or function to ensure that it is of an expected form or to restrict its access to certain types and namespaces?

Also, forgive me if I'm not quite using the right terminology, I'm still learning.

Cadaverine answered 4/1, 2015 at 17:19 Comment(3)
Note also that you can inject malicious code through inheritance (by overriding virtual and abstract methods) and interface implementation. But SLaks' answer also applies for these cases. The System.String class, for instance, protects itself from this by being sealed.Abbreviation
What's the scenario? Trusted and untrusted code in the same process separated by CAS?Crowther
@Crowther I'm really asking if there are scenarios in which there is any concern. I've seen some solutions on here which use these as a way to, for instance, pass a property getter or setter to a named method by wrapping it in one of these. But that feels incorrect because there's no way, as far as I know, for the named method to guarantee or otherwise ensure that the passed Action<> or Func<> is behaving in an expected way. Is it then bad practice to use these as parameters unless the named method truly doesn't care what it does? E.g. Assert.ThrowsException<T>().Cadaverine
E
9

A method which accepts Action<>/Func<> seems to be a potential way for foreign code to be injected into a program

That is completely wrong. Whoever is calling your function and passing a delegate is, by definition, already running code in your program.
Any code which is passing a delegate can already do whatever it wants. You cannot have security boundaries within the same AppDomain. (older versions of .Net had Code Access Security, which tried to do this, but was not a good idea)

However, it can create unexpected reentrancies, which can cause issues with thread-safe code.

Entreat answered 4/1, 2015 at 17:21 Comment(3)
I think I understand. You're saying that anything which could run could just call the code itself and there's nothing that would be gained by the putative malicious code in doing so? Let's say that there's a deliberately-caused re-entrance. Would that have security risks, or just potentially destabilize the program? If I pass in an infinite loop, that could be a problem I would imagine. If so, are there design recommendations to mitigate risks? Such as using these sparingly, internally, and if public, thoroughly tested for re-entrance and instability?Cadaverine
@NickBauer: Again, unless you have an actual security boundary, there is no security to speak of. See blogs.msdn.com/b/oldnewthing/archive/2014/05/29/10529251.aspx and blogs.msdn.com/b/oldnewthing/archive/2007/08/07/…Entreat
Okay, I'm with you. But I'm still curious about what you mean regarding re-entrance, since you mentioned it. EDIT: That is, not that re-entrance is a problem, but if allowing a window for re-entrance in this way could be a problem.Cadaverine
C
2

I'm really asking if there are scenarios

Back when CAS policy was still being used (e.g. medium trust ASP.NET) a trusted piece of code could not safely call untrusted code when stack asserts are present. For example when

new SecurityPermission(Unrestricted).Assert()

was in effect the security check stack walk would stop at this point. That can lead to untrusted code not being detected. See the docs for Assert.

I'm being a little vague here because the scenario is hard to pull off and it is obsolete.


In case there is no trust boundary inside of the same process the caller already has all the power even without injecting code somewhere. No need for that.

Crowther answered 6/1, 2015 at 10:13 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.