Broad Network


Perl Hash Insecurities and Prevention

Perl Insecurities and Prevention Part 4

Perl Course

Foreword: In this part of the series, I explain the insecurities with the hash and how to prevent them.

By: Chrysanthus Date Published: 23 Nov 2015

Introduction

This is part 4 of my series, Perl Insecurities and Prevention. In this part of the series, I explain the insecurities with the hash and how to prevent them. You should have read the previous parts of the series before coming here, as this is a continuation.

An example of a hash is:

    my %fruitColor = (Apple => "purple", Banana => "yellow", Pear => "green", Lemon => "green", Pineapple =>);

The Hash::Util Module
This module can be used to prevent a hash key, a hash value or the entire hash from being changed, in the program. It can also be used to allow only particular key names to be added to the hash. This module comes with the Perl installation. To bring in the module to your program, type:

use Hash::Util qw(
hash_seed all_keys
lock_keys unlock_keys
lock_value unlock_value
lock_hash unlock_hash
lock_keys_plus hash_locked
hidden_keys legal_keys
);

From here, you can use the functions of the module.

The lock_hash Function
The syntax is:

     lock_hash(%hash);

where hash is the name of the hash. When this is done, the entire hash is locked, making all keys and values read-only. No value can be changed, no keys can be added or deleted. Down in the code, you can unlock the hash with the following syntax:

    unlock_hash(%hash)

The lock_keys Function
You can restrict the keys to the current keyset for a particular hash as follows:

    lock_keys(%hash);

If you want all keys to come from a keyset, use the syntax,:

  lock_keys(%hash, @keyset);

If there are already some keys in the hash, and you want new keys to come from a keyset, use,

    lock_keys_plus(%hash, @additional_keys);

In this case, the old keys may not belong to the keyset, but any additional key must come from the @additional_keys keyset.

With these locking of keys, the delete() function can still delete an element (key/value pair). To remove the restriction for the methods, use,

     unlock_keys(%hash);

The lock_value Function
The above functions lock but the keys. To lock an individual value use:

    lock_value  (%hash, $key);

With this, the value cannot be changed. However, the element (key/value pair) can be deleted. To unlock the value, use:

    unlock_value(%hash, $key);

The lock_hash_recurse Function
It is possible to have a hash of hashes. It is possible to have a hash of hashes of hashes. The lock_hash() function can lock only one hash. It cannot lock a hash of hashes; it cannot lock a hash of hashes of hashes. If you want to lock a hash of hashes or a hash of hash of hashes, you need but the lock_hash_recurse() function, which will lock all the hashes in the hash tree. The syntax is:

    lock_hash_recurse(%hash)

where %hash is the top level hash. With this, all keys and values of all hashes become read-only. No value can be changed, no keys can be added or deleted. To unlock the hashes, use:

    unlock_hash_recurse(%hash)

Note: if you apply the lock_hash_recurse() function to a hash of arrays of hashes, only the top level hash will be locked.

Passing a Non-Existing Hash Key to a Perl Function
Read and try the following code:

use strict;

    my %ha;

    sub fn
        {
            $_[0] = 'aa';
        }
  
    fn($ha{one});

    print $ha{one};

There should have been no output printed, but the output is,

    aa

This is wrong. The hash had an empty list. However, as the assumed key was passed to the function, and the assumed key as $_[0] being assigned a value, the hash developed the key/value pair. It does not have to be like that. That is a weakness. See solution below.

Passing a Non-Existing Hash Slice
If you pass a non-existing hash slice, even if there is no assignment in the function body, the hash develops the keys. Try the following code:

use strict;

    my %ha;

    sub fn
        {
            
        }
  
    fn(@ha{'one', 'two'});

    print "Hash now has a key as one\n" if exists($ha{'one'});
    print "Hash now has a key as two\n" if exists($ha{'two'});

The output is:

    Hash now has a key as one
    Hash now has a key as two

This output is wrong. It means the hash has developed keys when it was not supposed to; just because a slice with the assume keys has been passed to the function. See solution below.

The problem of non-existing hash key and non-existing hash slice can be solved by locking the keys.

Try the following code and note that the assumed hash key could not be added to the hash, resulting from the function call (and assignment).

use strict;

  use Hash::Util qw(
                     hash_seed all_keys
                     lock_keys unlock_keys
                     lock_value unlock_value
                     lock_hash unlock_hash
                     lock_keys_plus hash_locked
                     hidden_keys legal_keys
                   );

    my %ha;

    lock_keys(%ha);

    sub fn
        {
            $_[0] = 'aa';
        }
  
    fn($ha{one});

    print $ha{one};

I tried the code and I had the following output (error message):

    Attempt to access disallowed key 'one' in a restricted hash at C:\temp.pl line 19.

This means that the key was not created as could have.

Try the following code for a slice and function, and note that there is no creation of keys:

use strict;

  use Hash::Util qw(
                     hash_seed all_keys
                     lock_keys unlock_keys
                     lock_value unlock_value
                     lock_hash unlock_hash
                     lock_keys_plus hash_locked
                     hidden_keys legal_keys
                   );

    my %ha;

    lock_keys(%ha);

    sub fn
        {
            
        }
  
    fn(@ha{'one', 'two'});

    print "Hash now has a key as one\n" if exists($ha{'one'});
    print "Hash now has a key as two\n" if exists($ha{'two'});

I tried the code and I had the following output (error message):

    Attempt to access disallowed key 'one' in a restricted hash at C:\temp.pl line 22.

This means that non of the assumed keys from the hash slice was created.

Reference Functions for the Module
The above functions are used with the hash names. You may have a reference to a hash instead of the hash name. In this case you use the following functions, which have the same meanings, but instead of the hash name you type the reference to the hash:

lock_hashref
unlock_hashref
lock_ref_keys
unlock_ref_keys
lock_ref_keys_plus
lock_ref_value
unlock_ref_value
lock_hashref_recurse
unlock_hashref_recurse

The module has a few more functions, but you will consult some other document for that.

When a hash is locked, the ways I think a hacker can unluck the hash is if he uses the unluck function through the eval() function, or through a module that Perl does not know (does not come with Perl installation).

That is it for this part of the series. We stop here and continue in the next part.

Chrys

Related Links

Perl Basics
Perl Data Types
Perl Syntax
Perl References Optimized
Handling Files and Directories in Perl
Perl Function
Perl Package
Perl Object Oriented Programming
Perl Regular Expressions
Perl Operators
Perl Core Number Basics and Testing
Commonly Used Perl Predefined Functions
Line Oriented Operator and Here-doc
Handling Strings in Perl
Using Perl Arrays
Using Perl Hashes
Perl Multi-Dimensional Array
Date and Time in Perl
Perl Scoping
Namespace in Perl
Perl Eval Function
Writing a Perl Command Line Tool
Perl Insecurities and Prevention
Sending Email with Perl
Advanced Course
Miscellaneous Features in Perl
Perl Two-Dimensional Structures
Advanced Perl Regular Expressions
Designing and Using a Perl Module
More Related Links
Perl Mailsend
PurePerl MySQL API
Perl Course - Professional and Advanced
Major in Website Design
Web Development Course
Producing a Pure Perl Library
MySQL Course

BACK NEXT

Comments

Become the Writer's Fan
Send the Writer a Message