returning a subclass through an interface

A

Andy Fish

Hi,

I am writing an API call which returns an object of type X. In my code, I
build an object which is of type Y - a subclass of X.

I'm worried that if I return the object Y, the caller will be able to use
reflection or a debugger to find out about the extra properties of Y. Is
this concern valid or is there something inherent that stops him doing this?

assuming my concern is valid, I need to make a "clone" of Y but for the
clone to be a superclass (i.e. X). Is there any clever way of doing this?
The class X only contains public immutable properties and has no methods so
there is no need to deep copy.

TIA

Andy
 
C

Chris Uppal

Andy said:
I am writing an API call which returns an object of type X. In my code, I
build an object which is of type Y - a subclass of X.

I'm worried that if I return the object Y, the caller will be able to use
reflection or a debugger to find out about the extra properties of Y. Is
this concern valid or is there something inherent that stops him doing
this?

There's nothing much stopping it; if Y is public then the caller could even
just downcast the "X" into a Y.

I'm curious as to why you want the extra protection ? It's not normally
something that you need.

assuming my concern is valid, I need to make a "clone" of Y but for the
clone to be a superclass (i.e. X). Is there any clever way of doing this?
The class X only contains public immutable properties and has no methods
so there is no need to deep copy.

?? Has no methods ??

Anyway, assuming that you don't mean that the way it sounds (and also assuming
that you have good reason to want give your "Y" more protection than the
language directly affords), what you could do is return an object that
/contains/ your Y, and implements the public methods of X by delagating them to
the Y.

Of course, that would still be open to abuse -- there's no way of preventing
someone using a debugger, or reflection (plus an open security policy), or JNI,
or even a custom JVM, from "getting at" the Y.

-- chris
 
X

xarax

Chris Uppal said:
There's nothing much stopping it; if Y is public then the caller could even
just downcast the "X" into a Y.

I'm curious as to why you want the extra protection ? It's not normally
something that you need.



?? Has no methods ??

Anyway, assuming that you don't mean that the way it sounds (and also assuming
that you have good reason to want give your "Y" more protection than the
language directly affords), what you could do is return an object that
/contains/ your Y, and implements the public methods of X by delagating them to
the Y.

Of course, that would still be open to abuse -- there's no way of preventing
someone using a debugger, or reflection (plus an open security policy), or JNI,
or even a custom JVM, from "getting at" the Y.

The general approach to prevent downcasting is to
protect the subtype somehow. (Forget about stopping
a debugger. There may be someway to prevent the
debugger from seeing the true type using a security
mechanism, but I don't know how or why you would
do that.)

Another way is to specify the super class as an
interface type and use a protected/private inner
class to implement that interface. Downcasting
would not show anything useful.
 
J

John C. Bollinger

Andy said:
I am writing an API call which returns an object of type X. In my code, I
build an object which is of type Y - a subclass of X.

I'm worried that if I return the object Y, the caller will be able to use
reflection or a debugger to find out about the extra properties of Y. Is
this concern valid or is there something inherent that stops him doing this?

Pretty much nothing prevents such analysis. On the other hand, nothing
prevents a user from digging Y.class out of your jar and running it
through javap, either. As to whether or not the concern is _valid_, I'd
say you need to make a good case for why the caller must *at all costs*
be prevented from doing what you describe before I would accept the
concern as valid.
assuming my concern is valid, I need to make a "clone" of Y but for the
clone to be a superclass (i.e. X). Is there any clever way of doing this?

Construct and return an X in the first place? I don't see the point of
an object that is not an X, but yet is indistinguishable from one
despite scrutiny.
The class X only contains public immutable properties and has no methods so
there is no need to deep copy.

I hope you don't mean that X exposes its fields to the world. As long
as access to its properties goes through accessor methods you have a
great deal of flexibility, including a variety of ways to accomplish
some of the things I imagine you might be trying to do. Before I make
any specific recommendation, however, I need to know what things you
actually are trying to do. (I have a vivid imagination. :) )


John Bollinger
(e-mail address removed)
 
A

Andy Fish

John C. Bollinger said:
Pretty much nothing prevents such analysis. On the other hand, nothing
prevents a user from digging Y.class out of your jar and running it
through javap, either. As to whether or not the concern is _valid_, I'd
say you need to make a good case for why the caller must *at all costs* be
prevented from doing what you describe before I would accept the concern
as valid.


Construct and return an X in the first place? I don't see the point of an
object that is not an X, but yet is indistinguishable from one despite
scrutiny.


I hope you don't mean that X exposes its fields to the world. As long as
access to its properties goes through accessor methods you have a great
deal of flexibility, including a variety of ways to accomplish some of the
things I imagine you might be trying to do. Before I make any specific
recommendation, however, I need to know what things you actually are
trying to do. (I have a vivid imagination. :) )

OK, here's a sample. The API returns a PersonDTO (Data Transfer Object). to
do this, it gets a rich, functional 'person' object (meant for internal use
only) from the business services and copies the information into the DTO.

PersonDTO getPersonDetails (int personId) {
PersonObject p = BusinessServices.GetPerson(personId);
PersonDetails pd = new PersonDetails();
pd.firstName = p.firstName;
pd.lastName = p.lastName;
pd.AddressLine1 = p.AddressLine1;
... etc etc
return pd;
}

now, if PersonObject was a subclass of PersonDTO, I wouldn't have to copy
all the fields; I could just return p. However, there are some properties of
PersonObject I definitely don't want the caller to know about.

Andy
 
S

Stefan Schulz

OK, here's a sample. The API returns a PersonDTO (Data Transfer Object).
to
do this, it gets a rich, functional 'person' object (meant for internal
use
only) from the business services and copies the information into the DTO.

PersonDTO getPersonDetails (int personId) {
PersonObject p = BusinessServices.GetPerson(personId);
PersonDetails pd = new PersonDetails();
pd.firstName = p.firstName;
pd.lastName = p.lastName;
pd.AddressLine1 = p.AddressLine1;
... etc etc
return pd;
}

now, if PersonObject was a subclass of PersonDTO, I wouldn't have to copy
all the fields; I could just return p. However, there are some
properties of
PersonObject I definitely don't want the caller to know about.

I'd use a Decorator that implements PersonDTO, but denies any further
operations. This will (of course) not be debug-proof, but the attacker
might just as well look at the Info while your new object is constructed,
so you will not achive 100% security in any case.
 
J

John C. Bollinger

Andy said:
OK, here's a sample. The API returns a PersonDTO (Data Transfer Object). to
do this, it gets a rich, functional 'person' object (meant for internal use
only) from the business services and copies the information into the DTO.

PersonDTO getPersonDetails (int personId) {
PersonObject p = BusinessServices.GetPerson(personId);
PersonDetails pd = new PersonDetails();
pd.firstName = p.firstName;
pd.lastName = p.lastName;
pd.AddressLine1 = p.AddressLine1;
... etc etc
return pd;
}

now, if PersonObject was a subclass of PersonDTO, I wouldn't have to copy
all the fields; I could just return p. However, there are some properties of
PersonObject I definitely don't want the caller to know about.

That doesn't tell me anything I hadn't already gleaned from your last
message. What I don't understand is why it is not sufficient that the
method's return type is specified as PersonDTO. Yes, a malicious
programmer who obtained your library could hack into the details at
runtime via reflection or a debugger, but is that an eventuality that
you really need to worry about? Is it more serious than the possibility
that the same malicious programmer might extract any class he wants from
your library jar and decompile it? Or even insert a modified version?
Is the program even going to run in an environment that exposes it to
these risks?

You would gain some measure of protection by making PersonObject
package-private (if you haven't already) but someone seriously out to
crack your code _will_. What are the consequences if someone does? Is
partial protection against those consequences worth the effort?

In general I wonder whether your application might benefit from some
refactoring. The concept of making PersonObject a subclass of PersonDTO
simply to avoid copying fields seems rather strange to me (and the idea
is the source of your present problem). I can't comment further on
that, however, because I haven't enough code to see the big picture.


John Bollinger
(e-mail address removed)
 
A

Andy Fish

John C. Bollinger said:
That doesn't tell me anything I hadn't already gleaned from your last
message. What I don't understand is why it is not sufficient that the
method's return type is specified as PersonDTO. Yes, a malicious
programmer who obtained your library could hack into the details at
runtime via reflection or a debugger, but is that an eventuality that you
really need to worry about? Is it more serious than the possibility that
the same malicious programmer might extract any class he wants from your
library jar and decompile it? Or even insert a modified version? Is the
program even going to run in an environment that exposes it to these
risks?

Thanks John (and others) for the replies. What I was concerned about is, say
the person object contains details about that person's privileges. If a
hacker could change those privileges with a debugger they might be able to
do things they aren't supposed to do.

However, I take your point about decompiling. If someone running in the same
JVM wanted to get those privileges they ultimately could, because in the end
my code is just a bunch of routines that access some underlying data store,
and the JVM must have access to that data store.

so I guess cases where I realistically need to worry about being hacked are
where someone is calling the API from outside the JVM (e.g. SOAP). In this
case, as long as I ensure that only the public fields (i.e. those from
PersonDTO) get transmitted across the wire, I am OK.

Unfortunately that brings up another problem - to maximise the ability of
reusing the interface in different places, the DTO object should be
serializable. However, the Person object will definitely not be serialisable
so that might put the kibosh on the whole idea
 
S

Stefan Schulz

Thanks John (and others) for the replies. What I was concerned about is,
say the person object contains details about that person's privileges. If
a hacker could change those privileges with a debugger they might be
able to do things they aren't supposed to do.

In that case you definitly need to re-think your security design. You
should
always authorize any "privileged" operation in the operation context, not
in some user context. You should also keep authorization information
directly
tied to some user (maybe by using a Certificate for that user)

Ultimately, however, if your cracker has your application in her debugger,
you've lost anyway. She can just remove the access check methods, or make
them accept anything.
However, I take your point about decompiling. If someone running in the
same JVM wanted to get those privileges they ultimately could, becausein
the end my code is just a bunch of routines that access someunderlying
data store, and the JVM must have access to that data store.
Exactly.

so I guess cases where I realistically need to worry about being hacked
are where someone is calling the API from outside the JVM (e.g. SOAP).
In this case, as long as I ensure that only the public fields (i.e. those
from PersonDTO) get transmitted across the wire, I am OK.
Exactly.

Unfortunately that brings up another problem - to maximise the ability of
reusing the interface in different places, the DTO object should be
serializable. However, the Person object will definitely not be
serialisable so that might put the kibosh on the whole idea

This merely goes to show that the Person class should not inherit from
DataTransferObject, but instead have some createDTA() method that
constructs one.
 
Y

Yamin

Thanks John (and others) for the replies. What I was concerned about is, say
the person object contains details about that person's privileges. If a
hacker could change those privileges with a debugger they might be able to
do things they aren't supposed to do.

However, I take your point about decompiling. If someone running in the same
JVM wanted to get those privileges they ultimately could, because in the end
my code is just a bunch of routines that access some underlying data store,
and the JVM must have access to that data store.

so I guess cases where I realistically need to worry about being hacked are
where someone is calling the API from outside the JVM (e.g. SOAP). In this
case, as long as I ensure that only the public fields (i.e. those from
PersonDTO) get transmitted across the wire, I am OK.

There are cases that you WILL need to worry this. Never worry about
someone debugging the code as they can debug any code. You shouldn't
even worry about people calling it outside the JVM. Things you should
worry about are:

1. If the person object is going to be saved to a file. Then you do
have a security problem. One that should force you to override some
of the encoding or better yet, make it a separate type.

2. If it is going to be sent over a network via RPC or other means.
Once again, your raw data now in the person object is going to be
visible by others snooping on the line, or someone who writes a
customized receiver (client program).

3. If you guys leave debug/toString statements in code that might
print out the more detailed information.

....
Yamin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top