如何在不遭遇XSS攻击的情况下在Blade模板中输出HTML



如果变量包含以下内容:

$straddr = "1 elm street<br>Unit 4<br><i>City Unknown</i>Alabama";

我想把这个变量包括在Blade模板中,我可以做这样的事情:

<td>{{ $straddr }}</td>

但是这将显示HTML标签。

然而,文件显示

默认情况下,Blade{{ }}语句通过PHP的htmlspecialchars函数自动发送,以防止XSS攻击。如果您不希望数据被转义,可以使用以下语法:

Hello, {!! $name !!}.

在刀片文件中使用{!! $variable !!}语法似乎风险很大。还是在这种情况下?

不逃离数据库中的数据是否风险过大?

在注释中,我们已经确定这个HTML实际上是由您在控制器方法中生成的。所以真正的问题是,你为什么要这么麻烦,只是为了颠覆MVC范式?

假设您有一个属性为address_1address_2address_3citystatezip_codeUser模型,这就是您需要做的

<td>
@if($user->address_1)
{{ $user->address_1 }}<br/>
@if($user->address_2) {{ $user->address_2 }}<br/>@endif
@if($user->address_3) {{ $user->address_3 }}<br/>@endif
@else
<i>{{ __("Street address unknown") }}</i><br/>
@endif
@if($user->city || $user->state)
{{ $user->city ?? "?" }}, {{ $user->state ?? "?" }}
@else
<i>City and state unknown</i>
@endif&nbsp;&nbsp;{{ $this->zip_code ?? "" }}
</td>

您提供的其余代码都在进行数据验证,在数据生命周期的这个阶段绝对不应该这样做。您的数据应该在进入应用程序时进行验证,无论是用户输入、CSV导入还是其他什么。你不应该把城市名称大写,弄清楚你的地址是否>3个字符长,或者想知道在显示时是否有一个州的缩写或全名。

用户提供的任何数据,即使存储在其间的数据库中,默认情况下也应被视为不安全。在这种特殊情况下,您将面临存储XSS的风险。

你应该确保你的数据可能是

  1. 逃逸(htmlspecialcharsstrip_tags等(
  2. 已验证(是否可以强制执行模式、字符限制(仅限a-Z或数字(或长度限制?(

好的,就是这样。在Blade组件或模板中使用的{{}}将始终将标记呈现为html实体。因此,正如miken32上面所说,关键是在返回字符串之前,只需使用字符串上的strip_tag,然后使用{!!!}将
标记渲染为实际的break标记,而不是html实体。

谢谢你,米肯和斑点。


好吧,我确信strip_tag不是个好主意。这又是一个问题,也许是一个答案。其中一个答案是编辑刀片模板,这样就可以将
标记直接放在模板中,而不是冒着它在数据库中的风险。但我认为它仍然可以在后端完成。这是我用来在数据表中显示个人地址的函数。

public function getFullAddressFhAttribute(){
$a1 = (!is_null($this->address_1) && strlen(trim($this->address_1))>3) ? ucWordsSpace(trim($this->address_1),'addr') : '';
$a2 = (!is_null($this->address_2) && strlen(trim($this->address_2))>3) ? ucWordsSpace(trim($this->address_2),'addr') : '';
$a3 = (!is_null($this->address_3) && strlen(trim($this->address_3))>3) ? ucWordsSpace(trim($this->address_3),'addr') : '';
$c =  (!is_null($this->city) && strlen(trim($this->city))>2) ? Str::title(trim($this->city)) : '';
$s = (!is_null($this->state) && strlen(trim($this->state))>1) ? trim($this->state) : '';
$s = (strlen($s)==2) ? strtoupper($s) : Str::title($s);
$z = (!is_null($this->zip_code) && strlen(trim($this->zip_code))>4) ? formatzip($this->zip_code) : '' ;
$address = (strlen($a1)>3) ? $a1 : '';
$address .= (strlen($address)>3 && strlen($a2)>3) ? "<br>$a2" : '';
$address .= (strlen($address)>3 && strlen($a3)>3) ? "<br>$a3" : '';
$address = (strlen($address)>3) ? $address . "<br>" : "<i>Street Addr Unknown</i><br>";
if(strlen($c.$s)==0)
$address .= "<i>City,State Unknown</i>";
else{
$address .= (strlen($c)>2) ? "$c," : "?, ";
$address .= (strlen($s)>1) ? " $s" : " ?";
}
$address .= (strlen($z)>4) ? "  $z" : '';
$safeElements = ["<br>", "<b>", "<i>"];
return strip_tags($address, $safeElements);
}

我认为,如果将上面的函数重写为前7个变量的strip_tag,那么它会更安全,如下所示:

public function getFullAddressFhAttribute(){
$a1 = (!is_null($this->address_1) && strlen(trim($this->address_1))>3) ? ucWordsSpace(trim($this->address_1),'addr') : '';
$a2 = (!is_null($this->address_2) && strlen(trim($this->address_2))>3) ? ucWordsSpace(trim($this->address_2),'addr') : '';
$a3 = (!is_null($this->address_3) && strlen(trim($this->address_3))>3) ? ucWordsSpace(trim($this->address_3),'addr') : '';
$c =  (!is_null($this->city) && strlen(trim($this->city))>2) ? Str::title(trim($this->city)) : '';
$s = (!is_null($this->state) && strlen(trim($this->state))>1) ? trim($this->state) : '';
$s = (strlen($s)==2) ? strtoupper($s) : Str::title($s);
$z = (!is_null($this->zip_code) && strlen(trim($this->zip_code))>4) ? formatzip($this->zip_code) : '' ;
$a1 = strip_tags($a1);
$a2 = strip_tags($a2);
$a3 = strip_tags($a3);
$c = strip_tags($c);
$s = strip_tags($s);
$z = strip_tags($z);

$address = (strlen($a1)>3) ? $a1 : '';
$address .= (strlen($address)>3 && strlen($a2)>3) ? "<br>$a2" : '';
$address .= (strlen($address)>3 && strlen($a3)>3) ? "<br>$a3" : '';
$address = (strlen($address)>3) ? $address . "<br>" : "<i>Street Addr Unknown</i><br>";
if(strlen($c.$s)==0)
$address .= "<i>City,State Unknown</i>";
else{
$address .= (strlen($c)>2) ? "$c," : "?, ";
$address .= (strlen($s)>1) ? " $s" : " ?";
}
$address .= (strlen($z)>4) ? "  $z" : '';
$safeElements = ["<br>", "<b>", "<i>"];
return strip_tags($address, $safeElements);
}

所以,在你把安全的标签放回去之前,把所有的标签都剥去。

相关内容

  • 没有找到相关文章

最新更新