22 Sept 2011

Net::LDAP::Security



Net::LDAP::Security

LDAP servers are vulnerable to LDAP query injection and DNS hijacking may lead to your query landing on the attacker's server. Attacker can sniff your username/password through your LDAP connection. Hacker may sniff your confidential information through LDAP connection.

So, How to prevent this? You can use Net::LDAPS and LDAP over TLS.

To know more about various security threats on LDAP and how to overcome those, read the document at Net::LDAP::Security

20 Sept 2011

Security Issues in Perl Scripts

Security Issues in Perl Scripts

system() and exec()

system() and exec() are potentially vulnerable to parameter tampering threat. Suppose if you have a CGI application which reads the the username parameter and displays the file he created. If you directly pass the parameter input to the system call it is a biggest security threat.

$user = param("user");
@out = system("cat /usr/upload/$user");

Imagine if some attacker is changing the param from "foe" to "test; cat /etc/passwd", your script will output the content of the user file along with the contents of /etc/passwd

As far as security is concerned, everything stated above with regard to the system() function applies to exec() too.

setuid scripts

Normally a Perl program runs with the privileges of the user who executed it. By making a script setuid, its effective user ID can be set to one that has access to resources to which the actual user does not (viz., to the owner ID of the file containing the program). The passwd program for example uses setuid to acquire writing permission to the system password file, thus allowing users to change their own passwords. Since programs that are executed via a CGI interface run with the privileges of the user who runs the web server (usually this is user 'nobody', who has very limited privileges), CGI programmers are often tempted to use the setuid technique to let their scripts perform tricks that they otherwise couldn't. This can be useful, but it can also be very dangerous. For one thing, if an attacker finds a way to exploit a weakness in the script, they won't only gain access to the system, but they will also have it with the privileges of the effective UID of that script (often the 'root' UID).

To avoid this, Perl programs should set the effective UID and GID to the real UID and GID of the process before any file manipulations:


     $> = $< # set effective user ID to real UID.
     $) = $( # set effective group ID to real GID.

and CGI scripts should always run with the lowest possible privilege.

Beware that just being careful in what you do inside your setuid script doesn't always solve the problem. Some operating systems have bugs in the kernel that make setuid scripts inherently insecure. For this, and other reasons, Perl automatically switches to a special security mode (taint mode) when it runs setuid or setgid scripts. We will discuss taint mode in our next article.

rand()
Generating random numbers on deterministic machines is a nontrivial problem. In security critical applications, random numbers are used intensely for many important tasks ranging from password generation to cryptography. For such purposes, it is vital that the generated numbers are as close to truly random as possible, making it difficult (but never impossible) for an attacker to predict future numbers generated by the algorithm. The Perl rand() function simply calls the corresponding rand(3) function from the standard C library. This routine is not very secure. The C rand() function generates a sequence of pseudorandom numbers based on some initial value called the seed. Given the same seed, two different instances of a program utilizing rand() will produce the same random values. In many implementations of C, and in all version of Perl before 5.004, if a seed is not explicitly specified, it is computed from the current value of the system timer, which is anything but random. Having some information about values produced by rand() at a given point and a sufficient amount of time, any self-respecting cracker can accurately predict the sequence of numbers that rand() will generate next, thus obtaining key knowledge necessary to compromise a system.

One (partial) solution to the rand() problem is to use one of the built-in random number generators on Linux systems -- /dev/random and /dev/urandom. Those are better sources of randomness then the standard library rand() function, but like anything else, they have their own imperfections. The difference between the two devices is that /dev/random stops supplying random numbers when its entropy pool runs out of randomness while /dev/urandom uses cryptography to generate new numbers when the entropy pool runs out. Another solution is to use a secure implementation of one of the more complicated cryptographic random number generators such as Yarrow.

13 Sept 2011

Perl 5.10 - Switch

 Perl 5.10 - Switch

Perl 5.10 introduces a native switch statement into the language. Like other features in Perl 5.10, we can enable it with the use feature pragma.
    use feature qw(switch);
It's also possible to enable all Perl 5.10 features with any of the following:
    use feature qw(:5.10);
    use 5.10.0;       # Requires perl v5.10.0 or later.
    use 5.010;        # Same, with nicer errors on older versions.
Perl's new switch feature is best demonstrated with an example. Let's take the classic guessing game, where the computer picks a number and our user needs to try and guess it.
    use strict;
    use warnings;
    use feature qw(switch say);
    # Pick our random number between 1 and 100
    my $secret = int(rand 100)+1;
    # An array of numbers guessed thus far
    my @guessed;
    say "Guess my number between 1-100";
    # Get each guess from the user
    while (my $guess = <STDIN>) {
        chomp $guess;
        # Check their guess using given/when
        given($guess) {
            when (/\D/)         { say "Give me an integer"; }
            when (@guessed)     { say "You've tried that";  }
            when ($secret)      { say "Just right!";  last; }
            when ($_ < $secret) { say "Too low";  continue; }
            when ($_ > $secret) { say "Too high"; continue; }
            # record the guess they've made
            push(@guessed,$_);
        }
    }
The heart of our program is the given/when block, which is enabled by the use of use feature qw(switch) at the top of our code. Let's look at each part in detail:
given($guess)
A given construct marks the start of our switch logic. It has the effect as assigning $_ to $guess for the duration of our given block. The changes to $_ are not visible outside of the given block (ie, they are lexical in scope).
when (/\D/)
when provided with a regular expression checks to see if $_ matches that regular expression. In our case, if our input contains non-digit characters, then we have something that doesn't look like an integer, and execute the associated block.
After a successful when match Perl will automatically break out of the given block unless told otherwise. In our case this repeats the loop asking the user for another guess.
when (@guessed)
In this second test we're asking whether $guess appears as a value in the @guessed. If it does we inform the user and go onto their next guess.
when ($secret)
This is a direct comparison. Is $guess the same value as $secret?. If so the player has guessed correctly! Using last allows us to break out of our while loop, ending the game.
when ($_ < $secret) and when ($_ > $secret)
These final two tests are simple comparisons. Remember that $_ contains the item we were given.
We've used continue for these statements to say that Perl should not break out of our given block on a successful match. This means that if the user guesses too low or too high, we will eventually evaluate the line:
    push(@guesses,$guess);
which remembers the guess as one we've already seen.
You can also use when with hashes (is $_ a key in the hash), subroutines (does the subroutine return true with $_ as an argument) and strings (tests for string equality). Furthermore, our given expression need not be merely a number or a string, we can also compare arrays, and hashes if we want to.
Finally, we can also set a default case, for when nothing has matched, although we have not shown it in our example.

foreach / when

If you've enabled use feature qw(switch then you can also use a foreach/when construct. Here's an example of tallying up the number of times we see cool things in a list:
    use feature qw(switch);
    foreach (@cool_things) {
        when (/pirate/)  { $pirate++ }
        when (/ninja/)   { $ninja++  }
        when (/robot/)   { $robot++  }
        say "$_ doesn't look cool...";
    }
If a when is activated, it automatically goes onto the next iteration of the foreach loop. Just like given/while, we can use the continue keyword to continue examining later options after a successful match.
It should be noted that foreach/when only works when using Perl's default $_ variable for iteration.

Lexical $_

In Perl 5.10 we can write:
    my $_;
This is allows us to do anything we like with $_, but without the possibility of changing $_ for code outside our current block. It's strongly recommended for subroutines using $_ in Perl 5.10 to avoid accidentally changing $_ for your caller.

16 Aug 2011

Compare two ldap branches

ldapcmp


ldapcmp is the tool which can be used to compare directory branches from two servers. This will compare all the entries in the branch including all the attributes in the branch

usage


ldapcmp -h hostA -h hostB -s sub -b "branch_path"

usage: ldapcmp -b basedn [options] [attributes...]
where:
basedn base dn for search
(if the environment variable LDAP_BASEDN is set,
then the -b flag is not required)
options:
-s scope one of base, one, or sub (default is sub)
-l timelim time limit (in seconds) for search (default is no limit)
-z sizelim size limit (in entries) for search (default is no limit)
-n show what would be done but don't actually do it
-v run in verbose mode (diagnostics to standard output)
-h host LDAP server1 name or IP address (default: localhost)
-p port LDAP server1 TCP port number (default: 389)
-h host LDAP server2 name or IP address (default: localhost)
-p port LDAP server2 TCP port number (default: 389)
-V n LDAP protocol version number (2 or 3; default: 3)
-ZZ start TLS request
-ZZZ enforce start TLS request (successful server response required)
-Z make an SSL-encrypted connection
-P pathname path to SSL certificate database (default: current directory)
-N name of certificate to use for SSL client authentication
-K pathname path to key database to use for SSL client authentication
(default: path to certificate database provided with -P option)
-m pathname path to security module database
-W SSL key password
-W - prompt for SSL key password
-I file SSL key password 'file' containing token:password pair/s
-Q [token][:certificate name] PKCS 11
-3 check hostnames in SSL certificates
-D binddn bind dn
-w passwd bind passwd (for simple authentication)
-w - prompt for bind passwd (for simple authentication)
-j file read bind passwd from 'file' (for simple authentication)
-E ask server to expose (report) bind identity
-g do not send a password policy request control
-R do not automatically follow referrals
-O limit maximum number of referral hops to traverse (default: 5)
-M manage references (treat them as regular entries)
-0 ignore LDAP library version mismatches
-i charset character set for command line input (default taken from locale)
use '-i 0' to override locale settings and bypass any conversions
-k do not convert password to utf8 (use default from locale)
-Y proxyid proxied authorization id,
e.g, dn:uid=bjensen,dc=example,dc=com
-H display usage information
-J controloid[:criticality[:value|::b64value|:

Example

ldapcmp -h exmaple.host.com -h example1.host.com -s sub -b "o=176,ou=grpStructure,o=com"

o=176,ou=grpStructure,c=com
different: type
1: SA 55
2: PA 55


27 Jun 2011

Comment your code with Smart::Comments

Normally we comment our code so that humans (including ourselves) can
understand it later on. However with ``Smart::Comments'' it becomes
possible to have comments which are not only useful in comprehending our
code, but also in *debugging* our code.

With ``Smart::Comments'' enabled, when a special comment sequence is
seen (``###'' by default) debugging output is produced:

use Smart::Comments;

### [] Running backups...

my $backup_dir = get_backup_host();

### Backing up files to: $backup_dir

foreach my $file (@manifest) { ### Copying files... % done
backup($file, $backup_dir);
}

### [] Backup complete...

With ``Smart::Comments'' enabled, output similar to the following would
be seen:

### [Fri Feb 25 12:14:34 2011] Running backups...

### Backing up files to: '/mnt/backup'

Copying files........ 64% done

### [Fri Feb 25 12:17:57 2011] Done...

One of great advantages of ``Smart::Comments'' is that the ``use
Smart::Comments'' line can simply be removed (or commented away) when
done, and all our smart comments are then simply ignored by Perl.
There's no requirement that ``Smart::Comments'' be installed on the
production systems, and no risk that that it may interfere with your
code.

You can read more about ``Smart::Comments'' on the
CPAN .

26 Jun 2011

local::lib

Work with local modules via local::lib

``local::lib'' helps solve the problem when a Perl package on your
machine isn't the version you need it to be. It allows you to create
your own directory of Perl packages into your own, or your team's
directory.

use local::lib;

# or

use local::lib '/path/to/team/directory';

``local::lib'' also sets up some useful shell commands which add our
preferred include directories to ``PERL5LIB'' in our environment. If our
code is not running under taint, we don't even need to add the ``use''
line to our code to use these newly installed modules.

App::perlbrew

Experimenting with new versions of Perl and modules

Many developers have a chicken-and-egg problem when it comes to
upgrading their version of Perl. On one hand, the system version of Perl
cannot be upgraded because it might break existing scripts, on the the
other hand it has been difficult to install your own version of Perl to
see whether an upgrade is safe. The same happens with modules.


Pick your Perl version with App::perlbrew

Use ``App::perlbrew'' to install and switch between multiple versions of
Perl. ``perlbrew'' is easy to install, even if you don't have system
administration privileges, and very easy to use. Once you've installed
and initialised it, you can install whichever version of Perl you wish
to use.

perlbrew install perl-5.12.2
perlbrew install perl-5.10.1

``perlbrew'' will then fetch, compile and install that version of Perl
in your home directory (or other nominated location) and you then you
can just start using that version (``perlbrew'' will do all the path
magic required to make this your default version of Perl).

If you have more than one version of Perl installed by ``perlbrew'' you
can list the verions out:

perlbrew list

and switch between them:

perlbrew switch perl-5.12.2

You can also ask ``perlbrew'' to switch itself off so that you can go
back to using the system Perl.

perlbrew off