{"id":22140889,"url":"https://github.com/stealth/troubleshooter","last_synced_at":"2025-07-25T23:31:52.168Z","repository":{"id":29376915,"uuid":"32911746","full_name":"stealth/troubleshooter","owner":"stealth","description":"setroubleshootd xSports","archived":false,"fork":false,"pushed_at":"2017-05-18T11:42:33.000Z","size":123,"stargazers_count":92,"open_issues_count":0,"forks_count":20,"subscribers_count":17,"default_branch":"master","last_synced_at":"2023-03-14T04:05:16.581Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stealth.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-03-26T06:40:56.000Z","updated_at":"2022-09-10T23:09:56.000Z","dependencies_parsed_at":"2022-09-06T16:51:03.545Z","dependency_job_id":null,"html_url":"https://github.com/stealth/troubleshooter","commit_stats":null,"previous_names":[],"tags_count":null,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stealth%2Ftroubleshooter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stealth%2Ftroubleshooter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stealth%2Ftroubleshooter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stealth%2Ftroubleshooter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stealth","download_url":"https://codeload.github.com/stealth/troubleshooter/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":227629069,"owners_count":17796054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-01T21:08:27.998Z","updated_at":"2024-12-01T21:08:28.756Z","avatar_url":"https://github.com/stealth.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"##                     troubleshooter\n\n####          The revenge of _GingerBreak_\n\n__Abstract:__ This paper demonstrates vulnerabilities within the\nSELinux framework as well as shortcomings in the type enforcement setup.\nI will show how to deconstruct a SELinux setup with some simple 80's style\nexploit techniques. While reading this paper, I recommend listening\nto [this music from the year of morrisworm.](https://www.youtube.com/watch?v=ufERJEdcfAY)\n\n##### Introduction\n\nWhen in 2012 the SELinux developers analyzed the behaivior of an exploit\nthat was not designed to run on a SELinux system [at page 32 of these slides](http://selinuxproject.org/~seandroid/slides/LinuxConNA2012-SEAndroid.pdf) - it\ntriggered  a review-selector for SELinux and I put it to the list of my audit\ntargets. Not surprisingly, _GingerBreak_ lost that \"competition\", just because\nit was not made for it. Using my QUANTUM AUDIT techniques I was now able to have\na deeper look into SELinux itself to see whether the claims that were made\nreally hold.\n\n\n##### The AVC subsystem\n\nSELinux is basically split into two parts. The kernel part, which mostly\nconsists of the Access Vector Cache (AVC) logic, and a userspace part which\nI will call the SELinux framework. The framework consists of a lot of Python\nscripts running as root and/or as a DBUS service. The AVC itself basically\ndecides whether a permission is granted or not, based on the typing and\ntransitioning rules from the policy.\n\nWhen the AVC denies access, it used to send a netlink message from the kernel\nto the audit subsystem which looks like this:\n\n```\ntype=AVC msg=audit(1427104951.889:423): avc:  denied  { open } for  pid=2521\ncomm=\"openvpn\" path=2F74[...]27 dev=\"tmpfs\" ino=31315\nscontext=system_u:system_r:openvpn_t:s0\ntcontext=unconfined_u:object_r:user_tmp_t:s0 tclass=file permissive=0\n```\nwithin a single line. It basically tells the admin that _openvpn_, running\nin the *openvpn_t* domain, was denied access to a file object with type\n*user_tmp_t*. The pathname of the object in question is encoded as hex string\nfor a reason. This logging makes sense in order to maintain the system.\n\nThe audit subsystem can be be further configured with plugins to handle such\nmessages. For example on a Fedora 21 system there is a plugin that further\nmangles such messages via _sedispatch_ to the _setroubleshoot_ DBUS service.\nSince everything in a targeted policy is safe due to type enforcement MAC\n(which we will break later), all this runs as root of course.\n\n##### Where is my mind?\n\nNow lets have a look on how this _setroubleshoot_ DBUS service, running as\nroot (although in its SELinux domain sandbox), handles this untrusted pathname\ninput originating from the AVC deny message:\n\n```Python\ndef get_rpm_nvr_by_file_path_temporary(name):\n    if name is None or not os.path.exists(name):\n        return None\n\n    nvr = None\n    try:\n        import commands\n        rc, output = commands.getstatusoutput(\"rpm -qf '%s'\" % name)\n        if rc == 0:\n            nvr = output\n    except:\n        syslog.syslog(syslog.LOG_ERR, \"failed to retrieve rpm info for %s\" % name)\n    return nvr\n```\n\nThe _setroubleshootd_ daemon which runs as root, activated by its DBUS\nactivation file when _sedispatch_ was forwarding its AVC denial message,\nstraight passes the pathname to a shell without further sanitization. This\ndirectly pops us in a rootshell running in the *setroubleshootd_t* domain.\nBad luck for us, this domain is not allowed to dump the shadow file. The\nframework which is meant to protect you by means of a MAC system, just\ndonated a __uid 0__ shell to the attacker.\n\nThe next chapter will show how this particular MAC setup can't even hold\nwhat it promised to be their stronghold: Once (in the unlikely case) an\nattacker successfully exploited a process, he is caged in its unprivileged\ndomain.\n\n\n##### Containers dont contain.\n\nAnd so don't domains. I really love that deep sentence that was philosophically\nspoken in response to my docker exploit which demonstrated a breakout of the\ndocker container. Programmers are the better philosophers.\n\nBy looking at the policy rules with regard to the *setroubleshootd_t* domain,\nwe quickly find that it is allowed to *create* and *setattr* file objects within\nits own directory. This comes with little surprise, but it allows us to mount\nthe well known __Vichy-attack__ against sandboxed systems where two domains\ncollaborate. That is, the command is constructed as follows:\n\n```\ncd var;cd lib;cd setroubleshoot;cat $SHELL \u003e sh;chmod 04755 sh\n```\nIts necessary to avoid the `/` character because we are passing\nalong a filename and it makes things easier since we dont need\nto create sub directories. This command, when executed from within\nthe *setroubleshootd_t* domain, will leave a suid shell in place\nfor the discretionary execution by the attacker who already runs\nhis shell in the *unconfined_t* domain.\n\n![Voila!](https://github.com/stealth/troubleshooter/blob/master/troubleshooter.jpg)\n\nA demo exploit using _NetworkManager's_ openvpn plugin as an attack vector is\nincluded in this git. Dont get fooled: There exist many other\nattack vectors (not just _NetworkManager's_ integrated wifi setup in case\nthe openvpn plugin is not available), some of\nthem might work remotely. All an attacker needs to do is to trick a confined\ndomain to access one of his files. If **polkit** has rules to just allow\nactive or console sessions to access the attack vector, that is not an\nobstacle either: just put it to the target user's *.bashrc* to execute\nit on the attacker's behalf.\n\n##### Conclusion\n\nI just demonstrated an exploit against SELinux itself (not an exploit\nagainst some buggy 3rd party suid binary which it claims to mitigate)\nwith simplest exploit math. I further outlined that the claims of confinement\nwere wrong.\nNo kernel exploits such as [these](http://grsecurity.net/~spender/exploits/) were required. Kernel security is a different topic, best discussed with spender.\n\n##### Epilogue\n\nYou might be surprised to hear that despite this writeup I am\nstill convinced that MAC systems (and the SELinux type enforcement\nin particular) are still very valuable. At least the SELinux core (the\nkernel part and some of the libraries) are of good code quality and\ntype enforcement has been well researched. If you play a little bit\naround with it you immediately see its value and get to know that\nit has its beauty. However, type enforcement does not allow to switch\noff the brain and to frame around a lot of crap that eventually just throws\naway what the MAC system initially bought you.\nIn fact, SELinux has silently become the largest installation base of a MAC\nsystem by the SEAndroid rollout since __KitKat__, without major problems.\n\nLet me stress that I dont point at people making bugs/mistakes. I certainly\nhave enough stupid bugs in my own code. However, projects making claims\nand presentations based on wrong assumptions deserve a deeper look. In\nparticular if made by organizations that play the interdiction game on\nthe backflip of the coin.\nI just felt it was necessary to demonstrate how it would look like when I\ntarget a MAC system and that mitigation of exploits _not_ targeting type\nenforcement has to be put in context since today.\n\n##### Donations\n\nIf you like __troubleshooter__, please consider donating at the\ndonation button [here](https://c-skills.blogspot.com)\nor to the [SELinux rescue funds](https://supporters.eff.org/donate) with\nsubject _troubleshooter_.\nThanks in advance. I am doing this work as part of my _Dr.xSports._\nthesis by grant No. 743c13377350.\n\n##### References\n\n* [SELinux project](http://selinuxproject.org/page/Main_Page)\n* [setroubleshoot](https://fedorahosted.org/setroubleshoot/)\n* [setroubleshoot git](https://git.fedorahosted.org/git/setroubleshoot.git)\n* [Mandatory Access Control (MAC)](http://en.wikipedia.org/wiki/Mandatory_access_control)\n* [grsecurity](https://grsecurity.net)\n* [docker exploit](http://stealth.openwall.net/xSports/shocker.c)\n* [KitKat + SEAndroid](https://software.intel.com/en-us/android/articles/android-security-customization-with-seandroid)\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstealth%2Ftroubleshooter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstealth%2Ftroubleshooter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstealth%2Ftroubleshooter/lists"}