security in task queue servlets

83 views
Skip to first unread message

Patrick Linskey

unread,
Jan 30, 2010, 4:07:55 PM1/30/10
to Google App Engine
Hi,

I'd like to programmatically ensure that my task queue servlets are
only invoked via the task queue. I've got a security constraint in my
web.xml, but I'd like to also check in code to avoid any potential mis-
configuration in the future.

Is there any supported means to do such a check?

I tried looking at the contents of the HttpServletRequest (isUserInRole
(), getAuthType(), getUserPrincipal(), getRemoteName()), to no avail.
I also tried UserServiceFactory.getUserService().isAdmin(), but
received an exception informing me that no user was logged in.

I can see that there are a number of task queue-specific HTTP headers.
Currently, I'm checking that X-AppEngine-TaskRetryCount is present,
and if so, assuming that the request has come from the task queue and
that it's therefore safe to process. Empirically, it looks like GAE
strips out the X-AppEngine-TaskRetryCount header when I specify it in
a curl-sourced request. Is this a safe assumption to rely on? Are
there plans to document a reliable way to ensure servlet security in a
task queue environment? Is there something else that I'm missing?

Also, in an ideal world, it'd be nice if request.isUserInRole("admin")
would return true at the appropriate times.

Thanks,

-Patrick

fhtino

unread,
Feb 1, 2010, 1:43:20 PM2/1/10
to Google App Engine
IMHO you're on a wrong way. Use web.xml contrains and no other
things.
HttpHeaders are very easy to create and send with a http request.

fabrizio


On Jan 30, 10:07 pm, Patrick Linskey <plins...@gmail.com> wrote:
> ...

Eli Jones

unread,
Feb 1, 2010, 2:02:42 PM2/1/10
to google-a...@googlegroups.com
If you have a compelling reason for really locking down the task queue url (and Require Admin login isn't enough), you could create a mechanism that creates a task name for each queued task.. and the task verifies that its name is "correct".

You could have the task use the X-AppEngine-TaskName header to check its name..

So.. when you add a task to the queue.. you do something like this:

taskName = getUniqueTaskName()
nameHash = getHash(taskName)

taskqueue.add(url    = '/myTaskQueue', countdown = 0,
              name   = taskName,
              params = {'nameHash' : nameHash})

and.. in the first part of the /myTaskQueue code.. you could have it verify that the 'nameHash' param is equal to getHash() of the TaskName you grab from the header..




--
You received this message because you are subscribed to the Google Groups "Google App Engine" group.
To post to this group, send email to google-a...@googlegroups.com.
To unsubscribe from this group, send email to google-appengi...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en.


Patrick Twohig

unread,
Feb 1, 2010, 3:22:18 PM2/1/10
to google-a...@googlegroups.com
I believe that the App Engine injects the pertinent information from the Users service.  For instance, when you call HttpServletRequest.getUserPrinicpal(), you're getting values injected by the UsersService.
--
Patrick H. Twohig.

Namazu Studios
P.O. Box 34161
San Diego, CA 92163-4161

Office: 619.862.2890 x100
Cell: 619.453.5075
Twitter: @svm_invictvs
IRC: svm_in...@irc.freenode.net ##java, #android-dev, #iphonedev, #appengine

http://www.namazustudios.com/

This communication, and any attachments, shall be considered confidential and proprietary information of Namazu Studios LLC.  This message, and attachments, are intended for the listed recipients only.  If you are not one of the intended recipients, please destroy all copies of this communication.

Patrick Linskey

unread,
Feb 1, 2010, 3:26:33 PM2/1/10
to Google App Engine
From what I can tell, it doesn't seem to do anything with the user
principal in the case where an unauthenticated servlet fires off a
task queue request.

The task queue docs indicate that requests from the task queue will be
executed with admin rights, but I can't seem to find any way to ensure
that this is the case from code.

Thanks,

-Patrick

On Feb 1, 12:22 pm, Patrick Twohig <patr...@namazustudios.com> wrote:
> I believe that the App Engine injects the pertinent information from the
> Users service.  For instance, when you call
> HttpServletRequest.getUserPrinicpal(), you're getting values injected by the
> UsersService.
>
>
>
>
>
> On Mon, Feb 1, 2010 at 11:02 AM, Eli Jones <eli.jo...@gmail.com> wrote:
> > If you have a compelling reason for really locking down the task queue url
> > (and Require Admin login isn't enough), you could create a mechanism that
> > creates a task name for each queued task.. and the task verifies that its
> > name is "correct".
>
> > You could have the task use the X-AppEngine-TaskName header to check its
> > name..
>
> > So.. when you add a task to the queue.. you do something like this:
>
> > taskName = getUniqueTaskName()
> > nameHash = getHash(taskName)
>
> > taskqueue.add(url    = '/myTaskQueue', countdown = 0,
> >               name   = taskName,
> >               params = {'nameHash' : nameHash})
>
> > and.. in the first part of the /myTaskQueue code.. you could have it verify
> > that the 'nameHash' param is equal to getHash() of the TaskName you grab
> > from the header..
>

> >> google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com>


> >> .
> >> For more options, visit this group at
> >>http://groups.google.com/group/google-appengine?hl=en.
>
> >  --
> > You received this message because you are subscribed to the Google Groups
> > "Google App Engine" group.
> > To post to this group, send email to google-a...@googlegroups.com.
> > To unsubscribe from this group, send email to

> > google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com>


> > .
> > For more options, visit this group at
> >http://groups.google.com/group/google-appengine?hl=en.
>
> --
> Patrick H. Twohig.
>
> Namazu Studios
> P.O. Box 34161
> San Diego, CA 92163-4161
>
> Office: 619.862.2890 x100
> Cell: 619.453.5075
> Twitter: @svm_invictvs

> IRC: svm_invic...@irc.freenode.net ##java, #android-dev, #iphonedev,

Patrick Linskey

unread,
Feb 1, 2010, 3:29:11 PM2/1/10
to Google App Engine
> (and Require Admin login isn't enough)

That would be enough, but the only way to do that is to put the
limitation in the web.xml file, which is pretty far away from the
servlet in question. I want to make sure that someone doesn't
accidentally mis-configure the web.xml file to remove the admin
restriction. And I'd really rather not parse web.xml and apply all the
appropriate rules to do so.

Also, I don't know whether or not Google guarantees that the X-
AppEngine-TaskName header is stripped from malicious incoming
requests. It looks like it does, but that's just based on my
observations.

Thanks,

-Patrick

> > google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com>

Patrick Linskey

unread,
Feb 1, 2010, 3:33:04 PM2/1/10
to Google App Engine
I am using web.xml, but I'm unsatisfied with the potential for a
future mis-configuration to open up a hole to these servlets.

I'm reluctant to rely on an obscure rule tucked away in a shared
separately-modifiable deployment descriptor to always be properly
configured.

> HttpHeaders are very easy to create and send with a http request.

Agreed, but it's also very easy for the appserver to filter out
certain headers (which it looks like Google is doing). If they're
doing this intentionally, then the existence of a header can provide a
meaningful security validation.

-Patrick

Eli Jones

unread,
Feb 1, 2010, 3:39:26 PM2/1/10
to google-a...@googlegroups.com
That's why you have to use the TaskName and Hash method to verify that a Task was added to the queue in an orthodox manner.

Unless someone knows the hash scheme you are using for TaskNames.. they will not be able to send in a (TaskName,getHash(TaskName)) pair that would get validated when the task started running..

Let me know if I'm not being clear in my suggestion.. this should do exactly what you want.. it would 100% prevent a person from accidentally visiting the URL and running a task (since it checks for the TaskName header).. and it would pretty much prevent some random person from trying to impersonate a task by sending a Post to the task URL..  They would have to know the correct hash to send along with the TaskName they are spoofing..

To unsubscribe from this group, send email to google-appengi...@googlegroups.com.

Patrick Linskey

unread,
Feb 2, 2010, 1:01:30 AM2/2/10
to Google App Engine
Hi,

That's a great suggestion -- thanks! I don't use task names for
anything meaningful currently, so using it as a hashing channel should
work great. Now that you've got me thinking about strong encryption
vs. just checking local state, I wonder if maybe I should just sign
the request payloads.

(When I replied earlier, I had only read the first paragraph. I'm
going to blame that on the small display on my phone.

Meanwhile, my questions to Google still stands: do you make any
guarantees about stripping client-provided headers, and do you have
any plans to provide an API for checking the current request's roles
in a way that works with task queues?

-Patrick

> > > > google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com><google-appengine%2Bunsubscrib

Nick Johnson (Google)

unread,
Feb 2, 2010, 5:35:21 AM2/2/10
to google-a...@googlegroups.com
Hi Patrick,

Filtering out X-AppEngine prefixed headers is intentional, and we certainly expect to continue doing so.

-Nick Johnson

To unsubscribe from this group, send email to google-appengi...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/google-appengine?hl=en.




--
Nick Johnson, Developer Programs Engineer, App Engine
Google Ireland Ltd. :: Registered in Dublin, Ireland, Registration Number: 368047

Eli Jones

unread,
Feb 2, 2010, 9:00:03 AM2/2/10
to google-a...@googlegroups.com
The only thing to look out for when naming Tasks is.. Task names are
unique for a certain time period (I think its 7 days [I'm writing this
on my phone so I won't be verifying that :) ]).

This makes sure a task with the same name doesn't get added to the
queue twice due to any errors.

> google-appengi...@googlegroups.com.


> For more options, visit this group at
> http://groups.google.com/group/google-appengine?hl=en.
>
>

--
Sent from my mobile device

Patrick Linskey

unread,
Feb 2, 2010, 12:31:17 PM2/2/10
to Google App Engine
Great, thanks!

Do you have any documentation to this effect? An enumeration of the
headers that you strip and add, and in what contexts, would make a
great contribution to your existing sections on securing an
application in Python / Java, or a new security FAQ section.

Also, I noticed that the dev appserver does not set the X-AppEngine
headers when invoking task queues. It's not a big deal, since I can
detect that the dev server in other ways (including checking for the
"X-Google-DevAppserver-SkipAdminCheck", if I knew that it was being
stripped). But it'd be nice if the environments were more similar.

Thanks for the info,

-Patrick

On Feb 2, 2:35 am, "Nick Johnson (Google)" <nick.john...@google.com>
wrote:

> > > > google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com><google-appengine%2Bunsubscrib


> > e...@googlegroups.com>
> > > > .
> > > > For more options, visit this group at
> > > >http://groups.google.com/group/google-appengine?hl=en.
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Google App Engine" group.
> > To post to this group, send email to google-a...@googlegroups.com.
> > To unsubscribe from this group, send email to
> > google-appengi...@googlegroups.com<google-appengine%2Bunsubscrib e...@googlegroups.com>
> > .
> > For more options, visit this group at
> >http://groups.google.com/group/google-appengine?hl=en.
>
> --

Danny Tuppeny

unread,
Feb 3, 2010, 12:41:32 PM2/3/10
to Google App Engine
> > (and Require Admin login isn't enough)
>
> That would be enough, but the only way to do that is to put the
> limitation in the web.xml file

I might be missing something, but can't you just do the same thing in
code:

http://code.google.com/appengine/docs/python/users/functions.html#is_current_user_admin

I'm not sure how different it is for Java, but I'd be surprised if you
couldn't do the same thing.

Danny Tuppeny

unread,
Feb 3, 2010, 12:44:09 PM2/3/10
to Google App Engine
> > > (and Require Admin login isn't enough)
>
> > That would be enough, but the only way to do that is to put the
> > limitation in the web.xml file
>
> I might be missing something, but can't you just do the same thing in
> code:

I just re-read your post, and looks like you did something similar but
got an error. Doh!

This isn't the first time I've seen someone complain about cron/
taskqueue not having a "current user", so it's worth checking the
issue tracker and raising an issue if there isn't already one. It
seems reasonable to expect to be able to tell the difference between a
real visitor and the system in cron/taskqueues.

Reply all
Reply to author
Forward
0 new messages