tags:

views:

77

answers:

1

I have some down time and I am think of picking a new project for fun. I am a college student and every year we have a online pitch competition. I want to create a project for this pitch competition that is approx 9 months from now. The problem is the project requires very high security and the competition is a very competitive.

Things I need to be able to do: 1. Store HIPAA or ePHI (.pdf|.gif|.jpg|.doc) 2. Strong access control 3. Support large number of users and files (1 million +) 4. Full Audit Reports (oh ePhi you are such a pain) 5. Encryption

Proposed Solutions
0) Place the web app on a secure dedicated sever behind a firewall

1) Store files in a file say “secure_files/” and then use mod_rewrite to restrict access to this directory.

Something on the lines of:

#Removes access to the secure_files folder by users.
RewriteCond %{REQUEST_URI} ^secure_files.*
RewriteRule ^(.*)$ /index.php?/$1 [L]

Then use a php script to open the files if the user has privileges to do so. So Could I just use:

------
-SQL
------

------
- create files table
-----
CREATE TABLE `files` (
id INT NOT NULL AUTO_INCREMENT,
file_name VARCHAR(50) NOT NULL,
PRIMARY KEY('id')
);

------
- create files table
-----
CREATE TABLE `privileges` (
uesr_id INT NOT NULL,
file_id INT NOT NULL,
);

------
- create users table
-----
CREATE TABLE `users` (
id INT NOT NULL AUTO_INCREMENT,
name VARCHAR(20) NOT NULL,
email VARCHAR(50) NOT NULL,
password CHAR(40) NOT NULL,
PRIMARY KEY('id')
);

<?php
public function get_user_files($filename)
{
   //this is set during login
   $user_id = $this->session->userdata('user_id');

   //check to see if the user has privileges to access the file and gets the file name
   $query = $this->db->join('privileges','privileges.id = files.id')
                     ->select('files.file_name')
                     ->where('privileges.user_id',$user_id)
                     ->where('files.file_name',$file_name)
                     ->limit(1)
                     ->get('files');

    $file = $query->row()->files.file_name;

   if($file)
   {
    //user has privileges to access the file so include it
    $handle = fopen($file, "rb");
    $data['file'] = fread($handle, filesize($file));
    fclose($handle);
   }
  $this->load->view('files',$data);
}
?>

2) Use CI sessions class to add a “user” to the session.

The controller checks to see if the session is set:

<?php
public function __construct()        
    {
        parent::__construct();

        if($this->secure(array('userType' => 'user')) == FALSE)
        {
            $this->session->set_flashdata('flashError', 'You must be logged into a valid user account to access this section.');
            $this->session->sess_destroy();
            redirect('login');
        }
    }    

function secure($options = array())
    {            
        $userType = $this->session->userdata('userType');

        if(is_array($options['userType']))
        {
            foreach($options['userType'] as $optionUserType)
            {
                if($optionUserType == $userType) return true;
            }
        }
        else
        {
            if($userType == $options['userType']) return true;
        }
        return false;
    }
?>

3) Rotate round robin between multiple web severs. I have never done this so I have no idea how to do this. I have no idea how to deal with the multiple database servers. Any ideas/suggestions?

4) Use Oracle Enterprise Standard Database Auditing. I wish I could use MySQL, but I cannot find any auditing support. I could use MySQL and use PITA. Has anyone used point-in-time architecture (PITA) with MySQL? can you share your experience?

5) So obviously I can hash the passwords with a one way salted hash. But do I need to encrypt everything? Also I don’t see how AES_ENCRYPT(str,key_str) improves secuirty at all. I guess it could prevent an admin from looking at a database? Can/should I encrypt everything in the “secure_files/” folder? Could I just use full disk encryption like BitLocker?

Basically can I achieve online bank level security with php and CI? Can you make any other suggestions besides the worthless “your an idiot go pay an expert because you know nothing” suggestions?

Thank you for taking the time to read through this.


adopted from Redux Auth

With regards to one-way hash. My mistake for saying encryption. I usually do the do something similar to:

/* * Class Auth * * */

class Auth { private $salt_length;

    public function __construct()  
{
     $this->salt_length = '9';
    }

    public function hash($password = false)
{
    $salt_length = $this->salt_length;

    if ($password === false)
    {
        return false;
    }

    $salt = $this->salt();

    $password = $salt . substr(hash('sha256',$salt . $password), 0, -$salt_length);
    return $password;       
}

private function salt()
{
    return substr(md5(uniqid(rand(), true)), 0, $this->salt_length);
}

} ?>

A: 

Edit: Encrypting sensitive data in a sql database defends against 3 major threats.

  1. Internal Threats:

    Sys admin and developers.

  2. SQL Injection:

    If your database is configured properly sql injection should only provide the attacker with access to the application's database, and nothing else. In mysql make sure you revoke FILE privileged as this could be used to read a hard-coded key or configuration file.

  3. Even More Secure Backups:

    Security in layers.

So obviously I can encrypt the passwords with a one way salted hash.

Encryption is not the same as hashing. Encryption implies that there is a means of decrypting the data. Using an encryption function for passwords is a vulnerablity recognized by CWE-257. Passwords must always use a salted hash, and sha-256 is a great algorithm. The salt should be a Cryptographic nonce, as in a very random value that is only used 1 per hash.

MySQL's AES_ENCRYPT() sucks, its using ECB mode which is terrible. If the function call doesn't have an IV its probably ECB mode, if the IV is null then its a violation of CWE-329.

Plain text:

alt text

encrypted with ECB mode:

alt text

Encryption is difficult, you have to worry about Initialization vectors, modes of operations, key storage, and string2key functions. The vast majority of programmers think cryptography is easy, but they manage seriously mess things up. Get a copy of Practical Cryptography, its straight to the point and not math heavy. If you enjoy math then go with "The Handbook".

EDIT: I don't like your nonce generation very much because it has a bad entropy/size ratio. A base16 salt is a waste when you could have base 256 salt. Keep in mind that most (probably all) message digest implementations are binary safe. Also uniqid() uses a lot of time in its calculation, and if it only used time it would be a violation of CWE-337. Now on the other hand mt_rand() kicks ass. Also keep in mind you should probably store this as a base64 and then base64 decode it before use in your hash function.

    public function nonce($size=32){//256 bit == 32byte. 
        for($x=0;$x<$size;$x++){
            $ret.=chr(mt_rand(0,255));
        }
        return base64_encode($ret);
    }
Rook
I agree with you agreeing with me lol. I will have to read the book you suggested. Have you read it your self? I am an engineering student so math heavy does little to scare me. Does it answer any of the questions about key storage, initialization vectors etc. Most books say; "hey this stuff is hard. You need to think about these things." Yet do not present any useful solutions. Thank you for your follow up
John
Rook
I agree completely with your nonce. It is a much better improvement. Again thank you for not dismissing me as a hopeless noob. I have a lot to learn, but then again I have library, no TV and great advice from great people. Thank you. I will look through "The Handbook" (gotta love mysterious book titles) and CWE.
John
@user379592 Haha, yeah TV rots the brain. We all have something to learn and SO is a great place (http://stackoverflow.com/questions/3008139/why-is-using-a-non-random-iv-with-cbc-mode-a-vulnerability).
Rook