RFC: AJAX with JavaScript proxy

classic Classic list List threaded Threaded
8 messages Options
Reply | Threaded
Open this post in threaded view
|

RFC: AJAX with JavaScript proxy

kohsuke Kawaguchi (CB)

As a building block for more interactive UI, I've added a mechanism to
call server-side Java methods from browsers.

http://wiki.jenkins-ci.org/display/JENKINS/AJAX+with+JavaScript+proxy

Unlike DWR, this routes the method call to the specific instance, which
I think is the key to simplify the coding. The method call uses XHR and
sets a specific Content type header, which I believe protects this from
CSRF.

Feedback appreciated.


--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

Paul Sandoz

On Mar 10, 2011, at 6:59 AM, Kohsuke Kawaguchi wrote:


As a building block for more interactive UI, I've added a mechanism to call server-side Java methods from browsers.

http://wiki.jenkins-ci.org/display/JENKINS/AJAX+with+JavaScript+proxy

Unlike DWR, this routes the method call to the specific instance, which I think is the key to simplify the coding. The method call uses XHR and sets a specific Content type header, which I believe protects this from CSRF.

Feedback appreciated.


Nice, i think this will definitely make it easier. If we choose to select some preferred JS widget library we may be able to provide some Java classes for associated data models.

Have you committed it back to the trunk? i cannot find the code.

Typo?:

  If the Java method returns an object value (such as int, String, JSONObject, etc.), you can use the responseObject() 
  method to evaluate the response into a JavaScript object and use it. 

In the code sample you refer to "resultObject" rather than "responseObject", i presume it should be the latter which is in line with Ajax.Response naming.

Paul.
Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

kohsuke Kawaguchi (CB)
On 03/10/2011 02:50 AM, Paul Sandoz wrote:

>
> On Mar 10, 2011, at 6:59 AM, Kohsuke Kawaguchi wrote:
>
>>
>> As a building block for more interactive UI, I've added a mechanism to
>> call server-side Java methods from browsers.
>>
>> http://wiki.jenkins-ci.org/display/JENKINS/AJAX+with+JavaScript+proxy
>>
>> Unlike DWR, this routes the method call to the specific instance,
>> which I think is the key to simplify the coding. The method call uses
>> XHR and sets a specific Content type header, which I believe protects
>> this from CSRF.
>>
>> Feedback appreciated.
>>
>
> Nice, i think this will definitely make it easier. If we choose to
> select some preferred JS widget library we may be able to provide some
> Java classes for associated data models.

Yes.

> Have you committed it back to the trunk? i cannot find the code.

I guess I didn't push them. Doing so now.

> Typo?:
>
> If the Java method returns an object value (such as int, String,
> JSONObject, etc.), you can use the responseObject()
> method to evaluate the response into a JavaScript object and use it.
>
> In the code sample you refer to "resultObject" rather than
> "responseObject", i presume it should be the latter which is in line
> with Ajax.Response naming.

Indeed. Fixed.


--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

Dean Yu
In reply to this post by kohsuke Kawaguchi (CB)
On 3/9/11 9:59 PM, "Kohsuke Kawaguchi" <[hidden email]> wrote:
> I think is the key to simplify the coding. The method call uses XHR and
> sets a specific Content type header, which I believe protects this from
> CSRF.
>
> Feedback appreciated.
>

I looked at the proxy code [1], and setting the content type header in this
manner is insufficient to protect against CSRFs. At the least, you should
generate a nonce value using a server-side secret and bake it into the
proxy, and have this value passed back on the request for the server to
verify. Since you mentioned DWR, they have a page [2] that discusses some of
their security techniques.

  -- Dean

[1]
http://java.net/projects/stapler/sources/svn/content/tags/stapler-parent-1.1
57/core/src/main/resources/org/kohsuke/stapler/bind.js?rev=1721

[2]
http://directwebremoting.org/dwr/documentation/security/script-tag-protectio
n.html

Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

kohsuke Kawaguchi (CB)
On 03/10/2011 01:00 PM, Dean Yu wrote:

> On 3/9/11 9:59 PM, "Kohsuke Kawaguchi"<[hidden email]>  wrote:
>>  I think is the key to simplify the coding. The method call uses XHR and
>>  sets a specific Content type header, which I believe protects this from
>>  CSRF.
>>
>>  Feedback appreciated.
>>
>
> I looked at the proxy code [1], and setting the content type header in this
> manner is insufficient to protect against CSRFs. At the least, you should
> generate a nonce value using a server-side secret and bake it into the
> proxy, and have this value passed back on the request for the server to
> verify. Since you mentioned DWR, they have a page [2] that discusses some of
> their security techniques.

Thanks. I'll do that, but I'm also curious what is the remaining attack
vector. My reasoning was:

  - Only XHR or form submission could produce a post
  - XHR can't cross domain
  - form submission can't set the content type
  - hence it's safe

What did I miss?

>
>    -- Dean
>
> [1]
> http://java.net/projects/stapler/sources/svn/content/tags/stapler-parent-1.1
> 57/core/src/main/resources/org/kohsuke/stapler/bind.js?rev=1721
>
> [2]
> http://directwebremoting.org/dwr/documentation/security/script-tag-protectio
> n.html
>
>


--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

Dean Yu
On 3/10/11 5:37 PM, "Kohsuke Kawaguchi" <[hidden email]> wrote:

> On 03/10/2011 01:00 PM, Dean Yu wrote:
>> On 3/9/11 9:59 PM, "Kohsuke Kawaguchi"<[hidden email]>  wrote:
>>>  I think is the key to simplify the coding. The method call uses XHR and
>>>  sets a specific Content type header, which I believe protects this from
>>>  CSRF.
>>>
>>>  Feedback appreciated.
>>>
>>
>> I looked at the proxy code [1], and setting the content type header in this
>> manner is insufficient to protect against CSRFs. At the least, you should
>> generate a nonce value using a server-side secret and bake it into the
>> proxy, and have this value passed back on the request for the server to
>> verify. Since you mentioned DWR, they have a page [2] that discusses some of
>> their security techniques.
>
> Thanks. I'll do that, but I'm also curious what is the remaining attack
> vector. My reasoning was:
>
>   - Only XHR or form submission could produce a post
>   - XHR can't cross domain
>   - form submission can't set the content type
>   - hence it's safe
>
> What did I miss?
>

You're assuming that request will always only come from script you generate.
Someone could handcraft a malicious request to try to invoke a server side
method.

I would also say that this is a really dangerous feature to expose unless
there's some form of user authentication in place.

  -- Dean

Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

kohsuke Kawaguchi (CB)
On 03/10/2011 09:40 PM, Dean Yu wrote:

> On 3/10/11 5:37 PM, "Kohsuke Kawaguchi"<[hidden email]>  wrote:
>
>>  On 03/10/2011 01:00 PM, Dean Yu wrote:
>>>  On 3/9/11 9:59 PM, "Kohsuke Kawaguchi"<[hidden email]>   wrote:
>>>>   I think is the key to simplify the coding. The method call uses XHR and
>>>>   sets a specific Content type header, which I believe protects this from
>>>>   CSRF.
>>>>
>>>>   Feedback appreciated.
>>>>
>>>
>>>  I looked at the proxy code [1], and setting the content type header in this
>>>  manner is insufficient to protect against CSRFs. At the least, you should
>>>  generate a nonce value using a server-side secret and bake it into the
>>>  proxy, and have this value passed back on the request for the server to
>>>  verify. Since you mentioned DWR, they have a page [2] that discusses some of
>>>  their security techniques.
>>
>>  Thanks. I'll do that, but I'm also curious what is the remaining attack
>>  vector. My reasoning was:
>>
>>    - Only XHR or form submission could produce a post
>>    - XHR can't cross domain
>>    - form submission can't set the content type
>>    - hence it's safe
>>
>>  What did I miss?
>>
>
> You're assuming that request will always only come from script you generate.
> Someone could handcraft a malicious request to try to invoke a server side
> method.

(Just for my own education), so the attack vector is from malicious
script that runs in a page that was served from the Jenkins domain? But
at that point isn't it pretty much game over? I mean, one can retrieve
the crumb value, in this case.

Or is the main issue that, without crumb, the protection hinges on
somewhat arbitrary restrictions about XHR/Flash/JavaApplet/<form> that
doesn't allow a custom content-type header, which can be lifted later?


> I would also say that this is a really dangerous feature to expose unless
> there's some form of user authentication in place.

The server-side method gets authenticated, and it can and should still
be authorized if it does something sensitive. In most typical cases, the
proxy is created when rendering a page, which by itself only happens
after adequate authorization is performed, so I think it's no more
dangerous than those doFooBar methods.

I'll capture the security aspect of this in the Wiki page to call attention.



You later sent me the following, so I'm assuming that I've addressed
your concerns:

> I see you made the changes. I also see that the instance identifier is
> randomly generated — something I didn’t notice yesterday in my initial
> look-through of the code. Before seeing this, my biggest concern was
> that if you were passing the object reference itself down to the
> Javascript proxy, that this would make it possible to guess at
> accessible instances. The random ID generation makes it much harder to
> do this, so I’m much less concerned now.
 >
> So between the crumb addition and this fact I discovered, I think this
> looks good now!



--
Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
Reply | Threaded
Open this post in threaded view
|

Re: RFC: AJAX with JavaScript proxy

Dean Yu
On 3/11/11 11:00 AM, "Kohsuke Kawaguchi" <[hidden email]> wrote:

>
> (Just for my own education), so the attack vector is from malicious
> script that runs in a page that was served from the Jenkins domain? But
> at that point isn't it pretty much game over? I mean, one can retrieve
> the crumb value, in this case.
>
> Or is the main issue that, without crumb, the protection hinges on
> somewhat arbitrary restrictions about XHR/Flash/JavaApplet/<form> that
> doesn't allow a custom content-type header, which can be lifted later?
>

Typically, the way a CSRF attack works is that I get make you click a link
that makes your browser to send a request to a server that trusts you. This
works best if I know something about how the server works. In this case, if
I can discover the URL that binds to a method to call, I can make you invoke
that method even if I don't have direct access to the server myself.

The crumb protects against this because it's a value that's generated by the
server and sent down with the initial response, so I would now be required
to have direct access to the server to be able to get this crumb value.

>
>> I would also say that this is a really dangerous feature to expose unless
>> there's some form of user authentication in place.
>
> The server-side method gets authenticated, and it can and should still
> be authorized if it does something sensitive. In most typical cases, the
> proxy is created when rendering a page, which by itself only happens
> after adequate authorization is performed, so I think it's no more
> dangerous than those doFooBar methods.

Right. I would put those doFooBar methods in the same category. Basically,
Stapler makes running an Jenkins server without authentication very
vulnerable to all sorts of bad things.

  -- Dean

>
> I'll capture the security aspect of this in the Wiki page to call attention.
>
>
>
> You later sent me the following, so I'm assuming that I've addressed
> your concerns:
>
>> I see you made the changes. I also see that the instance identifier is
>> randomly generated < something I didn¹t notice yesterday in my initial
>> look-through of the code. Before seeing this, my biggest concern was
>> that if you were passing the object reference itself down to the
>> Javascript proxy, that this would make it possible to guess at
>> accessible instances. The random ID generation makes it much harder to
>> do this, so I¹m much less concerned now.
>>
>> So between the crumb addition and this fact I discovered, I think this
>> looks good now!
>
>
>
> --
> Kohsuke Kawaguchi | CloudBees, Inc. | http://cloudbees.com/
>