Skip to content

Security bug in tkinter allows for untrusted, arbitrary code execution. #60452

Closed

Description

@RamchandraApte
BPO 16248
Nosy @warsaw, @birkenfeld, @terryjreedy, @mdickinson, @pitrou, @larryhastings, @tiran, @benjaminp, @asvetlov, @skrah, @zware
Files
  • exploit.py
  • issue16248-2.x.patch: 2.x patch
  • issue16248-3.x.patch: 3.x patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = <Date 2013-09-15.19:59:57.526>
    created_at = <Date 2012-10-16.15:29:21.664>
    labels = ['type-security', 'expert-tkinter', 'release-blocker']
    title = 'Security bug in tkinter allows for untrusted, arbitrary code execution.'
    updated_at = <Date 2013-09-15.19:59:57.525>
    user = 'https://bugs.python.org/RamchandraApte'

    bugs.python.org fields:

    activity = <Date 2013-09-15.19:59:57.525>
    actor = 'pitrou'
    assignee = 'none'
    closed = True
    closed_date = <Date 2013-09-15.19:59:57.526>
    closer = 'pitrou'
    components = ['Tkinter']
    creation = <Date 2012-10-16.15:29:21.664>
    creator = 'Ramchandra Apte'
    dependencies = []
    files = ['27823', '27937', '27938']
    hgrepos = []
    issue_num = 16248
    keywords = ['patch']
    message_count = 64.0
    messages = ['173047', '173048', '173050', '173051', '173125', '173191', '173230', '173231', '173278', '174299', '174300', '174317', '174319', '174396', '174420', '174429', '174450', '174460', '174462', '174463', '174464', '174466', '174469', '174471', '174476', '174479', '174488', '174509', '174553', '174556', '174813', '175253', '177218', '177219', '177220', '177222', '182507', '182511', '182524', '182525', '182526', '182527', '182532', '182565', '182566', '182568', '182569', '194091', '194094', '194096', '194112', '194114', '194639', '195091', '195093', '195599', '195600', '195737', '195738', '197689', '197690', '197697', '197825', '197826']
    nosy_count = 15.0
    nosy_names = ['barry', 'georg.brandl', 'terry.reedy', 'mark.dickinson', 'pitrou', 'larry', 'christian.heimes', 'benjamin.peterson', 'gpolo', 'Arfrever', 'asvetlov', 'skrah', 'python-dev', 'Ramchandra Apte', 'zach.ware']
    pr_nums = []
    priority = 'release blocker'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'security'
    url = 'https://bugs.python.org/issue16248'
    versions = ['Python 3.1']

    Activity

    1. RamchandraApte commented on Oct 31, 2012

      RamchandraAptemannequin
      MannequinAuthor

      I think this is a legitimate security bug.
      the malicious program needs to create a file with a certain name in the home dir.
      If a user runs say IDLE (or another tk app) with root priveleges using sudo, the file will be run with root priveleges.

    2. mdickinson commented on Nov 1, 2012

      @mdickinson
      Member

      Ramchandra: can you give an example of a realistic situation where the existence of this code in tkinter allows users to execute code *that they wouldn't be able to execute otherwise*?

    3. RamchandraApte commented on Nov 1, 2012

      RamchandraAptemannequin
      MannequinAuthor

      @mark Dickinson
      Run the attached file, exploit.py, with normal priveleges and then run IDLE with sudo (something I did to actually uncover this bug!).
      Then the file "/root/exploited" should contain "Exploit succeeded!"

    4. mdickinson commented on Nov 1, 2012

      @mdickinson
      Member

      Okay, but if a user can run IDLE with sudo, they presumably *already* have many other ways to use sudo to create files in /root, without using IDLE or tkinter. That's why I said: "*that they wouldn't be able to execute otherwise*". I don't see the security issue here.

    5. zware commented on Nov 1, 2012

      @zware
      Member

      If I understand correctly, I think what Ramchandra is getting at is that if an attacker could manage to get a .Tk.py file into a user's home directory somehow, then the next time that user happens to do 'sudo idle', the attacker's code is executed with root privileges.

      That said, I don't know that it would be any easier for an attacker to get such a file into such a place than to just do their maliciousness some other way.

      I think Guilherme's suggestion of just making those who need it call it themselves, instead of at every tkinter startup, sounds good.

    6. pitrou commented on Nov 1, 2012

      @pitrou
      Member

      As Zachary and Ramchandra explained, the security issue is obvious: a non-sudoer user A can make a sudoer user B execute arbitrary code, simply by placing a file where IDLE will be run from.

      This is the same reason Python has -s and -E options. The least we could do would be to disable readprofile() when sys.flags.ignore_environment is true.

    7. mdickinson commented on Nov 1, 2012

      @mdickinson
      Member

      And then user A is relying on user B executing IDLE via sudo? Is that a normal thing to do?

    8. pitrou commented on Nov 1, 2012

      @pitrou
      Member

      And then user A is relying on user B executing IDLE via sudo? Is that
      a normal thing to do?

      Well, I suppose that could be any Tk app, not just IDLE.
      And I also suppose you could use IDLE to edit some file that is only
      root-writable.

    9. mdickinson commented on Nov 1, 2012

      @mdickinson
      Member

      So if this is a security issue, should Python 2.6 also be fixed?

    10. pitrou commented on Nov 1, 2012

      @pitrou
      Member

      So if this is a security issue, should Python 2.6 also be fixed?

      Probably, if it's deemed important enough by our security RMs.

    11. skrah commented on Nov 1, 2012

      skrahmannequin
      Mannequin

      Isn't IDLE supposed to be a Python shell? As I understand this issue,
      you'd have the same "exploit" by adding this to your .bashrc:

      echo "EXPLOIT" > /root/exploit

      Then, as a normal user, run:

      sudo bash

      It would be nice to get rid of the exec, but why is this an exploit?

    12. pitrou commented on Nov 1, 2012

      @pitrou
      Member

      As I understand it, this is not specifically about IDLE. Any Tk app would be vulnerable.

    13. gpolo commented on Nov 1, 2012

      gpolomannequin
      Mannequin

      It is not IDLE specific. But I still fail to see how this actually is a
      security bug. It doesn't give more power to the user than the user already
      gave to it. If you are recklessly installing untrusted libraries or
      anything for the matter, then you already have a lot of other problems.

      Anyways, I would still go with my earlier option because I never used this
      piece of code.

      2012/11/1 Antoine Pitrou <report@bugs.python.org>

      Antoine Pitrou added the comment:

      As I understand it, this is not specifically about IDLE. Any Tk app would
      be vulnerable.

      ----------


      Python tracker <report@bugs.python.org>
      <http://bugs.python.org/issue16248\>


    14. skrah commented on Nov 1, 2012

      skrahmannequin
      Mannequin

      I also don't find the scenario where an attacker has write privileges
      to a user's home directory so disturbing -- there are juicier targets
      (like .bashrc).

      This constructed example using /tmp is a little more troubling:

      $ cd /tmp
      $ echo 'print("exploit")' > .Tk.py
      $ export XAUTHORITY=$HOME/.Xauthority
      $ unset HOME
      $ python3.3
      >>>import tkinter
      >>> w = tkinter.Tk()
      /usr/local/lib/python3.3/tkinter/__init__.py:1817: ResourceWarning: unclosed file <_io.TextIOWrapper name='./.Tk.py' mode='r' encoding='ANSI_X3.4-1968'>
        exec(open(class_py).read(), dir)
      exploit
    15. RamchandraApte commented on Nov 2, 2012

      RamchandraAptemannequin
      MannequinAuthor

      On 2 November 2012 01:48, Stefan Krah <report@bugs.python.org> wrote:

      Stefan Krah added the comment:

      Isn't IDLE supposed to be a Python shell? As I understand this issue,
      you'd have the same "exploit" by adding this to your .bashrc:

      echo "EXPLOIT" > /root/exploit

      Then, as a normal user, run:

      sudo bash

      It would be nice to get rid of the exec, but why is this an exploit?

      ----------
      nosy: +skrah


      Python tracker <report@bugs.python.org>
      <http://bugs.python.org/issue16248\>


      Almost nobody knows that when using tkinter, code in .Tk.py is executed.
      (readprofile is not even documented!)
      While in your example, it is quite easy to see that it will run .bashrc

    16. skrah commented on Nov 2, 2012

      skrahmannequin
      Mannequin

      Ramchandra Apte <report@bugs.python.org> wrote:

      Almost nobody knows that when using tkinter, code in .Tk.py is executed.
      (readprofile is not even documented!)
      While in your example, it is quite easy to see that it will run .bashrc

      The point of the example is that it's "game over" anyway once an attacker
      has write privileges to a user's home directory.

      "sudo bash" is certainly a more common operation than "sudo tkapp.py",
      and users are not in the habit of auditing .bashrc each time they launch
      a shell.

      In fact, I'd probably be more likely to notice a new file ".Tk.py" than
      a small modification to my .bashrc.

      That said, I absolutely agree that *ideally* tkinter apps should not
      execute code from a startup file, especially if the startup file is
      *not* in the user's home directory.

    17. pitrou commented on Nov 2, 2012

      @pitrou
      Member

      I'm gonna point people to the discussion about the "-s" flag of the Python interpreter (added as part of PEP-370), since the issue is conceptually identical:
      http://mail.python.org/pipermail/python-dev/2008-January/076130.html

      Adding Christian to the discussion since he was the author and implementor of that PEP.

    18. tiran commented on Nov 2, 2012

      @tiran
      Member

      It's gonna take a while to read this ticket ...

      Some comments:
      The code in site.py already does some checks, for example getuid() == geteuid(). System code and code that is run with administrator privileges shall be run with -Es to prevent code injection. See https://bugs.launchpad.net/ubuntu/+source/lsb/+bug/938869 comment #24 for an issue.

    19. tiran commented on Nov 4, 2012

      @tiran
      Member

      I'm all with Antoine's suggestion. readprofile() should not be executed when sys.flags.ignore_environment is set.

    20. zware commented on Nov 9, 2012

      @zware
      Member

      Here are a pair of trivial patches that implement Antoine's suggestion of not executing readprofile() if the -E flag is set. Current tests seem to pass, but there are no new tests included because frankly I'm not sure of either how to test it or where. Also, I can't seem to find any tests of the -E flag at all; does this change need a test? No doc change either since the function isn't documented.

      The patches apply equally well on 2.6 or 2.7, or 3.1 or 3.2, depending on whether this is determined to be security issue enough to mess with 2.6 and 3.1.

      Thanks,

      Zach

    21. python-dev commented on Dec 9, 2012

      python-devmannequin
      Mannequin

      New changeset d8300842a0e9 by Antoine Pitrou in branch '3.2':
      Issue bpo-16248: Disable code execution from the user's home directory by tkinter when the -E flag is passed to Python.
      http://hg.python.org/cpython/rev/d8300842a0e9

      New changeset 10d04bdb05ab by Antoine Pitrou in branch '3.3':
      Issue bpo-16248: Disable code execution from the user's home directory by tkinter when the -E flag is passed to Python.
      http://hg.python.org/cpython/rev/10d04bdb05ab

      New changeset a4fc52da295b by Antoine Pitrou in branch 'default':
      Issue bpo-16248: Disable code execution from the user's home directory by tkinter when the -E flag is passed to Python.
      http://hg.python.org/cpython/rev/a4fc52da295b

    22. python-dev commented on Dec 9, 2012

      python-devmannequin
      Mannequin

      New changeset 822b472eff13 by Antoine Pitrou in branch '2.7':
      Issue bpo-16248: Disable code execution from the user's home directory by tkinter when the -E flag is passed to Python.
      http://hg.python.org/cpython/rev/822b472eff13

    23. pitrou commented on Dec 9, 2012

      @pitrou
      Member

      Fixed. I will let Benjamin and Barry decide whether this deserves backporting to security branches. Benjamin, Barry, please do your job :)

    24. python-dev commented on Dec 9, 2012

      python-devmannequin
      Mannequin

      New changeset 03b3124e9ea3 by Antoine Pitrou in branch '3.1':
      Issue bpo-16248: Disable code execution from the user's home directory by tkinter when the -E flag is passed to Python.
      http://hg.python.org/cpython/rev/03b3124e9ea3

    25. RamchandraApte commented on Feb 20, 2013

      RamchandraAptemannequin
      MannequinAuthor

      I suppose this should be closed.

    26. tiran commented on Feb 20, 2013

      @tiran
      Member

      The bug hasn't been closed deliberately. We need to announce the security fix and possibly acquire a CVE, too.

    27. reopened this on Feb 20, 2013
    28. zware commented on Feb 20, 2013

      @zware
      Member

      I believe we're also waiting on input from Barry about whether to apply the
      patch to 2.6.

    29. warsaw commented on Feb 20, 2013

      @warsaw
      Member

      Does the 2.x patch apply cleanly to 2.6? If so, then I think it should be applied (though I'd like to review it first). 2.6 is still under security maintenance until October 2013. I'm thinking we'll probably do one last security release around that time.

    30. zware commented on Feb 20, 2013

      @zware
      Member

      Does the 2.x patch apply cleanly to 2.6?

      It should, if I remember correctly, though I haven't checked since
      uploading it. I believe there were actually very few or no changes to the
      file the patch is for between 2.6 and 2.7.

    31. warsaw commented on Feb 20, 2013

      @warsaw
      Member

      Release blocking for 2.6.9 (oh how I wish we could release block for specific Python versions).

    32. pitrou commented on Feb 20, 2013

      @pitrou
      Member

      Barry A. Warsaw added the comment:

      Does the 2.x patch apply cleanly to 2.6?

      Perhaps it's your job as a release manager to check that ;-P

    33. warsaw commented on Feb 20, 2013

      @warsaw
      Member

      I'm working on applying the 2.x patch to 2.6, but one thing interesting of note: sudo, at least on Debian and derivatives going back at least to Squeeze, generally reset the environment by default (i.e. env_reset). So you'd have to either have disabled env_reset in sudoers or use sudo -E the exploit.py.

    34. pitrou commented on Feb 20, 2013

      @pitrou
      Member

      I'm working on applying the 2.x patch to 2.6, but one thing
      interesting of note: sudo, at least on Debian and derivatives going
      back at least to Squeeze, generally reset the environment by default
      (i.e. env_reset). So you'd have to either have disabled env_reset in
      sudoers or use sudo -E the exploit.py.

      Or you just have to use something else than Debian.

    35. python-dev commented on Feb 20, 2013

      python-devmannequin
      Mannequin

      New changeset 936621d33c38 by Barry Warsaw in branch '2.6':

    36. warsaw commented on Feb 20, 2013

      @warsaw
      Member

      I think this has now been applied to all of 2.6, 2.7, 3.1, 3.2, 3.3, and 3.4. So, closing.

    37. Arfrever commented on Aug 1, 2013

      Arfrevermannequin
      Mannequin

      The fix in 2.6, 2.7, 3.1 and 3.2 branches introduced UnboundLocalError occurring when a non-None baseName parameter is passed.
      At least a part of fa82071bb7e1 should be backported to 2.6, 2.7, 3.1 and 3.2 branches.

      $ python2.7 -c 'import Tkinter; print(repr(Tkinter.Tk(baseName="some_name")))'
      Traceback (most recent call last):
        File "<string>", line 1, in <module>
        File "/usr/lib64/python2.7/lib-tk/Tkinter.py", line 1748, in __init__
          if not sys.flags.ignore_environment:
      UnboundLocalError: local variable 'sys' referenced before assignment
      $ python3.2 -c 'import tkinter; print(repr(tkinter.Tk(baseName="some_name")))'
      Traceback (most recent call last):
        File "<string>", line 1, in <module>
        File "/usr/lib64/python3.2/tkinter/__init__.py", line 1734, in __init__
          if not sys.flags.ignore_environment:
      UnboundLocalError: local variable 'sys' referenced before assignment
    38. larryhastings commented on Aug 1, 2013

      @larryhastings
      Contributor

      You're talking about a new bug. Please open a new issue.

      I'm closing this issue right now because I want to cut a Python 3.4 alpha release tomorrow, and this bug is marked Python 3.4 and "release blocker".

    39. Arfrever commented on Aug 1, 2013

      Arfrevermannequin
      Mannequin

      UnboundLocalError is effect of partially incorrect fix for this bug.
      It is better to update Versions field.

    40. python-dev commented on Aug 1, 2013

      python-devmannequin
      Mannequin

      New changeset 0f17aed78168 by Antoine Pitrou in branch '2.7':
      Fix tkinter regression introduced by the security fix in bpo-16248.
      http://hg.python.org/cpython/rev/0f17aed78168

    41. pitrou commented on Aug 1, 2013

      @pitrou
      Member

      I've committed a fix to 2.7 (I hope it's really a fix, since I don't know how to test it).
      I'll let Benjamin and Barry decide whether to backport to 2.6 and 3.2.
      As for 3.1, it's pretty much dead.

    42. zware commented on Aug 8, 2013

      @zware
      Member

      Antoine Pitrou wrote:

      I've committed a fix to 2.7 (I hope it's really a fix, since I don't know how to test it).
      I'll let Benjamin and Barry decide whether to backport to 2.6 and 3.2.
      As for 3.1, it's pretty much dead.

      That fix does work, but it should probably get a NEWS entry since it fixes a regression from 2.7.3 to 2.7.5.

      Also, I think the same fix should be backported to all three of 2.6, 3.1, and 3.2. The same regression as in 2.7.5 exists in 3.2.5, and would be introduced by the next (last?) releases of 2.6 and 3.1.

      Sorry to have broken every possible version of Python :S

    43. python-dev commented on Aug 13, 2013

      python-devmannequin
      Mannequin

      New changeset 00bcf202cc3f by Antoine Pitrou in branch '2.7':
      Add NEWS entry for 0f17aed78168 (issue bpo-16248)
      http://hg.python.org/cpython/rev/00bcf202cc3f

    44. pitrou commented on Aug 13, 2013

      @pitrou
      Member

      That fix does work, but it should probably get a NEWS entry since it
      fixes a regression from 2.7.3 to 2.7.5.

      Done, thank you?

      Also, I think the same fix should be backported to all three of 2.6,
      3.1, and 3.2.

      Benjamin and Barry will have to decide what to do for 2.6 and 3.2.

    45. benjaminp commented on Aug 19, 2013

      @benjaminp
      Contributor

      3.2 is owned by Georg.

    46. benjaminp commented on Aug 19, 2013

      @benjaminp
      Contributor

      As for 3.1, feel free to apply. There will likely be a source release of it at some point.

    47. python-dev commented on Aug 21, 2013

      python-devmannequin
      Mannequin

      New changeset 84f40562669f by Barry Warsaw in branch '2.6':
      Fix UnboundLocalError regression due to previous incorrect fix for
      http://hg.python.org/cpython/rev/84f40562669f

    48. warsaw commented on Aug 21, 2013

      @warsaw
      Member

      Applied the fix to 2.6 and null merged into 2.7. This didn't need a NEWS entry because the regression hadn't been released yet. I'll remove 2.6 from the Versions now.

    49. birkenfeld commented on Sep 14, 2013

      @birkenfeld
      Member

      Should be fixed now in 3.2 too.

    50. python-dev commented on Sep 14, 2013

      python-devmannequin
      Mannequin

      New changeset c18c18774e24 by Georg Brandl in branch '3.2':
      Fix tkinter regression introduced by the security fix in bpo-16248.
      http://hg.python.org/cpython/rev/c18c18774e24

    51. Arfrever commented on Sep 14, 2013

      Arfrevermannequin
      Mannequin

      Fix still needs to be applied on 3.1 branch.

    52. python-dev commented on Sep 15, 2013

      python-devmannequin
      Mannequin

      New changeset c39f42f46a05 by Georg Brandl in branch '3.1':
      Fix tkinter regression introduced by the security fix in bpo-16248.
      http://hg.python.org/cpython/rev/c39f42f46a05

    53. pitrou commented on Sep 15, 2013

      @pitrou
      Member

      Fix backported to 3.1, closing.

    54. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    No one assigned

      Projects

      No projects

        Milestone

        No milestone

        Relationships

        None yet

        Development

        No branches or pull requests

        Issue actions