跟着DVWA学Web安全开发

本文已发布到“安全脉搏”,原文链接:https://www.secpulse.com/archives/59262.html

0x00 前言

DVWA(Damn Vulnerable Web Application)是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用,旨在为安全专业人员测试自己的专业技能和工具提供合法的环境,帮助web开发者更好的理解web应用安全防范的过程。

本文将从DVWA中包含的各种漏洞来学习基本的Web安全开发中的需要注意的问题,本文旨在为Web开发中的新手提供一些安全指南,抛砖引玉,望大牛们多多指点。

0x01 SQL注入

1、使用mysql_real_escape_string函数,不要使用addslashes
mysql_escape_string已经被弃用,主要说下mysql_real_escape_stringaddslashes的区别
1.1 这两个函数都会对'"\\x00进行转义处理,除此之外mysql_real_escape_string还会对\r\n\x1a进行转义。
1.2 在字符集为GBK时,0xbf27不是一个合法的多字节字符,但0xbf5c却是,若我们输入0xbf27addslashes会将它修改为0xbf5c270xbf5c会被当作单字节字符,所以成功注入一个单引号,这就是宽字节注入。
2、使用is_numeric函数,但是如果单使用is_numeric函数是不行的,因为使用十六进制、科学记数法即可轻松绕过。
3、使用PDO技术,PDO是PHP数据对象(PHP Data Object)的缩写,即使用它的准备语句(Prepared Statements,即“参数化查询”)。举个例子:

1
2
3
4
5
6
7
$Statement = $pdo->prepare("select * from info where id =? and name = ?");
$id = 18;
$name = 'w2n1ck';
$Statement->bindParam(1,$id);
$Statement->bindParam(2,$name);
$Statement->execute();
$Statement->fetchAll();

PHP会将将SQL模板select * from info where id =? and name = ?和变量bindParam(1,$id);bindParam(2,$name);分两次发送给MySQL,由MySQL完成变量的转义处理,然后进行参数字符串匹配即可。
(PS:之前还了解了语义分析防SQL注入,一直觉得PDO很好了,为啥还要语义分析,后来才恍然大悟,PDO是对开发的,语义分析人家是为了卖产品,mdzz)
4、DVWA里面还加了Anti-CSRF token验证,进一步提高了系统安全性

0x02 XSS(跨站脚本)

DVWA中XSS防护流程步骤代码如下:

1
2
3
4
5
$message = trim( $_POST[ 'mtxMessage' ] );
Sanitize message input
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message );
$message = htmlspecialchars( $message );

1、使用trim函数,trim函数移除字符串两侧的空白字符或其他预定义字符。因为有时候我们会使用\t、\n、\r"等尝试绕过。
2、使用stripslashes,删除由 addslashes()函数添加的反斜杠。
3、使用mysql_real_escape_string转义一些特殊的字符。
4、使用htmlspecialchars把特殊字符&,",',<,>替换为HTML实体&amp;&quot;&#039;&lt;&gt;,但我们还是可以通过编码的方式绕过函数进行XSS注入,尤其是DOM型的XSS

1
2
3
4
5
6
<a href="
<?php echo htmlspecialchars("javascript:alert(1)",ENT_QUOTES); ?>
">test</a>
<a href="
<?php echo htmlspecialchars("javascript:location%3Dhttp%3A%2F%2Fwww.baidu.com",ENT_QUOTES); ?>
">test</a>

总结:对输入(URL参数)进行过滤;对输出进行编码;白名单和黑名单结合;

0x03 文件上传

DVWA中文件安全上传的流程:

1、取文件最后的扩展名

1
$uploaded_ext = substr( $uploaded_name, strrpos( $uploaded_name, '.' ) + 1);

2、对上传文件的文件名做随机数重命名操作

DVWA用的是MD5,rand()函数也可以

1
$target_file = md5( uniqid() . $uploaded_name ) . '.' . $uploaded_ext;

3、采取白名单方式验证文件的后缀名,MIME-TYPE类型,以及文件大小

1
2
3
if( ( strtolower( $uploaded_ext ) == 'jpg' || strtolower( $uploaded_ext ) == 'jpeg' || strtolower( $uploaded_ext ) == 'png' ) &&
( $uploaded_size < 100000 ) &&
( $uploaded_type == 'image/jpeg' || $uploaded_type == 'image/png'

4、检查是否为真正图片

1
getimagesize( $uploaded_tmp )

5、使用GD库或image-magick进行二次渲染

二次渲染,清除图片中的恶意代码

1
$img = imagecreatefromjpeg( $uploaded_tmp );

6、回显相对路径

1
if( rename( $temp_file, ( getcwd() . DIRECTORY_SEPARATOR . $target_path . $target_file ) ) )

DVWA中只是从代码设计层面考虑文件上传的安全性,比如还有Nginx与Apache的解析漏洞,截断问题,.htaccess,.user.ini后门,windows特性,ADS流,RTLO技术,包含漏洞等等。

0x04 文件包含

DVWA中的文件包含直接写死了就那几个文件,简单粗暴。。。

这里举一些需要注意的点:

  1. 使用open_basedir配置,限制文件目录
  2. 过滤./,注意不是../,因为可以使用..././..././绕过
  3. 禁止服务器远程文件包含,allow_url_fopen=Off与allow_url_include=Off
  4. 注意php://input,data://等各种伪协议问题
  5. 注意截断问题,比如%00截断,超长路径截断,点号截断
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    file:///var/www/html 访问本地文件系统
    ftp://<login>:<password>@<ftpserveraddress> 访问FTP(s) URLs
    data:// 数据流
    http:// — 访问 HTTP(s) URLs
    php://input — 访问各个输入/输出流
    zlib:// — 压缩流
    glob:// — 查找匹配的文件路径模式
    phar:// — PHP Archive
    ssh2:// — Secure Shell 2
    rar:// — RAR
    ogg:// — Audio streams
    expect:// — 处理交互式的流
    php://filter/

0x05 命令执行

DVWA中是以ping命令为例

1
2
$octet = explode( ".", $target ); //以点号进行分割
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) //判断每个部分是否是数字,同时size是否为4

这里举一些需要注意的点:

1.尽量少用执行命令的函数或者直接禁用
2.参数值尽量使用引号包裹
3.在使用动态函数之前,确保使用的函数是指定的函数之一
4.在进入执行命令的函数、方法之前,对参数进行过滤,对敏感字符进行转义,PHP中使用escapeshellcmd函数

escapeshellcmd对字符串中可能会欺骗shell命令执行任意命令的字符进行转义。 此函数保证用户输入的数据在传送到exec()或system()函数,或者执行操作符 之前进行转义。
特殊字符有`#,&,;反引号,|,*,?,~,<,>,^,(,),[,],{,},$,x0A,x00和xFF`。'和"仅在不配对的时候被转义。在Windows平台上以前缀`^`来转义的

0x06 CSRF(跨站请求伪造)

DVWA中的CSRF是以改密码为例。

1、验证token

这是一个非常有效的手段,用户每次访问改密页面时,服务器会返回一个随机的token,向服务器发起请求时,需要提交token参数,而服务器在收到请求时,会优先检查token,只有token正确,才会处理客户端的请求。

1
2
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

2、二次确认

1
2
3
4
5
6
7
8
9
10
// Get input
$pass_curr = $_GET[ 'password_current' ];
...
// Check that the current password is correct
$data = $db->prepare( 'SELECT password FROM users WHERE user = (:user) AND password = (:password) LIMIT 1;' );
$data->bindParam( ':user', dvwaCurrentUser(), PDO::PARAM_STR );
$data->bindParam( ':password', $pass_curr, PDO::PARAM_STR );
$data->execute();
// Do both new passwords match and does the current password match the user?
if( ( $pass_new == $pass_conf ) && ( $data->rowCount() == 1 ) ){}

二次确认就是在调用某些功能时进行二次验证,如:删除用户时,产生一个提示对话框,提示”确定删除用户吗?”,转账操作时,要求用户输入二次密码。

3、验证码

这是一个非常简单并且有效的防御CSRF的方法。

0x07 暴力破解

1、增加验证码,token等验校字段

DVWA中加入了Anti-CSRFtoken预防无脑爆破。

2、增加sleep操作

只要登陆失败,则延迟3秒,大大降低了爆破速度

1
2
// Login failed
sleep( rand( 2, 4 ) );

3、增加登陆错误机制

单用户,登陆次数错误到一定次数,即锁定该账户。此外还可以对用户IP等进行频次限制。

0x08 验证码

验证码主要会出现一些逻辑漏洞,最常见的有两种:

  1. 验证过程分两步,先验证验证码是否正确,正确则进行下一步
  2. 验证码没有设置有效时间,导致可以重复使用

参考链接:
http://www.jb51.net/article/56612.htm
http://www.freebuf.com/author/lonehand
http://www.cnblogs.com/Hyber/p/6133196.html
http://www.am0s.com/functions/227.html

大爷,赏个铜板呗!