New Navigation Buttons

April 25, 2007

Long-lasting readers may have noticed a few minor tweaks over the past week or so to the main site – the background to the main text has been getting lighter, so that it has now actually become white. Also, I have added new navigation buttons:Click to View

What do you think? Are these useful navigation aids, Do they make the pages too slow to load (there should only be one new 4Kb image per page), or is it much as before?

Any feedback on the new look of the main shell tutorial is, as ever, greatly appreciated.


suid shell scripts – setting “the SUID bit”

April 21, 2007

I just found an excellent explanation of why suid shell scripts are a very bad idea.

So just be glad that most modern OSes don’t allow it. You really don’t want to do it, in the first place.

Yes, yes, yes. I know. You do want to do it, and you’re really really sure (really really really sure) that it will all be nice and secure; you’ve got a firewall, completely trusted users, regular password changes, and all the rest of it.

You still don’t want to do it.

Do it in C – you could even get away with a C wrapper, if you must.

But – and let me be quite clear on this:

Don’t do it. It really isn’t worth it, however much it seems, right now, to be a good idea.

What is the “SUID bit”?

The suid bit, is what you get from a “chmod u+s” command, which will set the permissions to “-rwsr-xr-x”, or similar (note the “s” replacing the usual “x”). That means that you can run certain commands with the permissions of a different user (typically root). This is very useful -for example, a normal user under Linux can’t open an ICMP socket (see footnote), so they can’t run the ping command. As a fix, it’s suid root:

$ ls -l /bin/ping
-rwsr-xr-x 1 root root 30848 2007-03-05 04:25 /bin/ping

okay, it’s owned by “root”, and the SUID bit is set. It will work fine, because ping itself has root permissions:

$ /bin/ping -c 1 localhost
PING localhost (127.0.0.1) 56(84) bytes of data.
64 bytes from localhost (127.0.0.1): icmp_seq=1 ttl=64 time=0.060 ms
--- localhost ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.060/0.060/0.060/0.000 ms

Good stuff. Now, what if we make a copy? That copy will be owned by a normal user (“steve”, in this example), so it won’t have root permissions:

$ cp /bin/ping /tmp/
$ ls -l /tmp/ping
-rwsr-xr-x 1 steve steve 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted

It still had the SUID bit set, it’s just the owner that changed. Let’s just confirm that it’s the “suid + root” that mattered:

$ chmod 755 /tmp/ping
$ ls -l /tmp/ping
-rwxr-xr-x 1 steve steve 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted

And what if it’s owned by root?:

$ sudo chown root:root /tmp/ping
$ ls -l /tmp/ping
-rwxr-xr-x 1 root root 30848 2007-04-22 00:46 /tmp/ping
$ /tmp/ping localhost
ping: icmp open socket: Operation not permitted
[footnote]: Why can’t I “ping”?

The reason that Linux ping has to be run as root, isn’t because ping itself is inherently dangerous, but the things that it does (open network connections, sends data over the network to other machines, and receives data back from them) are potentially dangerous. Therefore, those functions are restricted to the root user. So ping can be seen as a special subset of commands which – whilst they do these potentially dangerous things, do them in a safe and secure manner. This means that the ping command can be elevated to superuser status by the “SUID bit”: It’s a trusted user of certain potentially dangerous commands.

A taxi cab is a useful thing, but it could be used for a ram-raid. The taxi cab, in this case, is like the network protocol. The taxi driver is ping. We trust ping to do the Good Stuff, and not the Bad Stuff. So, we don’t let anyone get in and start driving the taxi, but we do let anyone get in and ask the taxi driver to take them somewhere. The command “ping DoS attack http://www.google.com” will not work – although another network utility, with the same permissions, may well perform a DoS attach. Similarly, getting into a taxi and telling the driver to “drive into that electronics store front window, wait for me to pile the car up with goods, and take me to my hiding place” is not likely to work. If you had a car (had root access) yourself, you could do it, but you can’t (well, should not be able to) convince these trusted services to do nasty stuff on your behalf.

For that reason, we need to be very picky about what code gets the “SUID bit” promotion – the restrictions are there for a reason, so any program with a SUID bit must be able to prove that it will “only use its powers for good, and not for evil”, in the good old melodramatic cliche.

Black-hat hackers will spend a lot more time looking at a suid program like ping than at they will at a normal program like cat, even though cat is far more flexible. If mkdir had the SUID bit set, all kinds of mayhem would ensue.

For shell scripts, where security-through-obscurity is not even possible (chmod permissions of r-x are required, at a minimum, so everyone who can run the script, can read exactly how it was written), suid is always to be avoided.


Regular Expressions

April 18, 2007

http://etext.lib.virginia.edu/services/helpsheets/unix/regex.html has a good introduction to Regular Expressions – grep, sed, and friends.

It includes a brief discussion on Backreferences (aka “the stuff that * matched”)


Tool Tip: “Read” – it does what it says!

April 14, 2007

read is a very useful tool; it might seem too simple to bother mentioning, but there are at least three different ways to use it. (Okay, two, and the third isn’t really anything special about read, just a nifty thing that the shell itself provides)…

1. Read the whole line

Let’s start with an interactive script:

$ cat readme.sh
#!/bin/sh
echo "I'm a parrot!"
while read a
do
    echo "A is $a"
done
$ ./readme.sh
I'm a parrot!
hello
A is hello
one two three
A is one two three
piglet eeyore pooh owl
A is piglet eeyore pooh owl
^D
$

Yes, you’ll need to hit CTRL-D to exit this loop, it’s just a simple example.

So far, so stupid. But wait; what if I wanted to get that “one” “two” “three” and use them differently?

2. Read the words

$ cat readme.sh
#!/bin/sh
echo "I'm a parrot!"
while read a b c
do
        echo "A is $a"
        echo "B is $b"
        echo "C is $c"
done
$ ./readme.sh
I'm a parrot!
hello
A is hello
B is
C is
one two three
A is one
B is two
C is three
piglet eeyore pooh owl
A is piglet
B is eeyore
C is pooh owl
^D
$

So, just by naming some variables, we can pick what we get. And – did you see that last one? We don’t lose anything, either… Just because we asked for three variables (a, b, c) and we got 4 values (piglet eeyore pooh owl), we didn’t lose anything; the last one was treated like a normal read.

This is actually pretty handy stuff; you’d have to do a bit of messing about with pointers to get the same effect in C, for example.

3. Read from a file

We can do all this from a file, too. This isn’t special to read, but it’s often used in this way. See that “while – do – done” loop? It’s a sub-shell, and we can direct whatever we want to its input (everything is a file, remember, so the keyboard, a text file, a device driver, whatever you want, it’s all just a file)

We do this with the “<” operator. Just add “< filename.txt” after the “done” end of the loop:

$ cat readme.sh
#!/bin/sh
echo "I'm a parrot!"
while read a b c
do
        echo "A is $a"
        echo "B is $b"
        echo "C is $c"
done  < myfile.txt
$ cat myfile.txt
1 2 3
4
5 6
7
8 9 10 11 12 13
14
15 16 17
$  ./readme.sh
I'm a parrot!
A is 1
B is 2
C is 3
A is 4
B is
C is
A is 5
B is 6
C is
A is 7
B is
C is
A is 8
B is 9
C is 10 11 12 13
A is 14
B is
C is
A is 15
B is 16
C is 17

So we can process tons of data, wherever it comes from.

4. I only mentioned 3 uses

We could make the script a bit more useful, by allowing the user to specify the file, instead of hard-coding it to “myfile.txt“:

$ cat readme.sh
#!/bin/sh
echo "I'm a parrot!"
while read a b c
do
        echo "A is $a"
        echo "B is $b"
        echo "C is $c"
done < $1
$ cat someotherfile.txt
123
1 2 3
one two three four
$ ./readme.sh someotherfile.txt
I'm a parrot!
A is 123
B is
C is
A is 1
B is 2
C is 3
A is one
B is two
C is three four
$

Update 14 April

Updated to fix the “done < filename.txt” from the example code of the last two examples.


More maths stuff – bc in detail

April 8, 2007

There’s a great post about bc at basicallytech.com – I think that I’ve already covered most of the same ground, but it’s got lots of great examples.


Follow

Get every new post delivered to your Inbox.