Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Ticket #2336 (closed defect: fixed)

Opened 8 years ago

Last modified 6 years ago

possible security hole in default error handler

Reported by: diefans Owned by: pedersen
Priority: highest Milestone: 2.0.* bugfix
Component: TurboGears Version: 2.0
Severity: critical Keywords: javascript injection
Cc:

Description (last modified by jorge.vargas) (diff)

Hello,

It is possible to inject executable Javascript-Code into an error page generated by the default ErrorController?.document method. Just put the code into the message URL parameter.

This is because:

  1. the error handler uses manipulatable request parameters
  2. the template shows those possible manipulated parameters as XML and not as escaped HTML/XML (IMHO quite irresponsible)

Since the error handling will be the last point where developers put attention to, even some will ignore it completely or use these defaults, this could be a sleeping vulnerablity to many of them.

Attachments

screenshot1.png Download (32.5 KB) - added by diefans 8 years ago.
just to see

Change History

comment:1 Changed 8 years ago by jorge.vargas

  • Version changed from 2.0b7 to 2.0
  • Description modified (diff)
  • Milestone set to 2.0

I'm not entirely sure this is accurate. Will ask a genshi expert.

comment:2 Changed 8 years ago by jorge.vargas

Could you provide an example call to that controller that will display an alert() window? From looking at how it is handle it should not be possible to put that in the URL as it is an indirection call to the errormiddleware. Neither GET or POST.

 http://localhost:8080/error/document?status_int=3

returns AttributeError?: 'NoneType?' object has no attribute 'status_int' with WebError? on.

Changed 8 years ago by diefans

just to see

comment:3 Changed 8 years ago by diefans

lets say you have an application where you serve files and when a wrong file id is requested you serve an 404 error by calling:

raise HTTPNotFound

on that page you can append a message parameter like

http://localhost:8080/file?id=invalid&message=%3Cscript%20type=%22text/javascript%22%3Ealert(%27test%27)%3C/script%3E

this is my error document method as it was created by quickstart. As you can see the URL parameter "message" is forwarded to the template as it is:

def document(self, *args, **kwargs):
        """Render the error document"""
        resp = request.environ.get('pylons.original_response')
        default_message = ("<p>We're sorry but we weren't able to process "
                           " this request.</p>")
        values = dict(prefix=request.environ.get('SCRIPT_NAME', ''),
                      code=request.params.get('code', resp.status_int),
                      message=str(request.params.get('message', default_message)))
        return values

this is the error template as it was created by quickstart:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
                      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:py="http://genshi.edgewall.org/"
      xmlns:xi="http://www.w3.org/2001/XInclude">

  <xi:include href="master.html" />

<head>
  <meta content="text/html; charset=UTF-8" http-equiv="content-type" py:replace="''"/>
  <title>A ${code} Error has Occurred </title>
</head>

<body>
<h1>Error ${code}</h1>

<div>${XML(message)}</div>
</body>
</html>

the relevant part is:

<div>${XML(message)}</div> 

which means, that everything in message is considered to be valid XML and is inserted that way. At the end you have the following code in your error page:

<div id="content">
<h1>Error 404</h1>

<div><script type="text/javascript">alert('test')</script></div>
    <div class="clearingdiv"></div>
    <!-- End of content -->
  </div>

it's a security hole, because unplanned and unwanted events may occur on that Page...

comment:4 Changed 8 years ago by Chris Arndt

  • Owner set to mramm

This seems like a serious issue. Though to exploit it as an XSS attack the attacker must be able to plant a forged URL on the victim.

comment:5 Changed 8 years ago by diefans

Just imagine a Blog where a commentator is able to post links or to enter his "own" website...

comment:6 Changed 7 years ago by Chris Arndt

  • Milestone changed from 2.0 to 2.* bugfix

comment:7 Changed 6 years ago by pedersen

  • Owner changed from mramm to pedersen
  • Status changed from new to assigned

Possible fix is located here. If everybody agrees, I will push this to SF, and copy fix to 2.1.

 https://github.com/pedersen/tg2devtools/commit/fd8e0b640f367801f4e054a168b9cd90ce6724d9

comment:8 Changed 6 years ago by pedersen

Better fix located here. Unless someone can come up with a reason not to make this fix permanent (and/or a better patch), I'll commit this to SF by Monday night.

 https://github.com/pedersen/tg2devtools/commit/b2f190fbfc5461fae88c3bbf03508c815f430ad4

comment:9 Changed 6 years ago by pedersen

Finalized fix. Unless an issue arises, I will complete the merge/push tomorrow night. Speak up now, people, if you don't like it.

Commits for 2.0 and 2.1 are here:  https://github.com/pedersen/tg2devtools/commit/2fc970a669718a6bc9924e158775e5e60e78aa25  https://github.com/pedersen/tg2devtools/commit/528caef07f102c831311b4885a927f0216553f4d

comment:10 Changed 6 years ago by pedersen

  • Status changed from assigned to closed
  • Resolution set to fixed

The fix for this issue has been commited into git. It will be released in 2.0.4 and 2.1.1, and then stay around afterwards. Closing this ticket as the work is done.

Note: See TracTickets for help on using tickets.