目前我正在使用一个表单发布"注释"并将其保存在数据库中。有两个隐藏字段,一个用于检查对哪个组件进行了注释,另一个隐藏字段是注释编号。但我在自己的表单中发现了一个漏洞。如果我进入开发者控制台,我可以将它们更改为将评论交叉发布到其他表单,或者不存在的表单,这并不重要,我也可以更改评论的编号,因为如果有相同编号的评论,它仍然可以正常工作。
<form action="/index.php?option=com_comments&view=comment&row=<?= $row ?>&table=<?= $table ?>" method="post">
<input type="hidden" name="row" value="<?= $row ?>" />
<input type="hidden" name="table" value="<?= $table ?>" />
<textarea type="text" name="text" class="control control--textarea control-group__control" placeholder="<?= translate('Add new comment here ...') ?>" id="new-comment-text"></textarea>
<br />
<input class="leader btn btn--theme control-row__trigger" type="submit" value="<?= translate('Comment') ?>"/>
但问题是,当我去控制台添加并提交表单时,我实际上可以覆盖该值,并将其发布为其他人。这显然不是有意作为他人发布的行为。在发送帖子之前,我似乎找不到验证created_by值的方法,因为如果我也把它放在一个隐藏的输入字段中,它也可以更改。我该怎么做才能确保安全?
编辑:发布是自动完成的,由于我们使用的框架,我无法更改任何内容。它覆盖了正确的默认行为。表达我的问题的更好方法是,我能阻止用户添加额外的隐藏输入字段来发布额外的值吗?如果帖子包含created_by,并且它确实将其更改为当前profile_id,我是否应该每次都发布表单帖子检查?
通过开发者控制台更改恶意代码
<form action="/index.php?option=com_comments&view=comment&row=2&table=blogs_blogs&created_by=6" method="post" class="ng-pristine ng-valid">
<input type="hidden" name="_token" value="a0b15d3664d7bc0e0e40675095fec014">
<input type="hidden" name="_token" value="a0b15d3664d7bc0e0e40675095fec014">
<input type="hidden" name="row" value="2">
<input type="hidden" name="created_by" value="6">
<input type="hidden" name="table" value="blogs_blogs">
<textarea type="text" name="text" class="control control--textarea control-group__control" placeholder="Add new comment here ..." id="new-comment-text"></textarea>
<br>
<input class="leader btn btn--theme control-row__trigger" type="submit" value="Comment">
</form>
web应用程序安全的第一条规则:永远不要信任客户端
如果用户已登录,请将用户的id存储在会话中,并仅使用该标识符将他/她的记录存储在数据库中。
另外,你应该在你的表单中实现一个防止CSRF(跨站点请求伪造)的机制。因为我看不出它能做到。
您可以将会话或cookie与数据库一起使用
[php]
$userHash = $db->prepare('SELECT user_hash FROM user WHERE id = :uId')->scalar([':uId' => $this->getUserId()]);
if (!empty($_SESSION['userHash']) && $_SESSION['userHash'] == $userHash) {
// process form
// generate new user hash
} else {
die('!HACKER!');
}
您可以使用会话ID来代替用户ID。
我通过将此检查添加到实际发布到服务器之前应用的行为中来修复它
public function createdbycheck(Library'CommandContext $context)
{
$context->request->data->created_by = null;
}
只需将其设置为NULL,然后由默认行为进行处理。