2

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

$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>

我想进一步调查表单篡改。特别是从受信任的用户添加 POST 请求customer%5Btags%5D%5B1%5D=1,这是一个id等于 1 的标签,它存在但它是由另一个用户创建的。攻击者用户正在使用另一个用户创建的标签创建客户:

POST 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

..并且似乎有某种控制可以防止这种情况发生。结果是200 OK(应该是302成功的情况下)没有任何错误,并再次呈现表单。当然实体没有持久化。

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

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

4

2 回答 2

2

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

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

当您提交表单时,选择字段会在此列表中查找与提交的视图表示匹配的模型表示。如果找不到,则该字段保持未分配状态。

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

于 2012-07-28T07:30:08.940 回答
0

大胆猜测:CSRF 保护已启用,您不会呈现错误。

于 2012-07-12T13:41:31.927 回答