安全性 HIPAA ePHI 加密
我有一些休息时间,我想选择一个新项目来娱乐。我是一名大学生,每年我们都会举办在线推介比赛。我想为大约 9 个月后的推介比赛创建一个项目。问题是该项目对安全性要求非常高,而且竞争非常激烈。
我需要能够做的事情: 1. 存储 HIPAA 或 ePHI (.pdf|.gif|.jpg|.doc) 2、强大的访问控制 3.支持大量用户和文件(100万+) 4. 完整的审计报告(哦,ePhi,你真是太痛苦了) 5. 加密
建议解决方案
0) 将 Web 应用程序放置在防火墙后面的安全专用服务器上
1) 将文件存储在“secure_files/”文件中,然后使用 mod_rewrite 限制对此目录的访问。
大致如下:
#Removes access to the secure_files folder by users.
RewriteCond %{REQUEST_URI} ^secure_files.*
RewriteRule ^(.*)$ /index.php?/$1 [L]
如果用户有权限,则使用 php 脚本打开文件。那么我可以使用:
------
-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)使用 CI 会话类向会话添加“用户”。
控制器检查会话是否已设置:
<?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) 在多个 Web 服务器之间轮流循环。我从来没有这样做过,所以我不知道该怎么做。我不知道如何处理多个数据库服务器。有什么想法/建议吗?
4) 使用Oracle企业标准数据库审计。我希望我可以使用 MySQL,但我找不到任何审计支持。我可以使用 MySQL 并使用 PITA。有人用过 MySQL 的时间点架构 (PITA) 吗?你能分享你的经验吗?
5)很明显,我可以使用单向加盐哈希对密码进行哈希处理。但我需要加密所有内容吗?另外,我根本不明白 AES_ENCRYPT(str,key_str) 如何提高安全性。我想这可能会阻止管理员查看数据库?我可以/应该加密“secure_files/”文件夹中的所有内容吗?我可以使用像 BitLocker 这样的全盘加密吗?
基本上我可以用php和CI实现网上银行级别的安全吗?除了那些毫无价值的“你这个白痴,因为你什么都不知道,去付钱给专家”的建议之外,你还能提出其他建议吗?
感谢您花时间阅读本文。
采用来自 Redux Auth 的
关于单向哈希的内容。我说的加密是错误的。我通常会做类似的事情:
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); } } ?>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:
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);
}
}
?>
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
编辑:
加密 SQL 数据库中的敏感数据可防御 3 个主要威胁。
内部威胁:
系统管理员和开发人员。
SQL注入:
如果您的数据库配置正确,sql 注入应该只会向攻击者提供对应用程序数据库的访问权限,而不会提供其他任何权限。在 mysql 中,请确保撤销
FILE
特权,因为这可用于读取硬编码密钥或配置文件。更安全的备份:
分层安全。
加密与散列不同。加密意味着有一种解密数据的方法。对密码使用加密函数是 CWE-257 识别的漏洞。密码必须始终使用加盐哈希,而 sha-256 是一个很好的算法。盐应该是一个 加密随机数,就像一个非常随机的值,每个值仅使用 1 个哈希。
MySQL的
AES_ENCRYPT()
很糟糕,它使用ECB模式< /a> 这太可怕了。如果函数调用没有 IV,则可能是 ECB 模式,如果 IV 为空,则违反 CWE-329。纯文本:
使用 ECB 模式加密:
加密很困难,你必须担心初始化向量、操作模式、密钥存储和 string2key 函数。绝大多数程序员认为密码学很简单,但他们却严重把事情搞砸了。获取一本《实用密码学》,它开门见山,数学不重。如果您喜欢数学,那么请选择 “手册”。
编辑:
我不太喜欢你的随机数生成,因为它的熵/大小比很差。当你可以使用 256 基盐时,16 基盐就是一种浪费。请记住,大多数(可能是所有)消息摘要实现都是二进制安全的。此外,
uniqid()
在计算中使用了大量时间,如果它只使用时间,则会违反 CWE-337。另一方面,mt_rand() 非常出色。另请记住,您可能应该将其存储为 Base64,然后在哈希函数中使用之前对其进行 Base64 解码。Edit:
Encrypting sensitive data in a sql database defends against 3 major threats.
Internal Threats:
Sys admin and developers.
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.Even More Secure Backups:
Security in layers.
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:
encrypted with ECB mode:
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.