Security 安全性-查看和编辑id在地址栏中可见
CakePHP版本3.5.5 该id在地址栏中可见,可供查看和编辑,这会给我的应用程序带来安全风险。同一公司的任何登录用户都可以更改地址栏中的id,并查看或编辑详细信息 不允许他们访问的用户数 IE:可在地址栏中手动更改为并输入。这将显示不允许的用户1215的详细信息 为了克服这个问题,我选择了允许用户编辑的id,并使用以下代码检查url中的id是否为这些id之一:Security 安全性-查看和编辑id在地址栏中可见,security,cakephp,cakephp-3.0,Security,Cakephp,Cakephp 3.0,CakePHP版本3.5.5 该id在地址栏中可见,可供查看和编辑,这会给我的应用程序带来安全风险。同一公司的任何登录用户都可以更改地址栏中的id,并查看或编辑详细信息 不允许他们访问的用户数 IE:可在地址栏中手动更改为并输入。这将显示不允许的用户1215的详细信息 为了克服这个问题,我选择了允许用户编辑的id,并使用以下代码检查url中的id是否为这些id之一: public function view($id = null) { if ($this->request->
public function view($id = null)
{
if ($this->request->is('get')) {
// Select the permitted ids.
if (superuser) { // example to explain only
$query = $this->Users->find()
->where(['companyid' => $cid])
->andWhere(['status' => 1])
->toArray();
}
elseif (manager) { // example to explain only
$query = $this->Users->find()
->where(['areaid' => $areaid])
->andWhere(['status' => 1])
->toArray();
}
elseif (team leader) { // example to explain only
$query = $this->Users->find()
->where(['teamid' => $teamid])
->andWhere(['status' => 1])
->toArray();
}
// Check if the edit id is in the array of permitted ids.
$ids = array_column($query, 'id');
$foundKey = array_search($id, $ids);
// If the edit id is not in the array of permitted ids redirect to blank.
if (empty($foundKey)) {
// Handle error.
}
$user = $this->Users->get($id);
$this->set('user', $user);
$this->set('_serialize', ['user']);
}
else {
// Handle error.
}
}
我的问题:上面的代码是实现这一点的最佳方法还是有更好的方法
这段代码确实有效,但因为它与安全性有关,我希望任何能改进它或指出它的弱点的输入
/////////////////////////////////////////////////////////////////////////////根据cgTag的要求,请参见下文 我的应用程序有超级用户、经理、团队领导和用户 经理管理一个可以包含多个团队的区域 团队领导者领导一个团队,并且必须属于一个区域 用户被分配到一个区域或团队 例如: 地区是英国
英格兰队
苏格兰队
威尔士队
地区是美国
球队位于佛罗里达州
球队来自加利福尼亚
团队位于德克萨斯州
在索引上-超级用户可以看到公司中的所有超级用户、经理、团队领导和用户 在索引上,经理可以看到自己和所在区域的用户、所在区域的团队领导以及团队中的用户 在索引上-团队领导可以看到自己和团队中的用户 我的问题是,如果英国地区的经理在其中一条记录上单击“编辑”,则该记录显示的url为 然后,假设这个不满的经理猜了一下,将url更改为并提交,然后显示此记录。(此记录可以是任何人、超级用户、其他经理、不在其所在区域的团队领导或不在其所在区域的用户 然后,经理可以更改电子邮件地址并提交此邮件,我需要防止这种情况 我的解决方案是重申我在view and edit类中对索引所做的超级用户、经理和团队领导的查找。这确保了经理只能查看或编辑其所在区域的人员 希望我已经解释得足够好了,但如果不让我知道,我会再次尝试 谢谢 ///////////////////////////////////////////////////////////////////////////// 多亏了cgTag,我对这种方法更有信心,但我不能使用这段代码,因为您正确地假设我使用的是一个id来选择所有公司的结果,但我使用的是一个40个字符的字符串。我这样做是为了使我的sql查询更加健壮 除非您拥有所需的所有信息,否则您不可能帮助我,因此我在下面发布了一份准确的陈述:
public function view($id = null)
{
if(!$this->request->is('get') || !$id) {
//throw new ForbiddenException();
echo 'in request is NOT get or id NOT set ' . '<hr />';
}
$user_id = $this->Auth->user('id');
// regular users can never view other users.
if($user_id !== $id) {
//throw new ForbiddenException();
echo 'in $user_id !== $id ' . '<hr />';
}
// Declare client id 1.
if ($this->cid1() === false) {
echo 'in throw exception ' . '<hr />';
}
else {
$c1 = null;
$c1 = $this->cid1();
}
$company_ids = $this->getCompanyIds($c1);
$area_ids = $this->getAreaIds($user_id, $c1);
$team_ids = $this->getTeamIds($user_id, $c1);
// company_id does not exist which will cause an unknown column error.
// The column I select by is cid_1 so I have changed this column to cid_1 as shown below.
$user = $this->Users->find()
->where([
'id' => $id,
'cid_1 IN' => $company_ids,
'area_id IN' => $area_ids,
'team_id IN' => $team_ids,
'status' => 1
])
->firstOrFail();
$this->set(compact('user'));
}
使用此代码,我得到以下错误:
错误:SQLSTATE[21000]:基数冲突:1241个操作数应包含1列
我不知道你的例子是否适用于这些新信息,但至少你现在掌握了所有信息
如果可以的话,那就太好了,但如果不能的话,我真的不介意。我非常感谢你抽出时间来帮助我
谢谢你
/////////////////////////////////////////////////////////////////////////////
@tarikul05-感谢您的输入
您的建议与我解决此安全问题的第一次尝试非常相似,但我通过模糊性实现了安全性,并将id隐藏在一个80字符的字符串中,如下例所示
// In a cell
public function display($id = null)
{
// Encrypt the id to pass with view and edit links.
$idArray = str_split($id);
foreach($idArray as $arrkey => $arrVal) {
$id0 = "$idArray[0]";
$id1 = "$idArray[1]";
$id2 = "$idArray[2]";
$id3 = "$idArray[3]";
}
// Generate string for the id to be obscured in.
$enc1 = null;
$enc1 = sha1(uniqid(mt_rand(), true));
$enc2 = null;
$enc2 = sha1(uniqid(mt_rand(), true));
$encIdStr = $enc1 . $enc2;
// Split the string.
$encIdArray = null;
$encIdArray = str_split($encIdStr);
// Generate the coded sequence.
$codedSequence = null;
$codedSequence = array(9 => "$id0", 23 => "$id1", 54 => "$id2", 76 => "$id3");
// Replace the id in the random string.
$idTemp = null;
$idTemp = array_replace($encIdArray, $codedSequence);
// Implode the array.
$encryptedId = null;
$encryptedId = implode("",$idTemp);
// Send the encrypted id to the view.
$this->set('encryptedId', $encryptedId);
}
然后用
// In function in the app controller
public function decryptTheId($encryptedId = null)
{
$idArray = str_split($encryptedId);
foreach($idArray as $arrkey => $arrVal) {
$id0 = "$idArray[9]";
$id1 = "$idArray[23]";
$id2 = "$idArray[54]";
$id3 = "$idArray[76]";
}
$id = null;
$id = $id0.$id1.$id2.$id3;
return $id;
}
问题是,在测试时,我设法使脚本出错,从而暴露了数组位置,这可能会通过模糊性原则破坏安全性,并使黑客更容易操作
你的建议比我的模糊方法更简洁,但我相信md5已经被破解,因此不应该使用
我不是安全专家,但在我看来,根据允许的id数组检查视图和编辑id是解决这个问题的最安全的方法
也许我错了,但如果我这样做的话,无论黑客在地址栏中尝试了什么,他们都无法看到或编辑他们不想看到的数据,这会使url更干净
我最初寻找/希望的是一个解决这个问题的蛋糕方法/函数,但我在食谱中找不到任何东西
无论如何谢谢。Z.我会简化您的代码,以便获取用户记录的SQL仅在当前用户具有权限的情况下才能找到该记录。当您依赖于这些条件的关联数据时。即使必须使用联接,也要遵循此方法 创建SQL条件,然后对查询调用
firstOrFail()
。如果记录不匹配,将抛出NotFoundException
public function view($id = null) {
if(!$this->request->is('get') || !$id) {
throw new ForbiddenException();
}
$user_id = $this->Auth->user('id');
// regular users can never view other users.
if($user_id !== $id) {
throw new ForbiddenException();
}
$company_ids = $this->getCompanyIds($user_id);
$area_ids = $this->getAreaIds($user_id);
$team_ids = $this->getTeamIds($user_id);
$user = $this->Users->find()
->where([
'id' => $id
'company_id IN' => $company_ids,
'area_id IN' => $area_ids,
'team_id IN' => $team_ids,
'status' => 1
])
->firstOrFail();
$this->set(compact('user'));
}
当一个用户属于数据的层次结构时,上面的逻辑应该是合理的。在这里,他们可以查看许多用户,但只有当这些用户属于他们也可以访问的上层关联之一时
它之所以有效,是因为where条件的子句中有
注意:如果数组为空,IN操作符将抛出一个错误。当您有可以看到所有“团队”的用户时,只需排除where条件,而不是使用空数组
这里的关键是让函数返回一个允许的父关联数组,例如;getCompanyIds($user\u id)
只返回当前用户允许访问的公司id
我认为如果您以这种方式实现它,那么逻辑就很容易理解,安全性是可靠的,并且是一个简单的firstOrFail()
public function view($id = null) {
if(!$this->request->is('get') || !$id) {
throw new ForbiddenException();
}
$user_id = $this->Auth->user('id');
// regular users can never view other users.
if($user_id !== $id) {
throw new ForbiddenException();
}
$company_ids = $this->getCompanyIds($user_id);
$area_ids = $this->getAreaIds($user_id);
$team_ids = $this->getTeamIds($user_id);
$user = $this->Users->find()
->where([
'id' => $id
'company_id IN' => $company_ids,
'area_id IN' => $area_ids,
'team_id IN' => $team_ids,
'status' => 1
])
->firstOrFail();
$this->set(compact('user'));
}