Friday, February 12, 2010

Configuring a local Liveupdate repository with Symantec Endpoint and Linux

Seven or eight years ago, I decided to finally dump all the individual antivirus packages around here and go with a centralized system. I wasn't sure what I wanted, but I knew what I didn't want - Symantec. I knew they were the evil empire.

After going through two different vendors, this year I finally decided to try Symantec Endpoint Protection Small Business Edition, v. 12. I'm a convert. Incredibly lightweight, responsive, and... cost effective. As in, under $15 a seat cost effective. I love it.

Never bothered with their Linux version, even though it was included with my purchase. ClamAV has been doing just fine for us for years, thank you.

Until last month. For some reason - I assume the definition file - ClamAV is now taking forever to make a scan:

Data scanned: 803.16 MB
Data read: 240.92 MB (ratio 3.33:1)
Time: 8035.814 sec (133 m 55 s)

100K a second?  Let's see, to scan our home directory would take... about a week.

So, easy solution - I've got plenty of SEP licences left; it runs on Linux; it's very easy to administer on Windows - I'll just install SEP on my Linux boxes!

Well, as easy as the Windows install/administration was, the Linux install is that complex. First of all, the Linux download is hard to find. Once I had it I wanted to set up a local LiveUpdate server on the Windows box. Easy enough. Then, I had to point the Linux server towards the LiveUpdate server. That's when things got crazy.

The docs say that you should change the server name in /etc/liveupdate.conf, but there are at least two documented ways of doing so. In addition, they changed the port from 8080 to 7070 in the most recent LiveUpdate Administration release. So I got all of that sorted out in the file, ran liveupdate... and nothing happened.

Well, something happened, actually:

Command failed: Failure in pre processing of micro definitions before update.
Unable to perform update

and the /etc/liveupdate.conf file was nulled out.

After a couple of days of back-and-forth with Symantec (Linux? What's that?), I finally found someone who gave me this link:

http://service1.symantec.com/SUPPORT/ent-security.nsf/docid/2008050713154648


Cause:
Once executed, JLU reads the contents of the unencrypted liveupdate.conf file, runs LiveUpdate, and then encrypts the liveupdate.conf file to prevent tampering. The encryption level used is above the maximum encryption level allowed by default in Sun Java. JLU requires the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files be applied to the version of Java being used to execute JLU.


Solution:
To allow JLU to properly encrypt the liveupdate.conf file, you must apply the Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files to the installation of Java being used to execute JLU.

Ah.  I need super-secret crypto, available only to true believers.  So I went to Sun, eventually found the
Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files, downloaded them and replaced the on my system.  It consists of two files, local_policy.jar and US_export_policy.jar.  Replaced the files on my system with those, made a mental note not to ever let these machines leave the country, and...

Still didn't work.  Crud.

OK, one more tech request.  They sent me to this link on 'Configuring JavaLiveUpdate':

http://service1.symantec.com/support/ent-security.nsf/docid/2006021007250213

which was wrong in an interesting way.  The table it's got is off by one row - the 'Parameter' column lines up with the 'Description' of the row above it.

But it did give me a hint - it pointed me to a Liveupdt.hst file.  I'd seen this before on the Windows side; the LiveUpdate Administration docs told me how to generate this file, but not what to do with it.  This seemed to imply that I pointed 'hostfile=' to it.  So I generated it on the Windows side (Configure/Client Settings/Export Java Settings), moved it over, and put it into my /etc/liveupdate.conf file, which now reads:

hostfile=/opt/Symantec/symantec_antivirus/liveupdt.hst
logfile=/var/log/symantec/liveupdt.log

Hah!  That worked!

And it's slightly faster.  That 133-minute clamav scan finished in just under 8 minutes.

Sheesh.  But worth it, I think.

Tuesday, February 9, 2010

Samba 0-day

Samba has announced a 0-day exploit that's caused the computing world to sit up and... yawn. Details here: http://www.samba.org/samba/news/symlink_attack.html

I think SANS says it best:

"When is a 0day not a 0day? When the exploit ends up being just a poor default configuration issue. It can lead to files being read, that the user has permission to read."

So what we have here is an exploit that allows users to read files that... they have permission to read. No privilege escalation.

Yawn. If this really bothers you, add

[global]
wide links = no

to your smb.conf file, and restart. Of course, this will break allowing symlinks in an exported share.

Monday, February 8, 2010

Windows 2008 NTP problem?

I've got a Windows 2008 R2 server sitting as a guest on our RHEL 5.4 server.  I just happened to notice that the time was off.  Way off, like about six minutes.

The w32tm.exe utility has some interesting switches.  I used one to stripchart against the main time server:

C:\Users\Administrator>w32tm /stripchart /computer:buran
Tracking buran [192.168.1.200:123].
The current time is 2/8/2010 12:12:44 PM
12:12:44 d:+00.0077832s o:+416.5745527s
12:12:46 d:+00.0029019s o:+417.0718254s
12:12:48 d:+00.0019183s o:+417.5564322s
12:12:51 d:+00.0019141s o:+418.0448887s
12:12:53 d:+00.0019232s o:+418.5206214s
12:12:55 d:+00.0019154s o:+419.0251265s
12:12:57 d:+00.0019209s o:+419.5642993s
12:12:59 d:+00.0019262s o:+420.0780252s
12:13:01 d:+00.0019133s o:+420.5655424s
12:13:03 d:+00.0019161s o:+421.0448077s
12:13:05 d:+00.0028745s o:+421.5292839s
12:13:07 d:+00.0019101s o:+422.0110611s

Wow.  I'm losing a second every four seconds.  Not good.

I've got w32time set up in NTP mode on the Windows server, so I'm not quite sure what's going on here.  Until I figure it out, I'm going to set the system up to resync time once a minute.  That'll at least keep me within 15 seconds of reality.  Change

HKLM\SYSTEM\CurrentControlSet\Services\W32Time\Config\TimProviders\NTPClient\SpecialPollIntercval

to 60, and start/stop w32time

C:\Users\Administrator>w32tm /stripchart /computer:buran
Tracking buran [192.168.1.200:123].
The current time is 2/8/2010 12:26:40
12:26:40 d:+00.0048590s o:+09.2796603s
12:26:42 d:+00.0009300s o:+09.8433852s
12:26:44 d:+00.0019293s o:+10.4054516s
12:26:46 d:+00.0019263s o:+10.9600696s
12:26:48 d:+00.0019241s o:+11.4967021s
12:26:50 d:+00.0019256s o:+12.0280363s
12:26:52 d:+00.0019269s o:+12.5750087s
12:26:54 d:+00.0019231s o:+13.1260536s
12:26:56 d:+00.0019243s o:+13.6663052s
12:26:58 d:+00.0018872s o:+14.2191757s
12:27:15 d:+00.0009443s o:+00.1400540s
12:27:17 d:+00.0019228s o:+00.6581759s

Better.  Not perfect, but better, and the network will be able to handle an NTP request every minute.  Now, all I have to do is find out what's wrong...

Friday, January 29, 2010

Hard vs. symbolic links

I don't know why I don't use many hard links.  Habit, I guess. I'll try to break it.

A symbolic link is a special file that points to another file, i.e.

lrwxrwxrwx 1 root root 4 Jun 23  2007 awk -> gawk*

Delete gawk, and awk points nowhere - and won't work.  Delete awk, and nothing at all happens to gawk.

A hard link is simply a file that points to the same inode as another.  In effect, it's just another way of referring to the same file.  You can't tell by looking at it that it's a hard link, and if you delete it - or the file it's linked to - nothing happens to the other file.  The only clue you've got is by looking at the link count, that column in 'ls -l' that nobody knows what it is:

-rwxr-xr-x 3 root root 62872 Jan 14 14:06 gunzip
-rwxr-xr-x 3 root root 62872 Jan 14 14:06 gzip
-rwxr-xr-x 3 root root 62872 Jan 14 14:06 zcat

Each has a link count of 3.  That means that there are three different files sharing the same inode number.  And, sure enough:

[root@dg bin]# ls -i *z*
319701 gunzip  319701 gzip  319701 zcat

So why have three 'identical' files with different names?  Well, here's what I do with one of my scripts.

[root@dg scripts]# ls -lai start*
1357990 -rwxr-xr-x 3 root root 446 Jan 28 16:44 start
1357990 -rwxr-xr-x 3 root root 446 Jan 28 16:44 start_this
1357990 -rwxr-xr-x 3 root root 446 Jan 28 16:44 start_that

Same file, hard linked.

#!/bin/bash

 ECHO="/bin/echo"
 MAIL="/bin/mail"

 CALLED_NAME="`basename $0`"
 case $CALLED_NAME in
    start_this)
        ICDIR="/thisdir"
    ;;
    start_that)
        ICDIR="/thatdir"
    ;;
    *)
        ICDIR="/theotherdir"
    ;;
esac

 cd $ICDIR||{ $ECHO "$0 failed chdir"|$MAIL tim;exit 1; }

/usr/local/bin/icrun

So all I do is see how it's called, and operate accordingly.

I believe that in dg/ux, cp was a hard link to mv.

Thursday, January 28, 2010

Wrong files in the /etc/rcx.d directories

I was looking for something in /etc the other day, and didn't know if it was there or in a subdirectory.  So I did a grep -r:

[root@dg etc]# fgrep -ir "testing 1 2 3" *
fgrep: rc0.d/K88syslog: No such file or directory
fgrep: rc1.d/K88syslog: No such file or directory
fgrep: rc2.d/K88syslog: No such file or directory
fgrep: rc2.d/S40snortd: No such file or directory
fgrep: rc2.d/S12phone_log: No such file or directory
fgrep: rc2.d/S55zabbix_agentd: No such file or directory
fgrep: rc3.d/K88syslog: No such file or directory

Whoops.  That's not good.

Linux uses AT&T Sys V-type directories for startup and shutdown, and links those files to /etc/init.d.  That means that under /etc/rc.d, you've got a bunch of directories corresponding to the various runlevels:

[root@dg ~]# ls -lad /etc/rc.d/rc*.d
drwxr-xr-x 2 root root 4096 Dec  8 15:32 /etc/rc.d/rc0.d
drwxr-xr-x 2 root root 4096 Dec  8 15:32 /etc/rc.d/rc1.d
drwxr-xr-x 2 root root 4096 Jan 28 02:14 /etc/rc.d/rc2.d
drwxr-xr-x 2 root root 4096 Jan 28 02:14 /etc/rc.d/rc3.d
drwxr-xr-x 2 root root 4096 Jan 28 02:14 /etc/rc.d/rc4.d
drwxr-xr-x 2 root root 4096 Jan 28 02:14 /etc/rc.d/rc5.d
drwxr-xr-x 2 root root 4096 Dec  8 15:32 /etc/rc.d/rc6.d

and in each of those directories, you've got a link to init.d for the various start and stop scripts:

[root@dg ~]# ls -la /etc/rc.d/rc5.d/S*|more
lrwxrwxrwx 1 root root   22 Dec  8 15:32 /etc/rc.d/rc5.d/S02lvm2-monitor -> ../i
nit.d/lvm2-monitor
lrwxrwxrwx 1 root root   17 Jun 24  2007 /etc/rc.d/rc5.d/S03sysstat -> ../init.d
/sysstat
lrwxrwxrwx 1 root root   18 Jun 23  2007 /etc/rc.d/rc5.d/S08iptables -> ../init.
d/iptables

That means that at runlevel 5,  lvm2-monitor will start first, followed by sysstat, iptables, etc.  The down scripts are prefixed with a 'K', and work the same way:

[root@dg ~]# ls -la /etc/rc.d/rc5.d/K*|more
lrwxrwxrwx 1 root root 20 Feb  7  2008 /etc/rc.d/rc5.d/K00xendomains -> ../init.
d/xendomains
lrwxrwxrwx 1 root root 17 Jan 31  2009 /etc/rc.d/rc5.d/K01dnsmasq -> ../init.d/d
nsmasq
lrwxrwxrwx 1 root root 24 Sep  6 17:26 /etc/rc.d/rc5.d/K01setroubleshoot -> ../i
nit.d/setroubleshoot

So anyway.  What did those error messages in grep tell me?  It says that I have files in the various rcx.d directories that are linked to a nonexistent file in /etc/init.d.  Not a real problem, because the file will just fail to do anything - but something that really should be cleaned up.

However, while I was checking things out, I spotted something that potentially could be a real problem.

[root@dg init.d]# ls -la /etc/rc2.d/S99ossec
-r-xr-xr-x 1 root root 1087 May  9  2006 /etc/rc2.d/S99ossec

That's not a link - it's really a file!

One of two things can happen in this case, both of them bad.  If you've made a change to the file in /etc/init.d, it won't be reflected in the level 2 startup.  Or, worse - if you've removed the app and deleted the file in /etc/init.d, it could be running something you don't want to run.

My cleanup script looks like this:

#!/bin/bash
# cleanup_rc

 MAIL="/bin/mail"

 cd /etc/rc.d||{ $ECHO "$0 failed chdir"|$MAIL tim;exit 1; }
 DIRS="`find . -name "rc*.d" -type d`"
 for i in $DIRS
 do
   cd /etc/rc.d
   cd $i
   FILES="`find . -type f`"
     for j in $FILES
     do
        FNAME="`basename $j`"
        rm -f $FNAME
        ln -s ../init.d/${FNAME:3} $FNAME
     done
   FILES="`find . -type l -follow`"
   for j in $FILES
   do
      rm -f $j
   done
 done
 
 exit 0

It finds all regular files in /etc/rc.d/rc*.d, deletes the file, and creates a link to init.d.  Then, it finds all files that don't exist in init.d, and deletes them.

Works like a charm:

[root@dg init.d]# cleanup_rc
[root@dg init.d]# ls -la /etc/rc2.d/S99ossec
lrwxrwxrwx 1 root root 15 Jan 28 11:29 /etc/rc2.d/S99ossec -> ../init.d/ossec
[root@dg init.d]# cd /etc
[root@dg etc]# fgrep -r "testing 1 2 3" *
[root@dg etc]#

Tuesday, January 26, 2010

bash numeric comparison

Ah, just ran into the dreaded bash comparison error again.  And I know better.  But in my defense, I'm cleaning up some scripts circa 1996.

OK, there is no good defense.  This is a miserable excuse for a loop.

 loops=1

  until test -z "`ps -e|grep icexec`"
  do
{some stuff you want to do here}
    if [[ $loops > 10 ]]  
        then
    exit 0
    fi

   let loops='loops + 1'
  done

This is just bad in so many ways, it's hard to decide where to start.  Let's go with the math functions first.

if [[ loops > 10 ]] just doesn't work.  It does an ASCII comparison, so the second time through it exits out, since '2' is larger than '1'.  Change it to if [[ loops -gt 10 ]].  Or, better still, use two parentheses, and make it if ((loops > 10)).  Much cleaner.

Incrementing the loop.  This works, but I hate the 'let' command.  It's so damn picky about whitespace.  Change it to parentheses again, ((loops = loops+1)).  Or, again better, ((loops++)).

So your code is now

  until test -z "`ps -e|grep icexec`"
  do
 {some stuff you want to do here}

 if ((loops > 10))
        then
  exit 0
  fi
  ((loops++))
done

Better.  But why bother with the inner 'if...then'?

  until test -z "`ps -e|grep icexec`"||((loops > 10))
  do
 {some stuff you want to do here}
    ((loops++))
done

Wednesday, January 20, 2010

bash error checking

Just had an interesting one bite me.

I like to do a lot of error checking in bash.  There are so many easy ways to destroy a system; something like this:

cd /nonexistentdirectory
rm -f *

can just ruin your whole day.  So I usually do something simple, like:

cd /nonexistentdirectory||exit 1
rm -f *

That works.  But if you've got it in the middle of a script, you'll never know about it.  The obvious thing to do is to mail yourself a message.

cd /nonexistentdirectory||(echo "$0 failed chdir"|mailx tim;exit 1)
This works fine.  That is, it emails me a nice error message - and then proceed to destroy all of my files.  See, it tosses up a subshell - a completely separate instance of bash.  Here's a little experiment.

  TESTVAL="testing"
  echo "testval before=$TESTVAL"

  cd /nonexistentdirectory||(TESTVAL="not a test";echo $TESTVAL)

  echo "testval after=$TESTVAL"

Running it shows:

testval before=testing
/usr/local/scripts/verify_full: line 25: cd: /nonexistentdirectory: No such file or directory
testval=not a test
testval after=testing

 So my variable gets changed to what I want it to - and then as soon as I drop out of that subshell, it changes back.  My 'exit 1' had the no effect at all - it droped me out of the subshell (which I was about to exit anyway) back to the main shell, and then proceeded to destroy all of my files.

Curly braces to the rescue.

cd /nonexistentdirectory||{ TESTVAL="not a test";echo "testval=$TESTVAL"; }

testval before=testing
/usr/local/scripts/verify_full: line 25: cd: /nonexistentdirectory: No such file or directory
testval=not a test
testval after=not a test


Now, the 'exit 1' really will drop you out of the whole script.  Your files are saved!

One gotcha - note the semicolon before the closing brace.  If you forget to put it there, you will search for a long time trying to find out why the script is failing.