在Symfony 2多租户应用程序中测试表单篡改

时间:2012-07-12 08:08:32

标签: forms symfony security symfony-forms

在我的项目中,User可以创建Customer并将其分配为零或更多Tag。当然,这些实体与User有关系。这是由tag字段entity type的表单完成的,由当前登录用户过滤:

$user = $this->securityContext->getToken()->getUser();

$builder
    ->add('tags', 'meta_selector', array(
        'label'         => 'Tag',
        'class'         => 'Acme\HelloBundle\Entity\Tag',
        'property'      => 'select_label',
        'query_builder' => function(EntityRepository $er) use($user) {
            $qb = $er->createQueryBuilder('t');

            return $qb
                ->where($qb->expr()->eq('t.user_id', ':user')
                ->orderBy('t.name')
                ->setParameter('user', $user);
        }
    ))
;

这很好用。查看生成的HTML标记将呈现为复选框:

<div class="controls">
    <label class="checkbox">
        <input type="checkbox" value="2" name="customer[tags][2]"
            id="customer_tags_2"> A Tag
    </label>
    <label class="checkbox">
        <input type="checkbox" value="3" name="customer[tags][3]" 
            id="customer_tags_3"> Another Tag
    </label>
</div>

我想进一步调查表格篡改。特别是从可信用户添加customer%5Btags%5D%5B1%5D=1发出POST请求,该idPOST http://localhost/Symfony2/web/app_dev.php/app/customers/new HTTP/1.1 Host: localhost User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:13.0) Gecko/20100101 Firefox/13.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive Referer: http://localhost/Symfony2/web/app_dev.php/app/customers/new Cookie: PHPSESSID=3avu1a2a1eufthr5tdftuhrnn7; hl=it Content-Type: application/x-www-form-urlencoded Content-Length: 276 customer%5Bfirst%5D=fake&customer%5Blast%5D=fake&customer%5Bgender%5D=m&customer%5Bbirthday%5D=&customer%5Bemail%5D=&customer%5Bmobile%5D=&customer%5Baddress%5D=&customer%5Bcountry%5D=IT&customer%5Btags%5D%5B1%5D=1&customer%5B_token%5D=455783fa2f866677669c9034a90554b9f75d68b4 等于1的标记,但是它已由另一个用户创建。攻击者用户正在使用其他用户创建的标记创建客户:

200 OK

..似乎有某种控制可以防止这种情况发生。结果为302(如果成功,则应为{{1}}),不会出现任何错误,并且会再次呈现表单。当然实体不会持久存在。

实际问题是:Symfony 2如何防止这种形式的“篡改”攻击?可能的解释是它检查提交的标签是否存在于表单构建器返回的集合中。但需要参考......

编辑:即使禁用CSRF保护,结果也是一样的。顺便说一句,我传递了一个有效的令牌,CSRF旨在防止其他类型的攻击。<​​/ p>

2 个答案:

答案 0 :(得分:2)

您的问题的答案可以很容易地解释。每个选择字段(以及实体类型是选择类型的特化)都有一个选项列表。对于每个选择,该字段都了解

  • 选择的模型表示(“选择”)(例如Tag实例)
  • 选择的视图表示(“值”)(例如ID)
  • 视图中使用的标签(例如Tag的属性)

当您提交表单时,选择字段在此列表中查找哪个模型表示与提交的视图表示匹配。如果找不到任何内容,则该字段仍未分配。

此逻辑的代码可以在类ChoiceList及其后代中找到,在您的情况下EntityChoiceList。提交后,将执行方法getChoicesForValues(),该方法执行查找并针对速度进行优化。

答案 1 :(得分:0)

狂野猜测:启用了CSRF保护,您不会渲染错误。