Subject: Bug#1465: Allow running with restricted shell (rbash), or limit applications that can be run.

From: Vladislav Kurz <[email-masked]>
Date: Wed, 22 Apr 2020 18:20:29 +0200

Package: x2goserver
Version: 4.1.0.3-0~1708~ubuntu16.04.1
Severity: wishlist

Hello all,

we are using x2go to run a single application on remote server, and we want to 
lock all other access as much as possible. Essentially, we'd like to ensure 
that even if the user connects via SSH, he could start only one (or limited 
set) of applications.

I found this guide https://wiki.x2go.org/doku.php/wiki:security:rbash but it 
seems to be somewhat outdated. I followed the instructions, created the 
wrapper command, set up the symlinks, and configured ssh, but then I get this 
error: Connection failed. rbash: bash: command not found

Apparently x2go client is trying to execute "bash /usr/bin/x2goruncommand" 
instead of just "x2goruncommand". If I add bash to the path with allowed 
commands, it starts working. But it makes the whole use of rbash pointless.
Also it allows me to run anything via x2go anyway - as x2goruncommand is a 
bash script, it escapes the restrictions of rbash.

Is it possible to update that wiki page with current requirements - what 
commands are necessary in $PATH for restricted shell ? I found that at least 
nxagent should be there too. And to modify the login sequence so that bash is 
not needed in $PATH ? BTW is that defined on server or client? Where exactly?

I also found a nice feature "published applications"
https://wiki.x2go.org/doku.php/wiki:advanced:published-applications
It would be nice, if the x2go server had a config option, allowing users to run 
only the "published applications", or use some other list of allowed commands.

So far my attempts at limiting the access to other applications was not very 
successful. There's a lot of stuff needed internally by x2go, so I cannot just 
remove execute bit from many commands in (/usr)/bin/

Thanks for any advice or hotfix.
Best Regards

Vladislav Kurz

---

From: Stefan Baur <[email-masked]>
Date: Mon, 4 May 2020 13:10:33 +0200

Am 04.05.20 um 10:12 schrieb Vladislav Kurz:

[...]

> What we need is to block users from copying files from the x2go server. So we 
> have to deny /bin/cat or /bin/dd to be invoked via ssh. But x2go will not 
> connect without /bin/cat being executable.

Sorry to disappoint you, but ...

in the early days of computing, there was a software copyright
infringement case in a German court of law, and the judge, being new to
computers, after having listened to all the expert witnesses, summed up
his impression as "A computer is a machine to copy ones and zeroes."

And that's the truth.

There are so many ways that files/data can be copied from a machine a
user has access to that you *will* fail blocking it.

(Of course, this isn't fully valid for files the user has no access to
at all - but what a user can read, they can copy.)

This is by all means anything but a comprehensive list, just a few ideas
most people don't think of at all:

- X2GoClient has file sharing built in.  It's easy to hide the feature,
  but users that know that it's there may still be able to use it.
- Users can create their own executables.  Or bash scripts.
  Or Perl Scripts.  Or, or, or.  (Yes, mounting all directories they
  have write access to -noexec does help.  A tiny little bit.)
- Bash itself has a netcat-like TCP and UDP client module built in. See
  "man bash", search for "/dev/tcp/host/port" and "/dev/udp/host/port".
- You could probably write a QR encoder in the macro language belonging
  to LibreOffice or whatever word processor is in use on the system.
  Then the user points their smartphone at the screen, scans the code,
  decodes the content.
- Web browsers allow upload forms.  And JavaScript, which could also be
  used for a QR encoder.
- Command line web browsers like lynx, elinks, even wget and curl can be
  used to upload files.
- Anything that works as a hex editor/hex viewer can be used to display
  even binary content on the screen, which can then be screenshotted
  either digitally or using a smartphone camera/webcam pointed at the
  screen.  These days, OCR does a pretty good job at reassembling such
  data.
- They could also use professional screengrabbing equipment, either as
  software or hardware looped into the VGA/HDMI cable.  (Oh, and even if
  you were to use the copy-protection features of HDMI - forget about
  it.  There are cheap Chinese HDMI converters that don't give a shit
  about that copy protection and will stream the unencrypted signal to
  whatever recording device you hook up to them.)
- They could attempt to use morse code, or even create a serial
  connection, making the keyboard CAPS LOCK/NUM LOCK/SCROLL LOCK LEDs
  blink and either use software on the client to decode it, or have
  light sensors on their keyboard LEDs to interpret the signals. (one
  LED would be CLOCK, the other DATA; for the return path, the third LED
  would be CLOCK, and e.g. a simulated space or shift or CTRL key push
  would be DATA).  Commands to make the LEDs blink are available both
  for the console and for X11.

etc. etc. etc.

Even if you find solutions for the points I listed above, there will be
way more.  And all it takes it one way you didn't think of, but your
user did think of, and you're fucked.

>> Anything X2Go would try place on top of that would be bound to fail, as
>> it can easily bypassed by a user running X2Go with a custom
>> configuration, or SSHing into the machine with ssh -X, thus bypassing
>> X2Go entirely.
> 
> Would it be possible to make some sort of wrapper that could be set as user's 
> shell that will allow only establishing x2go session? Something like setting 
> x2goruncommand as users shell?  Something like scponly. Then one could focus 
> on blocking only x-applications like xterm, etc.

No.  You would not be the first to try, but you will also not be the
last to fail if you try.

You need to realize the truth: What a user can see (as in "access"),
they can copy.

So, if you're looking to block access to certain executables: Yes, that
may work, with varying levels of success.  If you're looking to block
users from copying data they are supposed to have read access to: Forget
about it.

Even if you managed to block every transfer other than to the screen
itself, you'd basically have to strap VR goggles to their head, verify
their identity via retina scan, and immediately cut off the display
stream if they attempt to take the goggles off. ;-)
And even then you run the risk that someone hacks the VR goggle hardware
in a way that you can't detect and taps recording equipment into the
stream.  Or that one of your users has eidetic memory and can just write
down/draw everything they saw after the session ends.

-Stefan

-- 
BAUR-ITCS UG (haftungsbeschränkt)
Geschäftsführer: Stefan Baur
Eichenäckerweg 10, 89081 Ulm | Registergericht Ulm, HRB 724364
Fon/Fax 0731 40 34 66-36/-35 | USt-IdNr.: DE268653243

---

From: Ulrich Sibiller <[email-masked]>
Date: Mon, 4 May 2020 14:06:31 +0200

> You need to realize the truth: What a user can see (as in "access"),

Well, I basically agree with what you wrote. But the OP was mentioning
he just wants to provide _one_ single published application.

Now let us assume some pre-conditions:
- the application is unable to display the data you want to protect.
If not, all the ways you mocked up above could be used and the
approach will not work
- the application cannot start other apps like an xterm or a shell on
user request
- there's only ssh access
- the x2go scripts are sane and secure

Then all we'd need was
- a restricted ssh-key that only allows for the commands that are
required for the x2go session handling
- ensuring the x2go session handling will only start that single
application and no other user specified command.

The user then can still configure arbitrary sessions but they will
either always fail or ignore the user's command and run the one
application in question. We could also provide a server side setting
that only allows published application connects.

It will not work out of the box but I am pretty sure it could be implemented.

Also, IIRC Mihai added an explicit bash call into certain commands to
make it work fur users with a different login shell. And obviously the
original rbash instructions worked before. So you could also try to
set that up and do some research where to remove the explicit bash
calls.

Comments?

Uli

---

From: Stefan Baur <[email-masked]>
Date: Mon, 4 May 2020 14:30:26 +0200

> If not, all the ways you mocked up above could be used and the

And that's the catch: If the application can't display the data - then
why would the user need access to it at all?  chmod/chown it away from
them and you're good to go.  But obviously the data is needed *somehow*,
or else they wouldn't have the problem of wanting to hide it from the user.

If it's raw data vs. processed data (e.g. points of data in a CSV file
vs. a graph generated from it), then (and only then) the solution is simple:
You need an app (a daemon, probably - though it might be done per-call
with passwordless sudo or the suid bit set on that app) that processes
the raw data and runs under another account, and another app that is
able to talk to this app, which can only display the processed data.
That way, you can use file system permissions to "wall off" the raw data
so only the processing app can access that data.

> - the application cannot start other apps like an xterm or a shell on

And that is particularly hard, as experience shows.  Even a "file
chooser" dialog from a standard GUI toolkit that you use for selecting a
data file will usually offer you a right-click option with "execute".
Navigate to the xterm binary (path traversal via ../../../ and the like
is another problem to keep in mind, even if you're able to hide critical
directories from view) and there's your shell.
One such item that you forget about, and boom - you've been exploited.

> - the x2go scripts are sane and secure

That's something I wouldn't want to bet my money on without an extensive
audit.  And even then there's the risk that the audit missed to spot
something.

> required for the x2go session handling

Which doesn't work out of the box.  You can specify exactly one command.
To be able to use more than one, you need a wrapper script on the host
that is set as forced command, which then parses $SSH_ORIGINAL_COMMAND.
These scripts are notoriously bad to maintain, error-prone, and while
they work with scripted commands (e.g. running an automated rsync job
with varying target directories), they suck hard for interactive use.

> It will not work out of the box but I am pretty sure it could be implemented.

To me, it sounds like a horrible kludge that is bound to collapse rather
sooner than later, and it would only offer a false sense of security.
Making false promises is something we should leave to the Microsoft
Windows world, I'd say. ;)

> set that up and do some research where to remove the explicit bash

Given that bash is enforced there for a reason, it doesn't sound like a
good idea to replace it with something else.

-Stefan

---

From: Vladislav Kurz <[email-masked]>
Date: Mon, 04 May 2020 15:34:22 +0200

Hello,

I'm not sure If I should post to @bugs.x2go.org or x2go-dev mailing list.

> or else they wouldn't have the problem of wanting to hide it from the user.

I have to explain it. The protected thing is openoffice sheet with some complex 
formulas. The formulas should be protected from viewing by openoffice somehow 
(that was not my task so I did not really check that in detail). Users fill in 
input data, get the results, and can print them via CUPS to PDF (or paper). We 
do not want them to get the sheet and use it elsewhere. They are allowed to 
make work copies of the sheet within the protected environment, but should not 
be able to get it out.

So openoffice is the only application they are supposed to run.
I do not want them to be able to run shell at all. Ideally, they should be 
kicked away if they log in with plain ssh.

> X2GoClient has file sharing built in.  It's easy to hide the feature,

I managed to block file transfer in x2go - by uninstalling fuse on server. 
Although it would be nice to have some switch to disable it server side, and 
allow fuse for other uses.

> Web browsers allow upload forms.  And JavaScript, which could also be
>  used for a QR encoder.
> Command line web browsers like lynx, elinks, even wget and curl can be
>  used to upload files.

The environment is quite limited and all browsers and similar stuff was either 
uninstalled or chmod 750, so that only root or trusted users can run run it.
Especially xterm, so that there is no reasonable way to run shell via x2go.
openoffice is the only x-application installed.

> They could also use professional screengrabbing equipment...

Using camera to make a screenshot is not a problem. The results of the 
calculation are not protected.

> with varying target directories), they suck hard for interactive use.

That was doing the wrapper mentioned in my original post. I don't know what 
commands are sent by the x2go client. But if it would be just one command that 
it could be put into the ssh forced command.

If I would not need x2go for bandwidth reasons, I would just put oocalc in 
forced commands and use ssh -X. That would provide the protection level I'm 
aiming for.

> good idea to replace it with something else.

I do not want to replace it. Just need to execute the script like:
x2goruncommand ...    (to let it be found in $PATH)
and not 
bash /usr/bin/x2goruncommand ...
That will let me use rbash which is close to what I need.

The question is where is this call written? Can I modify it myself?
I was trying to find it on server side but failed.

Best Regards
Vladislav Kurz

---

From: Stefan Baur <[email-masked]>
Date: Mon, 4 May 2020 16:06:59 +0200

> I'm not sure If I should post to @bugs.x2go.org or x2go-dev mailing list.

Since you opened a bug report, use <[email-masked]>, that way, all
the right things (TM) will happen automagically.

> make work copies of the sheet within the protected environment, but should not 

And that's your design flaw that you need to fix.

You really need to separate the logic from the data, so the users can't
access it.

You could, for example, try using stored procedures in a database, and
use Libreoffice or a Web browser as the GUI front end for the database
access.

Or you could try using Libreoffice in headless mode, by querying
parameters from the users in a script, properly sanitizing them
(whitelist the allowed input characters, instead of blacklisting
potentially troublesome ones), then passing them on to be inserted in a
template of your spreadsheet, and automatically print the result to a
PDF.  That way, the users won't be in direct contact with your precious
formulas, but only with a script you wrote (which would then call
libreoffice under a user id that has permission to access the
spreadsheet), and with a PDF viewer.

If the users have access to Libreoffice, and to your spreadsheet, they
*will* be able to come up with a way to copy your file.  And if it is
formula by formula using a QR code or OCR.

For example, Libreoffice Basic - the Macro language used by Libreoffice
that any user can write macros in - allows raw file I/O.
So it would be possible to read your spreadsheet file byte-by-byte
(bypassing any Libreoffice-internal protections it may have), encode it
in a QR code (current Libreoffice even has its own QR encoder built in),
then scan that code on the client, and save the result as a file.
And once it is stored on the attacker's machine, they can brute-force
their way into whatever protection you tried to apply, until they see
your formulas.

There is NO WAY of making it safe if you don't separate formulas and
data from each other.  X2Go won't help you.  Switching to a different
remote access solution won't help you.  Switching operating systems
won't help you.  Your problem is not X2Go, but how mighty and versatile
Libreoffice is.

You're trying to mitigate a severe security/privacy flaw in your basic
design with kludgy workarounds, instead of fixing it properly.  This is
hopeless and won't end well.

-Stefan

---

From: Ulrich Sibiller <[email-masked]>
Date: Mon, 4 May 2020 16:36:53 +0200

> or else they wouldn't have the problem of wanting to hide it from the user.

Well, there a things a user requires for the app to run but must now
get into his hands. Think about a special plugin that does some
calculation. Or think about a license file that he requires for his
application to start. Believe me, license-wise you'll find the oddest
conditions where chmod'ing them away is not an option (we had one
license software that requires the user to have WRITE access to the
license file...).

> so only the processing app can access that data.

Well, depending on the app this might be possible - or not.

> data file will usually offer you a right-click option with "execute".

Well, I have not seen "execute" yet, but I have seen "open in file
manager" and the like. This could be covered with SELinux.

> One such item that you forget about, and boom - you've been exploited.

Like in every other situation you are not safe if there are bugs in
the software. So this is - with the exception of the x2go code itself
- negligible here.

> audit.  And even then there's the risk that the audit missed to spot

Yes, that risk is always there. Putting your data at a network
attached machines brings them to risk. You as the user decide if you
are ready to take the risk or not.

> with varying target directories), they suck hard for interactive use.

Well, there's no interactive use here, it is just the session setup. I
have written such scripts. It is doable.

> sooner than later, and it would only offer a false sense of security.

Well, as long as you know what your application can do and what not it
should be handable.

> Windows world, I'd say. ;)

;-)

> good idea to replace it with something else.

I have done some research. The reason is that before the scripts used
/bin/sh which is unspecific and might point to other shells. As the
scripts seem to use one or the other bashism this is problematic.

Uli

---

From: Stefan Baur <[email-masked]>
Date: Mon, 4 May 2020 17:01:10 +0200

> license software that requires the user to have WRITE access to the

That's third-party stupidity.  Here, however, the issue is with their
very own "product" design.

[...]

> manager" and the like. This could be covered with SELinux.

Messy, messy, messy.

> the software. So this is - with the exception of the x2go code itself

Not so fast.  This is code that is usually not part of the application
itself, but part of a framework like Qt.  You're importing their bugs.

[...]

> are ready to take the risk or not.

The situation here is a bit different: The *user* totally doesn't mind
if the intellectual property is available like that.  The owner,
however, does ...

> have written such scripts. It is doable.

Then there's an update to the X2Go package that introduces a subtle
change, and boom, your script fails.  Users start to complain and you
are in a hurry to find out what the cause is.  Chances are that in your
panic, you don't think of the wrapper as the probable culprit.

It's a royal pain in the ass.  I've been there.  Which is why my

> Well, as long as you know what your application can do and what not it

And here's the next catch: They intend to use Libreoffice as their
single published application.  Which allows the user to write their own
macros in Libreoffice Basic.  Which allows them to read binary files and
do things with them.  Like convert them to a bunch of QR codes and
display them.  So to do the things that need to be done, they (the
owners) are depending on an executable which the user can do so much
more with than they want it to do.  And there's no way to limit that,
other than to refrain from using Libreoffice as a front-end.

-Stefan

---

From: Vladislav Kurz <[email-masked]>
Date: Mon, 04 May 2020 17:50:11 +0200

> scripts seem to use one or the other bashism this is problematic.

The proper way then is to put #! /bin/bash into the script that requires it. 
Not to invoke it using "bash script"

Vladislav Kurz

---

From: Vladislav Kurz <[email-masked]>
Date: Mon, 04 May 2020 18:00:42 +0200

> other than to refrain from using Libreoffice as a front-end.

With full respect to the users, if they were capable of that, they would 
probably be able to write similar spreadsheet from scratch (and have some 
other job).

I know that redesigning the whole calculation as web application would be much 
better. But if protection against 80% of users can be done with 20% effort, I 
would do it. You say that 100 % protection is not possible, so there is no 
reason to do anything...

All I want is to close this one obvious hole:
ssh somewhere "cat file" > file

I cannot remove exec bit from /bin/cat, cause it is required to set up x2go 
session. If the rbash guide I referenced at the beginning worked, this would 
be possible.

Best regards
Vladislav Kurz

---

From: Stefan Baur <[email-masked]>
Date: Mon, 4 May 2020 18:40:36 +0200

> would do it. You say that 100 % protection is not possible, so there is no 

As previously explained, there is probably no need to code the whole
application as a web app.  All you need should need, in my opinion, is a
frontend (GUI+X2Go, or Web, doesn't matter), proper input sanitizing,
and libreoffice in headless mode.

*.ods files are ZIP archives, so you can unzip them like so:

unzip samplecalc.ods

Archive:  samplecalc.ods
 extracting: mimetype
 extracting: Thumbnails/thumbnail.png
   creating: Configurations2/accelerator/
   creating: Configurations2/popupmenu/
   creating: Configurations2/toolpanel/
   creating: Configurations2/menubar/
   creating: Configurations2/images/Bitmaps/
   creating: Configurations2/toolbar/
   creating: Configurations2/floater/
   creating: Configurations2/statusbar/
   creating: Configurations2/progressbar/
  inflating: content.xml
  inflating: meta.xml
  inflating: styles.xml
  inflating: manifest.rdf
  inflating: settings.xml
  inflating: META-INF/manifest.xml

You would then use xmlstarlet to modify the fields in content.xml.  Or
even simpler (but dirty), put some unique placeholders there and use sed
to replace them with your sanitized user-provided values.

Zip it all back together, and run:

soffice --convert-to pdf samplecalc.ods  --headless

This gives you a samplecalc.pdf that you can open in a PDF viewer or web
browser.

Or you could provide your users with a template *.ods with identical
fields, but lacking the formulas.

Have them fill out the fields in their "dumb" copy, then read the field
contents into your template and provide them with the output.  Either as
PDF or as *.ods again - with the value fields, but lacking the formulas
again.

No need to rape X2Go code for this.  In fact, it's probably safer and
saner to run all this on a web server.

-Stefan