在只有纯文本输入的站点上使用 HTML Purifier
Using HTML Purifier on a site with only plain text input
如果能解决我和一些同事之间的分歧,我将不胜感激。
我们有一个典型的 PHP / LAMP 网络应用程序。
我们希望用户输入的唯一内容是纯文本。我们不邀请或希望用户在任何时候输入 HTML。表单元素大多是基本的输入文本标签。可能会有一些文本区域、复选框等
目前没有对页面输出进行清理。所有动态内容(其中一些来自用户输入)都简单地回显到页面。我们显然需要确保安全。
我的解决方案是在页面上回显时对所有输出使用 htmlspecialchars。
我同事的解决方案是将 HTML Purifier 添加到数据库层。他们希望在将所有用户输入的内容保存到数据库之前通过 HTML Purifier 传递。显然他们在其他项目中也像这样使用过它,但我认为这是对 HTML Purifier 用途的误解。
我的理解是,只有在允许用户输入 HTML 的站点上使用 HTML Purifier 才有意义。它需要 HTML 并根据白名单和其他规则使其更安全、更清洁。
谁对谁错?
还有整个 "escape on input or output" 问题,但我想这是另一个时间和地点的辩论。
谢谢
作为一般规则,应该针对上下文和用例进行转义。
如果您想做的是在 HTML 上下文中输出纯文本(您确实这样做了),那么您需要使用转义功能来确保您始终在 [=] 中输出纯文本87=] 上下文。给定基本 PHP,那确实是 htmlspecialchars($yourString, ENT_QUOTES, 'yourEncoding');
.
如果你想做的是在 HTML 上下文中输出 HTML(你没有),那么你会想要 santitise HTML 当你输出它以防止它造成损坏时 - 这里你会 $purifier->purify($yourString);
输出。
如果你想通过执行 SQL 语句将纯文本用户输入存储在数据库中(同样,你这样做了),那么你应该使用准备好的语句来防止 SQL 注入,或者特定于您的数据库的转义函数,例如 mysql_real_escape_string($yourString)
.
你应该不:
- 将数据放入数据库时转义 HTML
- 在将数据放入数据库时HTML进行清理
- 当您将数据输出为纯文本时,HTML 进行清理
其中,所有这些都是完全有害的,尽管程度不同。请注意,以下假设数据库是您唯一的或规范的数据存储介质(它还假设您以其他方式处理了 SQL 注入 - 如果您不这样做,那将是您的主要问题):
- 如果在将数据放入数据库时为 HTML 进行转义,则可以保证始终将数据输出到 HTML 上下文中;突然之间,如果你只想把它放入一个明文文件中按原样打印,你需要在输出之前对数据进行解码。
- 如果您在将数据放入数据库时将数据清理为 HTML,您将破坏用户放置在那里的信息。它是一个消息传递系统,您的用户想告诉其他人有关
<script>
标签的信息吗?您的用户不能那样做 - 您会破坏他的消息的那一部分!
如果您没有将清理模块设置为 strip ,当您将数据输出为纯文本(不转义)时,清理为 HTML 可能会产生令人困惑的分页结果]all HTML(你不应该这样做,因为那时你显然不想输出 HTML)。
您是否针对 <div>
上下文进行了清理,但将数据放入内联元素中?您的用户可能会将 <div>
放入您的内联元素中,迫使布局中断您的页面布局(这有多烦人取决于您的布局),或者影响用户对元数据的感知(例如使网络钓鱼更容易),例如像这样:
- 姓名:John Doe
(网站管理员)
您是否针对 <span>
上下文进行了清理?用户可以使用其他标签来影响用户对元数据的感知,例如像这样:
- 姓名:John Doe (该用户是管理员)
最坏的情况:您是否使用 HTML Purifier 版本对您的 HTML 进行了消毒,但后来发现存在允许某种恶意 HTML 的错误生存?现在您正在输出不受信任的数据,并使在您的网页上查看此数据的用户处于危险之中。
消毒为 HTML 和 为 HTML 转义(按此顺序!)没有这个问题,但这意味着消毒步骤是不必要的,这意味着这个星座只会降低你的表现。 (大概这就是为什么你的同事想在保存数据时而不是在显示数据时进行清理 - 大概你的用例(像大多数一样)会比提交数据更频繁地显示数据,这意味着你将避免不得不处理频繁的性能问题。)
tl;博士
当您以纯文本形式输出时,将其作为 HTML 进行消毒并不是一个好主意。
转义/清理用例和上下文。
在你的情况下,你想为 HTML 上下文转义纯文本(= 使用 htmlspecialchars()
)。
如果能解决我和一些同事之间的分歧,我将不胜感激。
我们有一个典型的 PHP / LAMP 网络应用程序。
我们希望用户输入的唯一内容是纯文本。我们不邀请或希望用户在任何时候输入 HTML。表单元素大多是基本的输入文本标签。可能会有一些文本区域、复选框等
目前没有对页面输出进行清理。所有动态内容(其中一些来自用户输入)都简单地回显到页面。我们显然需要确保安全。
我的解决方案是在页面上回显时对所有输出使用 htmlspecialchars。
我同事的解决方案是将 HTML Purifier 添加到数据库层。他们希望在将所有用户输入的内容保存到数据库之前通过 HTML Purifier 传递。显然他们在其他项目中也像这样使用过它,但我认为这是对 HTML Purifier 用途的误解。
我的理解是,只有在允许用户输入 HTML 的站点上使用 HTML Purifier 才有意义。它需要 HTML 并根据白名单和其他规则使其更安全、更清洁。
谁对谁错?
还有整个 "escape on input or output" 问题,但我想这是另一个时间和地点的辩论。
谢谢
作为一般规则,应该针对上下文和用例进行转义。
如果您想做的是在 HTML 上下文中输出纯文本(您确实这样做了),那么您需要使用转义功能来确保您始终在 [=] 中输出纯文本87=] 上下文。给定基本 PHP,那确实是 htmlspecialchars($yourString, ENT_QUOTES, 'yourEncoding');
.
如果你想做的是在 HTML 上下文中输出 HTML(你没有),那么你会想要 santitise HTML 当你输出它以防止它造成损坏时 - 这里你会 $purifier->purify($yourString);
输出。
如果你想通过执行 SQL 语句将纯文本用户输入存储在数据库中(同样,你这样做了),那么你应该使用准备好的语句来防止 SQL 注入,或者特定于您的数据库的转义函数,例如 mysql_real_escape_string($yourString)
.
你应该不:
- 将数据放入数据库时转义 HTML
- 在将数据放入数据库时HTML进行清理
- 当您将数据输出为纯文本时,HTML 进行清理
其中,所有这些都是完全有害的,尽管程度不同。请注意,以下假设数据库是您唯一的或规范的数据存储介质(它还假设您以其他方式处理了 SQL 注入 - 如果您不这样做,那将是您的主要问题):
- 如果在将数据放入数据库时为 HTML 进行转义,则可以保证始终将数据输出到 HTML 上下文中;突然之间,如果你只想把它放入一个明文文件中按原样打印,你需要在输出之前对数据进行解码。
- 如果您在将数据放入数据库时将数据清理为 HTML,您将破坏用户放置在那里的信息。它是一个消息传递系统,您的用户想告诉其他人有关
<script>
标签的信息吗?您的用户不能那样做 - 您会破坏他的消息的那一部分!
如果您没有将清理模块设置为 strip ,当您将数据输出为纯文本(不转义)时,清理为 HTML 可能会产生令人困惑的分页结果]all HTML(你不应该这样做,因为那时你显然不想输出 HTML)。
您是否针对 <div>
上下文进行了清理,但将数据放入内联元素中?您的用户可能会将 <div>
放入您的内联元素中,迫使布局中断您的页面布局(这有多烦人取决于您的布局),或者影响用户对元数据的感知(例如使网络钓鱼更容易),例如像这样:
- 姓名:John Doe
(网站管理员)
您是否针对 <span>
上下文进行了清理?用户可以使用其他标签来影响用户对元数据的感知,例如像这样:
- 姓名:John Doe (该用户是管理员)
最坏的情况:您是否使用 HTML Purifier 版本对您的 HTML 进行了消毒,但后来发现存在允许某种恶意 HTML 的错误生存?现在您正在输出不受信任的数据,并使在您的网页上查看此数据的用户处于危险之中。
消毒为 HTML 和 为 HTML 转义(按此顺序!)没有这个问题,但这意味着消毒步骤是不必要的,这意味着这个星座只会降低你的表现。 (大概这就是为什么你的同事想在保存数据时而不是在显示数据时进行清理 - 大概你的用例(像大多数一样)会比提交数据更频繁地显示数据,这意味着你将避免不得不处理频繁的性能问题。)
tl;博士
当您以纯文本形式输出时,将其作为 HTML 进行消毒并不是一个好主意。
转义/清理用例和上下文。
在你的情况下,你想为 HTML 上下文转义纯文本(= 使用 htmlspecialchars()
)。