Quiz: Who can access your state?


Without compiling or running this code, can you tell if Malicious will be able to “steal” the password set in an instance of Child?   Why or why not?

 

    public class Base

    {

         protected String _password;

    }

    public class Child : Base

    {

        public Child(string password)

        {

            _password = password;

       }

    }

    public class Malicious : Base

    {

        public String StealPassword(Child child)

        { return child._password; }

    }

 

Comments (52)

  1. Ross says:

    Nope, _password is essentially a protected member of Child as far as Malicious can see (or not), the fact that Malicious also extends Base is irrelevant.

  2. MS says:

    <code><pre>

    public class Malicious : Base

    {

    public string StealPassword (Child child)

    {

    return (child as Base)._password;

    }

    }

    </pre></code>

  3. Ross says:

    Nope casting child should still not work, _password is protected in Base.

  4. Peter says:

    No, it can’t because _password in Base class is protected.

  5. Ben Lowery says:

    Yes, it can. All derived classes have access to their parent’s protected parts. Therefore, both Child and Malicious have access to _password, which is part of Base. Just because the type passed in is Child doesn’t make _password any less accessible to a Malicious. The visibility of _password is scoped by the class that declares it, not the class being instantiated.

  6. Mike Kolitz says:

    Since Malicious derives from Base, it could read the _password set in Base, but not in Child. Malicious doesn’t have any access to Child._password, since it would technically be protected and does not have a public property exposing it.

  7. Bharani Mantrala says:

    I agree with Ben.

  8. Of course it can, protected means that the field can be accessed in derived classes, in contrast with private, that means that the field can be accessed only in the class where it is defined.

  9. Roy J. Salisbury @ VsDevCentral says:

    As the code is written, it should not even compile. So the answer to your question is NO.

    However, if I can change a single line of cade, I would change:

    return child._password;

    into

    return base._password;

    No reason to even pass in Child as a paramater to the method (don’t need it).

    P.S. That "base" is not the class Base, but the keyword base.

  10. Laura T. says:

    No, the password cannot be stealed.

    _password is instance member of Child and is qualified as non visible outside the instance.

    Both malicious and child have their own _password member, but still qualified protected out of their context.

    Malicious has the context of Malicious instance so it cannot access instance member of child.

    This should be catched by the compiler.. may I check it now?

  11. Roy J. Salisbury @ VsDevCentral says:

    Now that I think about it a bit more, you dont even need "base._password" .. just remove "child." and your still good (I just always prefix my variables (this._whatever, base._whatever, ect).

  12. Jeff Parker says:

    Hmm, interesting one, I am of course going to have to try this out but I am going to have to say no it can’t and I come to this conclusion by looking at the other accessibility levels, and I am guessing the instance of child you are passing to the method StealPassword wouldn’t work, because it is not part of the surounding class, which is a different instance. The only way I can see if this does work is set protection level at protected internal. There is really not much you can do about this though, hmm a very perplexin question. Well off to try and no I won’t post the definite answer either but I got to find out it is bugging me.

  13. Mike Kolitz says:

    Marius and Ben – the _password in Child is not the same as the _password in Base, though. Child._password is it’s own instance, isn’t it?

  14. Laura T. says:

    C# standard:

    10.5.3 Protected access for instance members

    "… Let B be a base class that declares a protected instance member M, and let D be a class that derives from B. Within the class-body of D, access to M can take one of the following forms:…"

    One can assume that access to _password can be made only from the class { } block. Malicious is not inside of Childs class {} block, so it cannot access Childs protected members.

  15. Russ says:

    No, malicious would not have access to child._password. _password is scoped to the instance of child. Only child would have access to this member. Protected members are only accessible from the inside the instance of the object. No external classes (even of the same type or of a base type) have access to internal(protected) members of another instance. Malicious can access base._password but this would be an instance of _password that is scoped internal to itself and therefore not the same password that child has.

  16. Jerry Pisk says:

    Laura is right, however in this case Malicious is the D class that derives from Base as well. So it will have access to _protected. However, my guess is that child has to be cast to Base before you can steal the password. My answer is that yes, Malicious can steal the password but not as coded here, which shouldn’t compile.

  17. Ross says:

    As far as I can see you can only get the value of child._password through reflection. None of the "Yes" votes have changed my mind 😉

  18. A class can access protected members even of instances other than the current instance (i.e. passed as a parameter), however a restriction of the protected access modifier is that you can only access ancestor protected members off of a property of the type of the current method. i.e.

    public String StealPassword(Child child) – no access to protected members

    public String StealPassword(Malicious child) – access to protected members

  19. From the C# Language Reference on MSDN:

    "A protected member of a base class is accessible in a derived class only if the access takes place through the derived class type"

    So what Russ said is true, Malicious would only be able to access _password is the object being referenced were of type Malicious (which it is of course, not).

    An instantiated object of type C, inheriting from B, would be able to access the protected base members of another instantiated object of type C, but an instantiated object type D, also inheriting from B, would not be able to access the protected base members of an instantiated object of type C (if I am reading this right).

  20. Surya says:

    You can access the base class protected member by directly calling the base class. So if you would like to steal the password you will have to write

    public class Base

    {

    protected String _password;

    }

    public class Child : Base

    {

    public Child(string password)

    {

    _password = password;

    }

    }

    public class Malicious : Base

    {

    public String StealPassword(Child child)

    { return base._password; }

    }

  21. Surya says:

    Actually I worded it wrong above. You cannot steal the child’s password, but you might as well have access to the member variable, which again wouldn;t amount to anything i.e. it will not be the same as in Child class

  22. Correct. base (keyword base) refers to the instantiated instance of type Malicious’s copy of the _password member, not the passed in object of type Child, so you would still not be able to steal the password from the child.

  23. Roy J. Salisbury @ VsDevCentral says:

    Opps.. your right… _password would be a seperate instance in the Child. But my original statement stands.. The code should not compile anyway becuase it’s a compilier error to even try to do what is suggested (return child._password).

  24. Actually, I’m going to qualify by saying that Russ was half-right. I think this statement:

    "No external classes (even of the same type or of a base type) have access to internal(protected) members of another instance"

    Is not true, in fact, quite the opposite. ONLY objects of the same type or base type would be able to reference an instantiated object’s protected members.

    (Brad, let us off the hook – I’m dying to know if we are all barking up the wrong tree)

  25. Steven Padfield says:

    Yes. Because _password is a protected member of Base, it is visible to any derived class of Base, regardless of the particular concrete types and instances in question.

  26. Matthew W. Jackson says:

    No, you cannot access _password. You can only access protected instance members on your own instance. I don’t even think a class can access an the base class’ protected members of another object of the same class.

    For example, I don’t think that Child could take another instance of Child and access its protected members, but I could be wrong on that point. It turns out that, until recently, you could construct objects of the base class using a base class protected constructor, and I would have never expected that behavior, so I could be wrong in this case.

    I’ve come across this "problem" before with regard to System.Windows.Forms.Control. I needed to access a protected member of another control class from my control class. I say "problem" because the real problem was a member being made protected when I think it could have safely been public.

  27. Matthew W. Jackson says:

    I take back my statement about instances of the same derived type. I just remebered that in order for static methods to access protected members, this would have to be allowed.

    So my answer is still no on Malicious accessing Child’s _password, but I do now think that Malicious could access another Malicious’ _password.

  28. Sergio Pereira says:

    I’m surprised that so many people are confused with this question 🙂 I’m going to put it in my list for interviewing cadidates!

  29. Jerry Pisk says:

    From the C# language specification (3.5.3 Protected access for instance members):

    When a protected instance member is accessed outside the program text of the class in which it is declared, and when a protected internal instance member is accessed outside the program text of the program in which it is declared, the access is required to take place through an instance of the derived class type in which the access occurs.

    So Malicious can only access Base’s protected members through an instance of its own, not through an instance of Base. So I stand corrected – Malicious can steal Child’s password, if it has enough privileges to do it through reflection or CodeDom (and at that point it doesn’t have to derive from the same base class).

  30. Don says:

    Before I worried about this problem, I’d want to make sure that the reflection security settings were turned on (http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/html/cpconsecurityconsiderationsforreflection.asp) and that I understood what my serialization settings are. It’s kind of silly to be worrying about how many tumblers the lock on your door has if you forget to lock it in the first place (it’s trivial to reflect out not just protected but private data if the security settings aren’t high enough).

    I’d also want to ask the architectural question of why am I handing secret data to code that I don’t trust and shouldn’t I look for a way to expose the services that the secret unlocks without needing to expose the secret? If I can’t find a way to do that with confidence, I’ll probably never be able to solve my security problems.

  31. Len Weaver says:

    Using the Reflection API you can access just about everything. The answer to this type of question is always ‘Yes’.

  32. Anon says:

    Len,

    Context is important. The queation was not ‘is it possible’. The question was ‘is it possible using code like this.’

  33. No… Malicious cannot steal the password for Child.

    —— The question is simple ——

    Does Malicious have access to _password within Child and the answer is NO due to the protection level of _password (protected).

    —— There is nothing tricky about the code ——

    Malicious inherits from Base just the same as Child but Malicious is not trying to reference _password in Base. It is trying to access _password within Child as the return value for StealPassword and it simply cannot do that because _password is a protected member.

  34. RJ says:

    Very popular question! I didn’t read everything, but looks like no one has mentioned this:

    Malicious __gc* back = reinterpret_cast<Malicious __gc*>(child);

    Now the fake instance of Malicious has access to everything. But I’m guessing "Safe" code is not allowed to use reinterpret_cast?

  35. Goodie says:

    No; Malicious cannot access the protected member of any Child instance.

    The outcome would be no different if the StealPassword method were moved to the Child class:

    public class Base

    {

    protected String _password;

    }

    public class Child : Base

    {

    public Child(string password)

    {

    _password = password;

    }

    public String StealPassword(Child child)

    { return child._password; }

    }

  36. EbuAhmed says:

    public class Base

    {

    protected String _password;

    }

    public class Child : Base

    {

    public Child(string password)

    {

    _password = password;

    }

    }

    public class Malicious : Child

    {

    public String StealPassword(){ return _password; }

    }

  37. Daren Thomas says:

    I tried it out: It doesn’t even compile!!!

    Casting to Base doesn’t work either (has to be Malicious or derived from Malicious).

    Casting to Base and then to Malicious: ((Malicious)((Base)child)) throws a runtime exception.

    EbuAhmeds version doesn’t work either, because we are trying to prye on an existing object…

    If you don’t have a copy of the Snippet Compiler, get one!

  38. Laura T. says:

    Daren, I’m glad it does not compile. Otherwise, why there would be any access scope modifiers anyway? protected, private. They must do something. If I say protected, it’s mine and my familys (my protection). If I say private, it’s mine only. My children "derive" from me, but they still cannot access what’s my private.

    Sergio, It’s interesting and a bit surprising the confusion in this matter, but not all things are intiutive and not every one come from OO background.

  39. John Tobler says:

    Just musing (without trying out anything): what if String_password is declared static?

  40. John Tobler says:

    Excuse me, I meant

    protected static String _password;

    in Base.