Edgewall Software

Opened 8 years ago

Last modified 8 years ago

#12403 closed defect

TypeError: execv() arg 2 must contain only strings — at Version 5

Reported by: Ryan J Ollos Owned by:
Priority: normal Milestone: 1.0.11
Component: web frontend Version:
Severity: normal Keywords:
Cc: Branch:
Release Notes:

Null bytes in request argument for name, value or filename raises an HTTPBadRequest exception.

API Changes:
Internal Changes:

Description

From the logs:

[pid 7564 139730844530432] 2016-03-14 16:05:09,876 Trac[main] ERROR: Internal Server Error: <RequestWithSession "GET '/changeset?new=302bd3796163449f419a328fb5ce566b6cc55948@/&old=14519%2540/<%00ScRiPt%20%0d%0a>prompt(937841)</ScRiPt>&reponame=psuter.git&sfph_mail=&sfp_email=sample@email.tst'">, referrer 'http://trac.edgewall.org/'
Traceback (most recent call last):
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/trac/web/main.py", line 607, in _dispatch_request
    dispatcher.dispatch(req)
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/trac/web/main.py", line 256, in dispatch
    resp = chosen_handler.process_request(req)
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/trac/versioncontrol/web_ui/changeset.py", line 256, in process_request
    old = repos.normalize_rev(old or new)
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/tracopt/versioncontrol/git/git_fs.py", line 534, in normalize_rev
    normrev = self.git.verifyrev(rev)
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 717, in verifyrev
    rc = self.repo.rev_parse('--verify', rev).strip()
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 139, in __execute
    p = self.__pipe(git_cmd, stdout=PIPE, stderr=PIPE, *cmd_args)
  File "/usr/local/virtualenv/1.1dev/lib/python2.7/site-packages/tracopt/versioncontrol/git/PyGIT.py", line 132, in __pipe
    close_fds=close_fds, **kw)
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1335, in _execute_child
    raise child_exception
TypeError: execv() arg 2 must contain only strings

This looks to be similar to #11291.

Change History (5)

comment:1 by Jun Omae, 8 years ago

Null byte attack. This issue is caused by passing null byte to Popen().

>>> from subprocess import Popen
>>> Popen(('/bin/echo', '123')).wait()
123
0
>>> Popen(('/bin/echo', '12\x003')).wait()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
TypeError: execv() arg 2 must contain only strings

It seems os.exec* family disallows null bytes.

$ LANG=C python -c "import os; os.execv('/bin/echo', ('/bin/echo', '123'))"
123
$ LANG=C python -c "import os; os.execv('/bin/echo', ('/bin/echo', '1\x0023'))"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: execv() arg 2 must contain only strings
$
$ LANG=en_US.UTF-8 python -c "import os; os.execv('/bin/echo', ('/bin/echo', '123'))"
123
$ LANG=en_US.UTF-8 python -c "import os; os.execv('/bin/echo', ('/bin/echo', '1\x0023'))"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
TypeError: execv() arg 2 must contain only strings
Last edited 8 years ago by Jun Omae (previous) (diff)

comment:2 by Jun Omae, 8 years ago

I think we could reject such a request with null bytes.

  • trac/web/api.py

    diff --git a/trac/web/api.py b/trac/web/api.py
    index 0ea3e05af..b2599330c 100644
    a b class Request(object):  
    729729        args = []
    730730        for value in fs.list or ():
    731731            try:
    732                 name = unicode(value.name, 'utf-8')
    733                 if not value.filename:
    734                     value = unicode(value.value, 'utf-8')
     732                name = value.name
     733                if '\x00' in name:
     734                    raise HTTPBadRequest(_("Invalid request arguments."))
     735                name = unicode(name, 'utf-8')
     736                if value.filename:
     737                    if '\x00' in value.filename:
     738                        raise HTTPBadRequest(_("Invalid request arguments."))
     739                else:
     740                    value = value.value
     741                    if '\x00' in value:
     742                        raise HTTPBadRequest(_("Invalid request arguments."))
     743                    value = unicode(value, 'utf-8')
    735744            except UnicodeDecodeError, e:
    736745                raise HTTPBadRequest(
    737746                    _("Invalid encoding in form data: %(msg)s",
Last edited 8 years ago by Jun Omae (previous) (diff)

comment:3 by Ryan J Ollos, 8 years ago

#12404 closed as a duplicate.

comment:4 by Ryan J Ollos, 8 years ago

Milestone: next-stable-1.0.x1.0.11

comment:5 by Ryan J Ollos, 8 years ago

Release Notes: modified (diff)

Thanks for the patch. I added tests in log:rjollos.git:t12403.

Note: See TracTickets for help on using tickets.