Authorize objects?

#1

I’ve been trying to understand how you would authorize a user for a particular object. It seems that only verbs can be checked with application logic.

The problem is that user X may have privileges to call A on object P but not object Q.

I see how I could possibly hack this in the callee by requesting details.caller and then get the session details which would give the authid, which then could be looked up against a permissions db.

(Unfortunately, this doubles the crossbar call overhead.) However, this seems really awkward as each callee would have to do this manually. There’s no hook for this in crossbar. Ideally, authorize would also get the arguments to the call so that an application could have a standard argument in kwargs for say “uri object”. An alternative would be to allow dynamic uri registering/routing, which I don’t see that crossbar allows.

Thanks,

Rob

0 Likes

#2

Hi Rob!

I’m having trouble understanding your usage scenario. Could you be a bit more specific about what you want to do?

Regards,

Alex

···

Am Dienstag, 18. August 2015 13:23:24 UTC+2 schrieb Rob Nagler:

I’ve been trying to understand how you would authorize a user for a particular object. It seems that only verbs can be checked with application logic.

The problem is that user X may have privileges to call A on object P but not object Q.

I see how I could possibly hack this in the callee by requesting details.caller and then get the session details which would give the authid, which then could be looked up against a permissions db.

(Unfortunately, this doubles the crossbar call overhead.) However, this seems really awkward as each callee would have to do this manually. There’s no hook for this in crossbar. Ideally, authorize would also get the arguments to the call so that an application could have a standard argument in kwargs for say “uri object”. An alternative would be to allow dynamic uri registering/routing, which I don’t see that crossbar allows.

Thanks,

Rob

0 Likes

#3

Good Morning, Alex,

Sorry I wasn’t clear.

Alice is authorized to call read_account() on account id 123. Bob is authorized to read_account() on account 456.

How can Crossbar ensure that Alice does not read_account() on 456 in WAMP?

I understand that I can write this code myself as follows:

  1. the caller passes disclose_me

  2. the callee adds “details” to args read_account

  3. read_account validates that details.caller is not None

  4. read_account calls wamp.session.get with details.caller

  5. read_account tests if (session.authid, account_id) is authorized

This is both a lot of boilerplate on every call and incurs another round trip (4) to the dealer.

All applications I write work this way on every call.

Rob

0 Likes

#4

Hi Rob,

Good Morning, Alex,

Sorry I wasn't clear.

Alice is authorized to call read_account() on account id 123. Bob is
authorized to read_account() on account 456.

This is going beyond dynamic authorization which works on the basis of URI and WAMP action.

What you describe necessarily means looking into the application payload.

Essentially, it is application payload based authorization.

On the other hand: why not make the account ID part of the URI?

How can Crossbar ensure that Alice does not read_account() on 456 in WAMP?

It doesn't and it won't. It would be against a fundamental design paradigm we adhere strictly to: WAMP routers MUST NOT contain application logic.

I understand that I can write this code myself as follows:

1) the caller passes disclose_me
2) the callee adds "details" to args read_account
3) read_account validates that details.caller is not None
4) read_account calls wamp.session.get with details.caller
5) read_account tests if (session.authid, account_id) is authorized

This is both a lot of boilerplate on every call and incurs another round
trip (4) to the dealer.

That's how it works.

I am open to discuss ways to remove the additional roundtrip in (4) - in fact, that was once working without that roundtrip, in that CB would provide all the details to the invoked procedure: not only session ID, but auth role and all that.

However, the downside of that is a lot of additional info (which doesn't change) on each and every call.

As indicated above, we won't extend CB to do app payload based authorization - in fact, that's not in the WAMP spec, and I'd be against adding it there in the first place also.

All applications I write work this way on every call.

Rob

Cheers,
/Tobias

···

Am 21.08.2015 um 15:10 schrieb Rob Nagler:

--
You received this message because you are subscribed to the Google
Groups "Crossbar" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to crossbario+...@googlegroups.com
<mailto:crossbario+...@googlegroups.com>.
To post to this group, send email to cross...@googlegroups.com
<mailto:cross...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/crossbario/c0adc510-1723-4c17-9b4a-a8ae93e57b9d%40googlegroups.com
<https://groups.google.com/d/msgid/crossbario/c0adc510-1723-4c17-9b4a-a8ae93e57b9d%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#5

Howdy Tobias,

Thanks for the quick response.

What you describe necessarily means looking into the application payload.

One could argue ad infinitum about the difference between “application” and “framework”. I have a friend that says that anything about socket.write is application payload. WAMP is an application messaging protocol so it’s goal, I believe, is to do things that all web applications need to do. The scenario I described is in every non-trivial application.

It seems to me authorization of verbs independent of the objects they operate on leads to security holes like the Citibank URI hack:

http://www.abovetopsecret.com/forum/thread716716/pg1

On the other hand: why not make the account ID part of the URI?

This moves around the code, but doesn’t change the number of roundtrips per call or the amount of code the application programmer has to write.

This brings up other questions:

  • Does the authorizer have access to the callee’s args?

  • How can the authorizer pass state to the callee, e.g. the already parsed URI?

Thanks,

Rob

0 Likes

#6

If you mean the dynamic authorisation end-point, no, it doesn’t. For an RPC, you need to do the authorisation check in the end-point being called (I don’t use dynamic authorisation now at all), but that also requires that the client is calling it with { disclose_me: true }. It’s [relatively] easy to then run the uri, authid, selected arguments or kwargs (and perhaps the authrole) through any sort of authorisation strategy pattern (after you’ve looked up the session meta).

In pseudocode, my pattern kinda looks like this:

var myAction = action_making_factory();

session.register(function (args, kwargs, detail) {

// Caller must have disclose_me option set to true.

session.call(‘wamp.session.get’, details.caller)

.then(function (sessionMeta) {

  // Done with WAMP stuff. Hand over control to my framework.

  return myAction.authorise(sessionMeta, args, kwargs, details)

    .then(function () {

      // Authorisation passed, now do what we gotta do.

      return action.invoke(sessionMeta, args, kwargs, details);

    });

})

.catch(function (err) {

  // Catch authorisation or other errors here.

  session.log(err);

  throw err;

});

});

Regards,

Andrew Eddie

···

On Saturday, 22 August 2015 00:49:22 UTC+10, Rob Nagler wrote:

  • Does the authorizer have access to the callee’s args?
0 Likes

#7

Hi Andrew,

Thanks for the pseudo-code. It’s quite complicated, unfortunately.

I’ll give my $.02 on why this approach is problematic below. I hope this is helpful…

When the application programmer hand codes authorization, security holes pop up in unexpected places. For example, the code “throw err” above is problematic: It exposes an internal problem with authorization. Crossbar returns such exceptions literally to the client, e.g.

add err: {“error”:“wamp.error.authorization_failed”,“args”:[“failed to authorize session for calling procedure ‘com.example.add’: ApplicationError(‘wamp.error.runtime_error’, args = (‘DETAILS OF THE INTERNAL EXCEPTION EXPOSED HERE’,), kwargs = {})”],“kwargs”:{}}

Another issue is that increasing the call overhead worsens denial of service attacks. It is much better if the front-end (Crossbar) denies the service. The more that that application has to do, the more likely an attacker will find ways to penetrate the system.

In general, the default authorization should be “no”, not “yes”. Without integrated authentication/authorization policies built into the framework, you end up having to ensure that all endpoints assert the validity of the user’s role against allowed roles, even if that role is “anonymous”. As I understand Crossbar, it means I have to write code which traps all requests. That basically requires a centralized dispatcher through which all requests pass. That’s a lot of duplicate effort on the part of all the developers who might want to use Crossbar.

Rob

0 Likes

#8

Hi Andrew,

Thanks for the pseudo-code. It's quite complicated, unfortunately.

It depends on what you are trying to achieve. If you don't want to use
dynamic authorisation, these are the steps you can include:

1. You must register the procedure to be called.
2. If you want information about the caller, you must call the session
meta end-point.
3. You must have your business logic authorise the request.
4. You must handle the request and provide a response.

When the application programmer hand codes authorization, security holes pop
up in unexpected places. For example, the code "throw err" above is
problematic: It exposes an internal problem with authorization. Crossbar
returns such exceptions literally to the client, e.g.

add err: {"error":"wamp.error.authorization_failed","args":["failed to
authorize session for calling procedure 'com.example.add':
ApplicationError('wamp.error.runtime_error', args = ('DETAILS OF THE
INTERNAL EXCEPTION EXPOSED HERE',), kwargs = {})"],"kwargs":{}}

That's a fair comment, except that the snippet was not intended to
show all of that sort of thing. I dumb the error down before returning
it.

Another issue is that increasing the call overhead worsens denial of service
attacks. It is much better if the front-end (Crossbar) denies the service.

Perhaps, but that would require you to compile a plugin or something
into Crossbar itself to be able to do all that.

The more that that application has to do, the more likely an attacker will
find ways to penetrate the system.

I don't think that's a reasonable case to make because shifting code
from one place to another doesn't necessarily make it more secure. You
might be lucky, you might not.

In general, the default authorization should be "no", not "yes".

It is (see Static Authorisation in the docs).

Without
integrated authentication/authorization policies built into the framework,

Into the Crossbar framework??

you end up having to ensure that all endpoints assert the validity of the
user's role against allowed roles, even if that role is "anonymous".
As I understand Crossbar, it means I have to write code which traps all requests.
That basically requires a centralized dispatcher through which all requests
pass. That's a lot of duplicate effort on the part of all the developers who
might want to use Crossbar.

I'm not totally clear on what you are suggesting to do, but you
wouldn't do that.

Regards,
Andrew Eddie

···

On 27 August 2015 at 14:51, Rob Nagler <> wrote:

0 Likes

#9

Does the authorizer have access to the callee’s args?

No

How can the authorizer pass state to the callee, e.g. the already parsed URI?

It can’t

···

Am Freitag, 21. August 2015 16:49:22 UTC+2 schrieb Rob Nagler:

Howdy Tobias,

Thanks for the quick response.

What you describe necessarily means looking into the application payload.

One could argue ad infinitum about the difference between “application” and “framework”. I have a friend that says that anything about socket.write is application payload. WAMP is an application messaging protocol so it’s goal, I believe, is to do things that all web applications need to do. The scenario I described is in every non-trivial application.

It seems to me authorization of verbs independent of the objects they operate on leads to security holes like the Citibank URI hack:

http://www.abovetopsecret.com/forum/thread716716/pg1

On the other hand: why not make the account ID part of the URI?

This moves around the code, but doesn’t change the number of roundtrips per call or the amount of code the application programmer has to write.

This brings up other questions:

  • Does the authorizer have access to the callee’s args?
  • How can the authorizer pass state to the callee, e.g. the already parsed URI?

Thanks,

Rob

0 Likes

#10

That’s a fair comment, except that the snippet was not intended to

show all of that sort of thing. I dumb the error down before returning

it.

Sorry for misunderstanding your intent.

I don’t think that’s a reasonable case to make because shifting code

from one place to another doesn’t necessarily make it more secure. You

might be lucky, you might not.

I’m not discussing shifting code, but sharing and reusing a common and necessary implementation of authorization across all practical distributed applications.

In general, the default authorization should be “no”, not “yes”.

It is (see Static Authorisation in the docs).

Subject-verb authorization is insufficient for any practical application.

Without

integrated authentication/authorization policies built into the framework,

Into the Crossbar framework??

Security needs to be written into the framework, not bolted on.

you end up having to ensure that all endpoints assert the validity of the

user’s role against allowed roles, even if that role is “anonymous”.

As I understand Crossbar, it means I have to write code which traps all requests.

That basically requires a centralized dispatcher through which all requests

pass. That’s a lot of duplicate effort on the part of all the developers who

might want to use Crossbar.

I’m not totally clear on what you are suggesting to do, but you

wouldn’t do that.

This is where we disagree. The creators of Unix designed authentication and subject-verb-object authorization into the kernel in 1970. Windows, OTOH, did not have a security model at its core and has been struggling ever since.

It seems reasonable to expect at least this level of security in frameworks in 2015. Verb-only security is no security at all. The framework has to restrict which file to write to, not just allowing the user to write to any file.

When I first read about Crossbar/WAMP, I wrote an internal memo saying I think I finally found a reasonable framework. It doesn’t do much, but it does quite a bit more than many frameworks out there. Without subject-verb-object authorization, it is losing its appeal.

Rob

···

On Thursday, August 27, 2015 at 3:15:52 AM UTC-6, Andrew Eddie wrote:

0 Likes

#11

does quite a bit more than many frameworks out there. Without
subject-verb-object authorization, it is losing its appeal.

WAMP does subject-verb-object-based authorization:

verb: WAMP action (one of 4)
object: The URI the originator want to act on

Dynamic authorizers get all 3 bits of info.

Cheers,
/Tobias

···

subject: caller/publisher/.. session that originates the action

0 Likes

#12

Security needs to be written into the framework, not bolted on.

     > you end up having to ensure that all endpoints assert the
    validity of the
     > user's role against allowed roles, even if that role is "anonymous".
     > As I understand Crossbar, it means I have to write code which
    traps all requests.
     > That basically requires a centralized dispatcher through which
    all requests
     > pass. That's a lot of duplicate effort on the part of all the
    developers who
     > might want to use Crossbar.

I don't know what above would mean exactly, but fact is, you can have subject-verb-object based authorization in CB both statically defined (which means you don't have to write any code, but just "rules"), or you can have a dynamic authorizer, which is code written by you which is called by CB to authorize a WAMP action. You can do any kind of authorization in such dynamic authorizers.

Dynamic authorizers can be written in any WAMP support language, and can talk over any CB supported transport.

E.g. you can have your authorizer be a Java piece of code, while the rest of your system is in X.

If you write a dynamic authorizer in Python/Twisted, then it can be run inside the same process as a CB router. It'll be just a regular function call.

If it runs out-of-process, you can still have it over Unix domain socket, which means the overhead and additional roundtrip is very small.

Actual authorization code is NOT framework code, as it depends on app design. Hence, authorization code must either by generic (the static auth. stuff in CB) or app specific, and hence must be (at least) logically seperated from any router/framework code.

This last paragraph summarizes a fundamental design principle of WAMP: separation from app specific code .. routers must not container app logic.

Cheers,
/Tobias

···

    I'm not totally clear on what you are suggesting to do, but you
    wouldn't do that.

This is where we disagree. The creators of Unix designed authentication
and subject-verb-object authorization into the kernel in 1970. Windows,
OTOH, did not have a security model at its core and has been struggling
ever since.

It seems reasonable to expect at least this level of security in
frameworks in 2015. Verb-only security is no security at all. The
framework has to restrict which file to write to, not just allowing the
user to write to any file.

When I first read about Crossbar/WAMP, I wrote an internal memo saying I
think I finally found a reasonable framework. It doesn't do much, but it
does quite a bit more than many frameworks out there. Without
subject-verb-object authorization, it is losing its appeal.

Rob

--
You received this message because you are subscribed to the Google
Groups "Crossbar" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to crossbario+...@googlegroups.com
<mailto:crossbario+...@googlegroups.com>.
To post to this group, send email to cross...@googlegroups.com
<mailto:cross...@googlegroups.com>.
To view this discussion on the web visit
https://groups.google.com/d/msgid/crossbario/920bcf9e-ca62-47b5-ae96-bd785a49af04%40googlegroups.com
<https://groups.google.com/d/msgid/crossbario/920bcf9e-ca62-47b5-ae96-bd785a49af04%40googlegroups.com?utm_medium=email&utm_source=footer>.
For more options, visit https://groups.google.com/d/optout.

0 Likes

#13

WAMP does subject-verb-object-based authorization:

subject: caller/publisher/… session that originates the action

verb: WAMP action (one of 4)

object: The URI the originator want to act on

Dynamic authorizers get all 3 bits of info.

I get it now. Thanks.

Rob

0 Likes