在我的项目中,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 旨在防止其他类型的攻击。