Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Xrdp as unprivileged user #2974

Merged
merged 7 commits into from
Jul 2, 2024

Conversation

matt335672
Copy link
Member

@matt335672 matt335672 commented Mar 1, 2024

Fixes #2965

Parameters are added to xrdp.ini and sesman.ini to allow running as a non-privileged user.

The following issues were found in implementing this:-

  1. PID files either need to be made alterable and deleteable by the non-privileged user, or just left to be deleted elsewhere. It seems current best-practice is the second of these. I've gone with that approach.

  2. A problem was found with Update sockdir security #2731 which is fixed in commit 4471012. This should probably be factored out as a separate PR. Edit 2024-3-22: See Fix permissions on user socket directory #3011

  3. We know it's tricky to get permissions right for non-privileged xrdp - there's a constant theme of users who don't understand why TLS doesn't work out-of-the-box on Debian/Ubuntu (see Debian BTS #860890). To address this I've provided a script which checks file permissions are correct when the parameters in xrdp.ini are entered or changed. This is referred to from the xrdp.ini manpage.

By default, xrdp runs as root. User interaction is required to address this. I've done this more for porting than anything else.

I've completed initial testing on Ubuntu and FreeBSD. The permissions check script may not work on some more oddball systems like Alpine Linux.

This is a complex area and I may well have omitted something. Feedback most welcome!

BTW: As I write this, Github CI is broken. Hopefully it will be working by Monday.

@metalefty
Copy link
Member

Thanks! I'll look into this soon.

@metalefty
Copy link
Member

Overall, LGTM.

Isn't xrdp-chkpriv script installed? Also, we need a check for rsakeys.ini?

runtime_user and runtime_group are added to the xrdp.ini file
so that the service knows how to reduce privilege
- xrdp_listen.c is refactored so we can create the
  listening socket(s) before dropping privileges.
- The code which reads startup params from xrdp.ini
  is moved from xrdp_listen.c to xrdp.c, so it
  is only called once if we test the listen before
  starting the daemon.
Now we have g_file_open_rw() we don't need to try to write to
the PID file to see if we can. Just leave the file open and write to
it after forking.
If xrdp is running with dropped privileges it won't be able to delete
the PID file it's created. Places where xrdp is stopped need to cater
for this.

It's prefereable to do this than make the PID file writeable by xrdp
with dropped privileges, as this can still lead to DoS attacks if an
attacker manages to modify the PID file from a compromised xrdp
process.
@matt335672
Copy link
Member Author

Thanks for that.

I've just rebased to latest devel, built the software and installed to /tmp/xrdp with:-

make install DESTDIR=/tmp/xrdp

then:-

$ find /tmp/xrdp/ -name xrdp-chkpriv -ls
  1055408      8 -rwxr-xr-x   1 mjb      mjb          6470 Jul  1 11:16 /tmp/xrdp/usr/local/share/xrdp/xrdp-chkpriv

so the script is installed, but in /usr/local/share/xrdp as it's not something the user will be running regularly.

There's a privilege check for rsakeys.ini, but nothing else:-

$ sudo /usr/local/share/xrdp/xrdp-chkpriv
[sudo] password for mjb: 
Settings
 - [xrdp.ini]   runtime_user        : xrdp
 - [xrdp.ini]   runtime_group       : xrdp
 - [xrdp.ini]   certificate         : /etc/xrdp/cert.pem
 - [xrdp.ini]   key_file            : /etc/xrdp/key.pem
 - [sesman.ini] SessionSockdirGroup : xrdp

-Info- runtime_user 'xrdp' appears to exist
-Info- runtime_group 'xrdp' appears to exist
-Info- xrdp.ini and sesman.ini agree on group ownbership
-Info- /etc/xrdp/rsakeys.ini has correct permissions
-Info- /etc/xrdp/cert.pem is readable by xrdp:xrdp
-Info- /etc/xrdp/key.pem is readable by xrdp:xrdp

-Summary- Permissions appear to be correct to run xrdp unprivileged

Is that what you were expecting, or should I add something else?

I'll re-check the rebase on FreeBSD 14.

The unprivileged user needs to be able to read the certificate and
key files to offer TLS, but should not be able to write to then.

This commit checks the TLS files are read-only, rather than
simply readable
@matt335672
Copy link
Member Author

I've just added another check to xrdp-chkpriv, which is that the TLS files are readable but NOT writeable by the unprivileged user:-

$ sudo chmod 660 /etc/xrdp/cert.pem
$ sudo ./xrdp-chkpriv
Settings
 - [xrdp.ini]   runtime_user        : xrdp
 - [xrdp.ini]   runtime_group       : xrdp
 - [xrdp.ini]   certificate         : /etc/xrdp/cert.pem
 - [xrdp.ini]   key_file            : /etc/xrdp/key.pem
 - [sesman.ini] SessionSockdirGroup : xrdp

-Info- runtime_user 'xrdp' appears to exist
-Info- runtime_group 'xrdp' appears to exist
-Info- xrdp.ini and sesman.ini agree on group ownership
-Info- /etc/xrdp/rsakeys.ini has correct permissions
-Error- /etc/xrdp/cert.pem is writeable by xrdp:xrdp
-Info- /etc/xrdp/key.pem is read-only for xrdp:xrdp

-Summary- 1 error(s) found. Please correct these and try again
$ sudo chmod 640 /etc/xrdp/cert.pem
$ sudo ./xrdp-chkpriv
Settings
 - [xrdp.ini]   runtime_user        : xrdp
 - [xrdp.ini]   runtime_group       : xrdp
 - [xrdp.ini]   certificate         : /etc/xrdp/cert.pem
 - [xrdp.ini]   key_file            : /etc/xrdp/key.pem
 - [sesman.ini] SessionSockdirGroup : xrdp

-Info- runtime_user 'xrdp' appears to exist
-Info- runtime_group 'xrdp' appears to exist
-Info- xrdp.ini and sesman.ini agree on group ownership
-Info- /etc/xrdp/rsakeys.ini has correct permissions
-Info- /etc/xrdp/cert.pem is read-only for xrdp:xrdp
-Info- /etc/xrdp/key.pem is read-only for xrdp:xrdp

-Summary- Permissions appear to be correct to run xrdp unprivileged

It's rather obvious, looking back on it now.

@matt335672
Copy link
Member Author

See also https://github.com/neutrinolabs/xrdp/wiki/Running-the-xrdp-process-as-non-root which I've updated in anticipation of merging this.

@metalefty
Copy link
Member

so the script is installed, but in /usr/local/share/xrdp as it's not something the user will be running regularly.

Okay, I see. rsakeys.ini check also LGTM. It would be very nice if xrdp-chkpriv script generated colored output but it can be added later and it doesn't block this PR get merged.

@matt335672 matt335672 merged commit fced000 into neutrinolabs:devel Jul 2, 2024
14 checks passed
@matt335672 matt335672 deleted the xrdp_as_unprivileged_user branch July 2, 2024 07:57
@matt335672 matt335672 mentioned this pull request Jul 11, 2024
3 tasks
# mode

# Change these if they do not match your installation
CONF_DIR=/etc/xrdp
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@matt335672 We should use @sysconfdir@/xrdp for the default location. It will be set to /usr/local/etc/xrdp on FreeBSD.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Raised #3159.

metalefty added a commit to metalefty/xrdp that referenced this pull request Jul 12, 2024
While here, ignore build artifacts of chkpriv tools.

Follow-up to:   neutrinolabs#2974
nedix pushed a commit to nedix/xrdp-fork that referenced this pull request Oct 4, 2024
While here, ignore build artifacts of chkpriv tools.

Follow-up to:   neutrinolabs#2974
nedix pushed a commit to nedix/xrdp-fork that referenced this pull request Oct 4, 2024
While here, ignore build artifacts of chkpriv tools.

Follow-up to:   neutrinolabs#2974
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support running xrdp daemon as user privilege like Debian does
2 participants