"Best Way" to inhibit halting of workstations (sou
Brent Chapman
capmkt!brent at uunet.uu.net
Fri Apr 21 23:17:57 AEST 1989
# What is the best way to stop non-staff personel from halting a workstation
# and then booting it up in single user mode as root?
#
# I've seen numerous suggestions posted here. I would like to know what
# method has proved the most secure and feature free in practice.
If you're running 3.x, you can use the following bit of code. It is
executed instead of /bin/sh by /etc/init when going into single user mode,
and prompts the user for the root password; if the user supplies the
correct password, then /bin/sh is invoked as usual, but otherwise (after 3
failed password attempts) the machine is halted.
Read the comments very carefully and think hard before proceeding; this
"fix" involves a binary patch to /etc/init, and if you make a mistake,
recovery could be painful. If you make a mistake and break your
/etc/init, you will _not_ be able to boot from your normal root, not even
single user. If this happens to you, you'll have to boot from an
alternate root (from tape, or from a server somewhere) then mount your
"real" root and restore the old /etc/init; this can be a real hassle, and
can ruin your whole day.
I'm not trying to disuade anyone from using the program (it's fairly
simple, and closes a serious security hole in 3.x systems); I just want
everyone to be damn sure they understand how tricky it is to install, and
what the consequences can be if a mistake is made during installation.
Anyway, with all those caveats, the code is appended to the end of this
message.
-Brent
--
Brent Chapman Capital Market Technology, Inc.
Computer Operations Manager 1995 University Ave., Suite 390
brent at capmkt.com Berkeley, CA 94704
{cogsci,lll-tis,uunet}!capmkt!brent Phone: 415/540-6400
======== file "sq.c" follows ========
/*
* This program forms a small layer between init and /bin/sh to prompt
* for the root password before going to single user mode;
*
* to augment security by preventing users acquiring root privileges
* by shutting down the system with L1-a and consequently starting
* the system single-user;
*
* made & installed by the following (you must be root to do the install):
*
* cc -O -o sq sq.c
* install -m 0700 -o root sq /bin/sq
*
* this program should be in /bin/sq and then you can patch /etc/init
* at address 0x2000c to exec /bin/sq instead of /bin/sh.
*
* Become super-user and issue the following commands. This patch to
* /etc/init makes it start /bin/sq rather than /bin/sh. /bin/sq starts
* /bin/sh if and only if the user enters the correct root password. You
* must do the mv & cp before beginning because the current /etc/init file
* is "busy" (because the program is running) and can't be modified. First
* create the new copy of init, then check to make sure that your 'init' is
* the same as mine:
*
* mv /etc/init /etc/init.old
* cp /etc/init.old /etc/init
* echo "0x2000c?s" | adb /etc/init
*
* If you don't get the following response, STOP HERE, because the patch
* isn't going to work (if you feel comfortable doing so, you could try
* to figure out where "/bin/sh" is in your /etc/init, and modify the
* patch below accordingly). The response you should get to the last
* command above is:
*
* 0x2000c: /sh
*
* Like I said, if that's not the response you get, then the following patch
* won't work, and is likely to do strange and wonderful things to your
* /etc/init. Anyway, if that _is_ what you get, the 0x2000c _is_ the righ
* location, and you can do the following to change init's exec of "/bin/sh"
* to "/bin/sq". Note that adb is _very_ case sensitive; the capital W is
* quite significant...
*
* echo "0x2000c?W 0x2f737100" | adb -w /etc/init
*
* Note that one should not forget the root password, otherwise
* miniunix should be loaded from tape; the rootfs should be mounted
* in /a after booting disk(,,1)vmunix -as etc.
*
* Note also that this solution works for SUN Release 3.2, 3.4, and 3.5.
* It probably works for other 3.x versions. It almost certainly DOESN'T
* work for 4.0, but it isn't needed for 4.0, either (you can just remove
* the "secure" attribute from the console line in /etc/ttytab).
*
* The user gets two tries to enter a valid password; if he fails,
* the program halts the machine.
*
* This code originally received from Carol Wilwelmy (carolw at sun.com)
* of Sun Microsystems, and subsequently adapted by D. Brent Chapman
* (brent at capmkt.com) of Capital Market Technology, Inc. Both of us
* will be pleased if you find our work useful, but you're playing with
* the very guts of your system; if you screw it up, the "solution" may be
* worse than the problem it solves...
*
* NO WARRANTIES; USE AT YOUR OWN RISK!!! If you screw up your 'init',
* you'll have to boot your system diskless from tape or a server in order
* to restore the old version of init (which you were supposed to save
* before you started playing around).
*/
#include <pwd.h>
#include <signal.h>
#include <sgtty.h>
#include <sys/file.h>
extern struct passwd *getpwnam();
extern char *crypt(), *getpass();
extern int (*signal())();
extern int alarm();
char *sorry = "\rSorry\n\r";
char *failed = "\r/bin/sq: getpwnam and getpwuid for user root failed\n\r";
char *halt = "/etc/halt";
char *halting= "\rHalting machine\n\r";
void
punt(status)
int status;
{
write(2, halting, strlen(halting));
execl(halt, halt, 0);
/* shouldn't get here, but just in case... */
exit(status);
}
main(argc, argv)
int argc;
char *argv[];
{
char *password;
struct passwd *pwd;
int i;
if (argc == 1 && strcmp(argv[0], "-") == 0) {
if (access("/single_shot", F_OK) == 0)
goto ok;
if ((pwd = getpwnam("root")) == (struct passwd *)0) {
/* apparently no user called "root"; try for uid==0 */
if ((pwd = getpwuid(0)) == (struct passwd *)0) {
write(2, failed, strlen(failed));
punt(1);
}
}
if (pwd->pw_passwd[0] == '\0')
goto ok;
for (i = 0; i < 2; i++) {
password = getpass("Password:");
if (strcmp(pwd->pw_passwd, crypt(password, pwd->pw_passwd)) != 0) {
if (i == 0) {
write(2, sorry, strlen(sorry));
continue;
}
write(2, sorry, strlen(sorry));
punt(2);
}
else
break;
}
}
ok:
execv("/bin/sh", argv);
/* shouldn't get here */
punt(3);
}
More information about the Comp.sys.sun
mailing list