社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
注意:请参考教程“保护应用程序免受跨站点脚本(XSS)攻击”以使用开发人员沙箱。 该教程中的代码段向您展示了如何使用转义序列,以使任何注入的代码都无法运行。
营造安全文化
公司将应用程序移动到Web上,以改善客户互动,降低业务处理成本并加快结果的速度。 但是这样做也增加了漏洞-除非安全性是应用程序开发过程的组成部分。 要了解有关在组织中创建安全文化的更多信息,请下载并阅读“ 安全Web应用程序:创建安全文化” 。
在跨站点脚本(XSS)攻击中,攻击者将恶意代码注入到合法的网页中,然后该网页运行恶意的客户端脚本。 当用户访问受感染的网页时,脚本将下载到用户的浏览器并从其运行。 此方案有很多变体。 恶意脚本可能访问浏览器cookie,会话令牌或浏览器保留的其他敏感信息。 但是,所有XSS攻击都遵循图1所示的模式。
在典型的XSS攻击中,攻击者找到了一种在服务器的网页中插入字符串的方法。 假设攻击者向网页中注入了以下字符串: <script>alert("attacked")</script>
。 最终用户每次访问此页面时,其浏览器都会下载此脚本并在呈现页面时运行该脚本。 在这种情况下,脚本将运行,并且用户会看到一个弹出警报,提示“已攻击”。
当攻击者成功利用Web应用程序中的XSS漏洞时,他们可以插入脚本,使他们能够访问最终用户的帐户凭据。 攻击者可以执行各种恶意活动,例如:
为了帮助防止XSS攻击,应用程序需要确保将页面中的所有变量输出编码后再返回给最终用户。 编码变量输出用称为实体的替代表示替代HTML标记。 浏览器显示实体,但不运行它们。 例如, <script>
转换为<script>
。
表1显示了一些常见HTML字符的实体名称。
结果 | 描述 | 实体名称 | 实体编号 |
---|---|---|---|
不间断空间 | &nbsp; | &#160; | |
< | 少于 | &lt; | &#60; |
> | 比...更棒 | &gt; | &#62; |
和 | &符 | &amp; | &#38; |
¢ | 分 | &cent; | &#162; |
£ | 磅 | &磅; | &#163; |
¥ | 日元 | &日元; | &#165; |
欧元 | &欧元; | &#8364; | |
§ | 部分 | &教派; | &#167; |
© | 版权 | &复制; | &#169; |
® | 注册商标 | &reg; | &#174 |
™ | 商标 | &trade; | &#8482; |
当Web浏览器遇到这些实体时,它们将被转换回HTML并打印出来,但是将不会运行。 例如,如果攻击者将<script>alert("you are attacked")</script>
注入服务器网页的变量字段中,则服务器将使用此策略返回<script>alert("you are attacked")</script>
。
当网络浏览器下载编码脚本时,它将编码脚本转换回<script>alert("you are attacked")</script>
并将该脚本显示为网页的一部分,但浏览器不会运行该脚本。
为确保恶意脚本代码不会作为页面的一部分输出,您的应用程序需要对所有可变字符串进行编码,然后才能在页面上显示它们。 编码只是将每个字符转换为其HTML实体名称,如清单1中的Java代码示例所示。
public class EscapeUtils {
public static final HashMap m = new HashMap();
static {
m.put(34, """); // < - less-than
m.put(60, "<"); // < - less-than
m.put(62, ">"); // > - greater-than
//User needs to map all html entities with their corresponding decimal values.
//Please refer to below table for mapping of entities and integer value of a char
}
public static String escapeHtml() {
String str = "<script>alert("abc")</script>";
try {
StringWriter writer = new StringWriter((int)
(str.length() * 1.5));
escape(writer, str);
System.out.println("encoded string is " + writer.toString() );
return writer.toString();
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
}
public static void escape(Writer writer, String str) throws IOException {
int len = str.length();
for (int i = 0; i < len; i++) {
char c = str.charAt(i);
int ascii = (int) c;
String entityName = (String) m.get(ascii);
if (entityName == null) {
if (c > 0x7F) {
writer.write("&#");
writer.write(Integer.toString(c, 10));
writer.write(';');
} else {
writer.write(c);
}
} else {
writer.write(entityName);
}
}
}
}
在清单1的Java示例中,对于HTML编码,输入为String "<script>alert("abc")</script>"
。 使用以下步骤。
StringWriter
,其大小为输入字符串长度的1.5倍。 escape
方法,该方法逐一拾取字符串中的每个字符并获取该字符的整数值。 字符串的每个字符都将转换为其实体名称。
输出是<script>alert("abc")</script>
。
表2将HTML实体映射到其十进制值。
小数 | 实体 | 描述 |
---|---|---|
160 | &nbsp; | 不间断空间 |
60 | &lt; | 少于 |
62 | &gt; | 比...更棒 |
38 | &amp; | &符 |
162 | &cent; | 分 |
163 | &磅; | 磅 |
165 | &日元; | 日元 |
8364 | &欧元; | 欧元 |
167 | &教派; | 部分 |
169 | &复制; | 版权 |
174 | &reg; | 注册商标 |
8482 | &trade; | 商标 |
跨站点脚本编写仍然是攻击用户计算机的最常用方法之一。 但是,您可以在很大程度上消除攻击者使用恶意代码感染Web应用程序的能力。 在编写应用程序时,请先对页面中的所有变量输出进行编码,然后再将其发送到最终用户的浏览器。
翻译自: https://www.ibm.com/developerworks/java/library/se-prevent/index.html
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!