防止 XSS 和 SQL 注入就这么简单吗

发布于 2024-08-16 11:19:16 字数 1030 浏览 3 评论 0原文

问题:在任何保存的输入字段上使用 strip_tags 并运行 htmlspecialchars 是否可以简单地防止 XSS(跨站点脚本) > 在任何显示的输出上...​​并通过使用 PHP PDO 准备好的语句来防止 SQL 注入

这是一个例子:

// INPUT: Input a persons favorite color and save to database
// this should prevent SQL injection ( by using prepared statement)
// and help prevent XSS  (by using strip_tags)
$sql = 'INSERT INTO TABLE favorite (person_name, color) VALUES (?,?)';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name']), strip_tags($_POST['color'])));


// OUTPUT: Output a persons favorite color from the database
// this should prevent XSS (by using htmlspecialchars) when displaying
$sql = 'SELECT color FROM favorite WHERE person_name = ?';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name'])));
$sth->setFetchMode(PDO::FETCH_BOTH);
while($color = $sth->fetch()){
  echo htmlspecialchars($color, ENT_QUOTES, 'UTF-8');
}

Question: Is preventing XSS (cross-site scripting) as simple using strip_tags on any saved input fields and running htmlspecialchars on any displayed output ... and preventing SQL Injection by using PHP PDO prepared statements?

Here's an example:

// INPUT: Input a persons favorite color and save to database
// this should prevent SQL injection ( by using prepared statement)
// and help prevent XSS  (by using strip_tags)
$sql = 'INSERT INTO TABLE favorite (person_name, color) VALUES (?,?)';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name']), strip_tags($_POST['color'])));


// OUTPUT: Output a persons favorite color from the database
// this should prevent XSS (by using htmlspecialchars) when displaying
$sql = 'SELECT color FROM favorite WHERE person_name = ?';
$sth = $conn->prepare($sql);
$sth->execute(array(strip_tags($_POST['person_name'])));
$sth->setFetchMode(PDO::FETCH_BOTH);
while($color = $sth->fetch()){
  echo htmlspecialchars($color, ENT_QUOTES, 'UTF-8');
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

梦境 2024-08-23 11:19:16

就更简单了。只需在用户控制的输入上使用 htmlspecialchars() (带有引号样式和字符集)就足够了。仅当您希望在处理/保存到数据库之前清理数据时,strip_tags() 才有用,而这在现实世界中通常不使用。 HTML 代码在 PHP 源代码中不会造成损害,但如果您在未经净化的用户控制输入或此类邪恶内容上使用 eval() ,PHP 代码可能会造成损害。

然而,这并不能避免SQL 注入,但那是另一回事了。

更新:从请求中获取干净用户输入,以避免

function get_string($array, $index, $default = null) {
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
         return get_magic_quotes_gpc() ?  stripslashes($value) : $value;
    } else {
         return $default;
    }
}

可以用作:(

$username = get_string($_POST, "username");
$password = get_string($_POST, "password");

您可以对 get_numberget_boolean 进行类似操作、get_array 等)

准备 SQL 查询以避免SQL 注入< /a>, do:

$sql = sprintf(
    "SELECT id FROM user WHERE username = '%s' AND password = MD5('%s')",
        mysql_real_escape_string($user),
        mysql_real_escape_string($password)
); 

要显示用户控制的输入以避免 XSS,请执行:

echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');

It's even more simple. Just htmlspecialchars() (with quote style and character set) on user-controlled input is enough. The strip_tags() is only useful if you already want to sanitize data prior to processing/save in database, which is often not used in real world. HTML code doesn't harm in PHP source, but PHP code may do so if you use eval() on non-sanitized user-controlled input or that kind of evil stuff.

This however doesn't save you from SQL injections, but that's another story.

Update: to get clean user input from the request to avoid magic quotes in user-controlled input, you can use the following function:

function get_string($array, $index, $default = null) {
    if (isset($array[$index]) && strlen($value = trim($array[$index])) > 0) {
         return get_magic_quotes_gpc() ?  stripslashes($value) : $value;
    } else {
         return $default;
    }
}

which can be used as:

$username = get_string($_POST, "username");
$password = get_string($_POST, "password");

(you can do simliar for get_number, get_boolean, get_array, etc)

To prepare the SQL query to avoid SQL injections, do:

$sql = sprintf(
    "SELECT id FROM user WHERE username = '%s' AND password = MD5('%s')",
        mysql_real_escape_string($user),
        mysql_real_escape_string($password)
); 

To display user-controlled input to avoid XSS, do:

echo htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
恋你朝朝暮暮 2024-08-23 11:19:16

这取决于您想要在何处以及如何使用用户数据。您需要知道要在其中插入数据的上下文以及该上下文的元字符。

如果您只想允许用户在您的网站上添加文本,htmlspecialchars 足以转义 HTML 元字符。但是,如果您想要允许某些 HTML 或想要将用户数据嵌入到现有 HTML 元素中(例如将 URL 嵌入到 A/IMG 元素中),则可以使用 htmlspecialchars 是不够的,因为您不再处于 HTML 上下文中,而是处于 URL 上下文中。

因此,在图像 URL 字段中输入 将会产生:

<img src="<script>alert("xss")</script>" />

但输入 javascript:alert("xss") 将会产生:成功:

<img src="javascript:alert("xss")" />

在这里,您应该看一下精彩的XSS(跨站脚本)备忘单来了解您的用户数据可以注入到什么上下文中。

It depends on where and how you want to use the user data. You need to know the context you want to insert your data in and the meta characters of that context.

If you just want to allow the user to put text up on your website, htmlspecialchars suffices to escape the HTML meta characters. But if you want to allow certain HTML or want to embed user data in existing HTML elements (like a URL into a A/IMG element), htmlspecialchars is not enough as you’re not in the HTML context anymore but in the URL context.

So entering <script>alert("xss")</script> into a image URL field will yield:

<img src="<script>alert("xss")</script>" />

But entering javascript:alert("xss") will succeed:

<img src="javascript:alert("xss")" />

Here you should take a look at the fabulous XSS (Cross Site Scripting) Cheat Sheet to see what contexts your user data can be injected in.

决绝 2024-08-23 11:19:16

strip_tags 不是必需的。在大多数情况下,strip_tags 只是令人恼火,因为某些用户可能希望在其文本中使用 <>。在将文本回显到浏览器之前,只需使用 htmlspecialchars(或 htmlentities,如果您愿意)。

(在将任何内容插入数据库之前,不要忘记 mysql_real_esacpe_string!)

strip_tags is not necessary. In most cases strip_tags is just irritating, because some of your users may want to use < and > in their texts. Just use htmlspecialchars (or htmlentities if you prefer) before you echo the texts to the browser.

(Don't forget mysql_real_esacpe_string before you insert anything into your database!)

记忆之渊 2024-08-23 11:19:16

一般规则/模因是“过滤输入,转义输出”。在输入中使用 strip_tags 来删除任何 HTML 对于输入过滤来说是一个好主意,但您应该尽可能严格地限制允许的输入。例如,如果输入参数仅应为整数,则仅接受数字输入并始终将其转换为整数,然后再对其进行任何操作。一个经过严格审查的输入过滤库将为您提供很大帮助;一个不特定于特定框架的是 Inspekt (我写的,所以我有点偏见)。

对于输出,htmlspecialchars 应该能够逃避 XSS 攻击,但前提是您传递了正确的参数。您必须传递引号转义样式和字符集。

一般来说,这应该消除 XSS 攻击:

$safer_str = htmlspecialchars($unsafe_str, ENT_QUOTES, 'UTF-8');

如果不传递 ENT_QUOTES 作为第二个参数,单引号字符不会被编码。此外,当未传递正确的字符集(通常 UTF-8 就足够了)时,XSS 攻击已被证明。 htmlspecialchars始终使用 ENT_QUOTES 和字符集参数调用。

请注意,PHP 5.2.12 包含针对多字节 XSS 攻击的修复。

您可能会发现 OWASP ESAPI PHP 端口 有趣且有用,尽管 PHP 版本AFAIK 并不完整。

The general rule/meme is "Filter Input, Escape Output." Using strip_tags on your input to remove any HTML is a good idea for input filtering, but you should be as strict as possible in what input you allow. For example, if an input parameter is only supposed to be an integer, only accept numeric input and always convert it to an integer before doing anything with it. A well-vetted input filtering library is going to help you a lot here; one that isn't specific to a particular framework is Inspekt (which I wrote, so I'm a bit biased).

For output, htmlspecialchars should be able to escape XSS attacks, but only if you pass the correct parameters. You must pass the quote escaping style and a charset.

In general, this should remove XSS attacks:

$safer_str = htmlspecialchars($unsafe_str, ENT_QUOTES, 'UTF-8');

Without passing ENT_QUOTES as the second parameter, single-quote chars are not encoded. Additionally, XSS attacks have been demonstrated when the correct charset is not passed (typically UTF-8 will be adequate). htmlspecialchars should always be called with ENT_QUOTES and a charset parameter.

Note that PHP 5.2.12 contains a fix for a multibyte XSS attack.

You may find the OWASP ESAPI PHP port interesting and useful, although the PHP version is not complete AFAIK.

我是男神闪亮亮 2024-08-23 11:19:16

是的,使用 PDO 准备好的语句可以防止 SQL 注入。 SQL注入攻击的基础是攻击者提交的数据被视为查询的一部分。例如,攻击者提交字符串“a”或“a”=“a”作为其密码。不是将整个字符串与数据库中的密码进行比较,而是将其包含在查询中,因此查询变为“SELECT * FROM users WHERE login='joe' AND password='a' or 'a'='a' ”。攻击者输入的部分被解释为查询的一部分。然而,在准备语句的情况下,您要具体告诉 SQL 引擎,哪一部分是查询,哪一部分是数据(通过设置参数),因此不可能出现这种混淆。

不,使用 strip_tags 并不总能保护您免受跨站点脚本攻击。考虑以下示例。假设您的页面包含:

<script>
location.href='newpage_<?php echo strip_tags($_GET['language']); ?>.html';
</script>

攻击者提交请求,并将“语言”设置为“';somethingevil();'”。 strip_tags() 按原样返回此数据(其中没有标签)。生成的页面代码变为:

<script>
location.href='newpage_';somethingevil();'.html';
</script>

someevil() 被执行。将 Somethingevil() 替换为实际的 XSS 漏洞利用代码。

您使用 htmlspecialchars() 的最后一个示例将防止出现这种情况,因为它会转义单引号。然而,我在 JavaScript 代码中看到了更奇怪的用户提供数据的情况,这些数据甚至不在带引号的字符串中。我认为它在变量或函数名称中。在最后一种情况下,再多的逃避可能也无济于事。我认为最好避免使用用户输入来生成 JavaScript 代码。

Yes, using PDO prepared statements protects from SQL injection. The SQL injection attack is based on the fact that the data submitted by the attacker is treated as a part of the query. For example, the attacker submits the string "a' or 'a'='a" as his password. Instead of the whole string being compared to the passwords in the database, it is included in the query, so the query becomes "SELECT * FROM users WHERE login='joe' AND password='a' or 'a'='a'". The part of attacker input is interpreted as a part of the query. However in case of prepared statements, you are telling the SQL engine specifically, what part is the query, and what part is data (by setting the parameters), so no such confusion is possible.

No, using strip_tags will not always protect you from cross-site scripting. Consider the following example. Let's say your page contains:

<script>
location.href='newpage_<?php echo strip_tags($_GET['language']); ?>.html';
</script>

The attacker submits the request with "language" set to "';somethingevil();'" . strip_tags() returns this data as is (there are no tags in it). The produced page code becomes:

<script>
location.href='newpage_';somethingevil();'.html';
</script>

somethingevil() gets executed. Replace somethingevil() with actual XSS exploit code.

Your last example with htmlspecialchars() will protect against this one, because it will escape single quotes. However I have seen even weirder cases of user-supplied data inside JavaScript code, where it is not even within a quoted string. I think it was in the variable or function name. In that last case no amount of escaping will probably help. I beleive that it is best to avoid using user input to generate JavaScript code.

慈悲佛祖 2024-08-23 11:19:16

简单的答案:没有

更长的答案:有一些 PHP strip_stags 无法避免的注入 xss 的方法。

为了获得更好的保护,请尝试 HTML 净化器

Simple answer : no

Longer answer : There are ways to inject xss that PHP strip_stags cannot avoid.

For better protection try HTML purifier

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文