XSS概述
1.原理
xss(Cross Site Script)跨站脚本攻击,指的是攻击者在Web页面插入恶意JS代码,这些代码在HTML解释时会被当做脚本执行,所以当用户请求该网页时,嵌入其中JS代码就会被执行,从而达到攻击的目的.
XSS漏洞类型
XSS漏洞 一般会出现在查询框,留言板等可以输入的地方.
1.反射型
反射型XSS漏洞(Reflected XSS): 攻击者利用目标网站对用户输入内容缺乏过滤和转义导致攻击脚本被插入到目标网页的URL参数中。当用户访问带有攻击脚本的URL时,浏览器会执行该脚本,此时攻击者就可以获取用户的信息。它是用户请求一次资源,服务器响应用户请求,并将原有数据返回到用户端,因为攻击者请求时利用漏洞向页面中插入了一串恶意代码,而服务器原样返回了该页面的数据,所以当解析到该页面这串代码时便完成一次攻击。一次请求一次响应,所以叫反射型。
非存储型,就是通过get或者post请求时,被后端处理过数据,并且响应到前端页面上。
2.存储型
存储型XSS漏洞(Stored XSS):攻击者在目标网站中插入的恶意JS脚本,被存储到了存放该页面数据的数据库中。就比如说,留言框,访问者在这里的留言可以一直显示在此页面中,这些数据其实是被存放在了一个数据库中,所以当用户再访问留言框这个页面时,才会看到别人的留言内容。存储型XSS漏洞就是把这个恶意JS代码提交到类似留言框的地方,使它永久存在数据库中去。所以当用户再次访问被存储攻击脚本的页面时,攻击脚本会被执行。
XSS代码被存储到服务器上的数据库里的某张表的字段里,或者页面,或者某个上传文件里。
3.DOM型
DOM型XSS的攻击方式。它是由于前端JavaScript框架在解析用户输入时对搜索引擎的优化而导致的。攻击者可以在URL上通过特定形式的参数伪装为页面的一部分,再通过脚本来执行攻击。由于DOM异常处理能力较弱,攻击者可以通过构造特殊的参数来绕过安全限制,实现XSS攻击。
仅仅在前段页面进行操作的。
XSS危害
窃取用户的个人信息:攻击者通过XSS注入恶意脚本,可以获取用户的Cookie、Session等敏感信息,从而窃取用户的账户名、密码、邮件、手机号等个人隐私。
利用用户浏览器进行攻击:攻击者可以将恶意脚本注入到非法网站,然后通过社会工程学的手段,诱骗用户访问该网站,进而将攻击方式延伸至用户的操作系统,造成更大的影响。
损害网站的声誉和信誉:遭受XSS攻击的网站会受到恶意攻击者的破坏,可能会误导用户、篡改网站内容,导致网站运营商的信誉受到影响。
泄露企业机密信息:企业针对外部用户开发的Web应用程序,如果存在XSS漏洞,可能会导致机密信息被攻击者窃取,造成不良的财务、商业影响。
XSS测试代码
(1)<script>alert('XSS')</script> //简单弹框
(2)<ScRiPt>AlErt('XSS')</ScRiPt> //过滤大小写
(3)<img src="#" onerror=alert("XSS")> //img 标签 进行绕过
(4)javascript:alert('xss') //使用 Javascript 的尾协议
(5)onclick=alert("xss") //利用 href 属性值来进行xss
靶场实操
1.反射型XSS
Low Reflected XSS Source
<?php
header ("X-XSS-Protection: 0");
/*array_key_exists()是判断一个数组中是否存在指定键名的函数。如果数组中存在该键名,返回值为true,否则返回false。
在PHP中,如果使用GET方法传递参数,那么可以使用GET来获取参数。
$_GET是一个关联数组,它包含了所有GET参数的键值对,
其中键是传递的参数名,这里指的是name这个参数,值是参数的值,这里指的name=具体的值。*/
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
// Feedback for end user
echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}
/*这个low等级的靶场,没有对输入的数据做任何控制和过滤,所以简单JS代码就可以完整插入并解析执行*/
?>
Medium Reflected XSS Source
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
/*str_replace()函数是一个字符串替换函数.
他的意思是将字符串中含有的指定字串替换为其他特定的内容。
这里面有三个参数,第一个参数:要查找替换的子串,此处要查找的是<script>这个字串;
第二个参数:是要替换为的子串,这里是替换为空;
第三个参数:是传入的待查找的字符串*/
$name = str_replace( '<script>', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
/*这个medium等级的靶场,只是做了一个字符串替换为空串的过滤
把输入字符串中含有的<script>子串替换为空.
所以可以利用大小写绕过的方式*/
?>
High Reflected XSS Source
<?php
header ("X-XSS-Protection: 0");
// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
/*preg_replace()正则匹配函数,它的功能是对传入的字符串进行正则匹配后做相应的替 换。‘/’符号表示正则表达式的开始和结束。
该正则表达式/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i"的含义为:
"<"表示匹配以"<"开头的字符串;
"(.*)"表示匹配任意字符(表示s、c、r、i、p、t之间可以是任何字符);
"i"表示忽略大小写。*/
/*所以该正则表达式用于检查字符串中是否包含<script>标签,如果有就将此标签替换为空*/
$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );
// Feedback for end user
echo "<pre>Hello ${name}</pre>";
}
?>
/*这个high等级的靶场,对传入的字符串中含有子串<script>的做了正则匹配后替换为空的操作并且还忽略大小写。
所以对这个的绕过方式是替换别的标签进行XSS,比如使用img标签<img src="#" οnerrοr=alert("XSS")>*/
2.存储型XSS
Low Stored XSS Source
<?php
/*首先使用isset()函数判断用户是否通过表单提交了信息,并从$_POST数组中获取提交的信息和用户名。*/
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
/*使用stripslashes()函数将用户提交的留言信息中的反斜杠去掉,避免用户恶意提交包含反斜杠的信息
在MySQL数据库中,字符串中的反斜杠被用于转义字符,例如,某个字符串中含有单引号('),则必须添加反斜杠进行转义,*/
/*用mysqli_real_escape_string()函数对留言信息和用户名进行SQL特殊字符转义。这一步是为了避免SQL注入攻击。
在使用mysqli_real_escape_string()函数时,需要传入两个参数.
第一个参数是连接到MySQL服务器的对象(即MYSQLi连接对象)
第二个参数是需要被转义的字符串*/
$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
/*使用mysqli_query()函数将处理好的留言信息和用户名插入到guestbook表中,并根据是否插入成功输出相应的错误信息。*/
$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();
}
?>
Medium Stored XSS Source
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// 首先,它检查是否点击了“btnSign”提交按钮,然后获取表单中的留言和姓名输入
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
//strip_tags() 函数去除任何 HTML 标签。
//addslashes() 函数添加转义字符,以防止 SQL 注入攻击。
//mysqli_real_escape_string() 函数对字符串进行转义,防止 SQL 注入攻击。
$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)) ? "" : ""));
//htmlspecialchars() 函数将 HTML 实体转换为特殊字符。
$message = htmlspecialchars( $message );
// Sanitize name input
//str_replace() 函数删除所有 <script> 标签,以防止 XSS 攻击。
//mysqli_real_escape_string() 函数以一种安全的方式对字符串进行转义,防止 SQL 注入攻击。
$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
//最后,将留言和姓名插入到一个数据库表中,使用了 mysqli_query() 函数执行 SQL 插入操作.
$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();
}
?>
High Stored XSS Source
<?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
/*这段代码和之前的代码非常相似,不同之处在于对姓名输入的过滤方法。
在这里,使用 preg_replace() 函数进行正则匹配,将所有包含 s, c, r, i, p, t 的字符串替换为空字符串,并且忽略大小写,所以这个就是过滤了<script>标签的各种形式。*/
/*这里使用img标签绕过,<img src="#" οnerrοr=alert("XSS之过滤")>*/
$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();
}
?>