DVWA中学习PHP常见漏洞及修复方法

http://www.2cto.com/Article/201308/237598.html

“安全是一个整体,保证安全不在于强大的地方有多强大 而在于真正薄弱的地方在哪里”--剑心

从很多的渗透大型企业内网的案例来看,入侵者大多数是从Web上找到漏洞,从而利用漏洞进一步进行提权,渗透入侵。

 网易某系统未授权访问可导致内网被渗透:http://www.2cto.com/Article/201208/151524.html

 网易某系统未授权访问续—内网渗透:http://www.2cto.com/Article/201208/151741.html

 

脚本安全就像你家的防盗门,你家门都没关,你家能安全吗?

乌云上最常见的脚本漏洞莫过于SQL注入和XSS。

脚本安全的本质就是脚本接受了不安全的变量输入,又没得到有效的过滤,最后进入一些对敏感的函数就会对安全造成威胁。

比如出现在mysql_query()函数可能就会造成SQL注入漏洞,出现在eval()以及preg_replace()中可能导致代码的执行。

这里我用DVWA演示SQL,XSS ,任意代码执行漏洞的原理

然后用各种修复方法进行修复,附带讲解一些修复方法的弊端。

DVWA下载地址: https://github.com/RandomStorm/DVWA/archive/v1.0.8.zip

DVWA sql调用的文件/vulnerabilities/sqli/目录下,分为low,medium,high三个等级

SQL注入原理

 
?
1
2
3
4
5
6
7
8
9
10
//Low.php
  
if (isset( $_GET [ 'Submit' ])){
  
     // Retrieve data
  
     $id = $_GET [ 'id' ];
  
     $getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'" ; //这里$id变量没有经过任何的过滤,直接传入了sql语句,造成字符型注入
     $result = mysql_query( $getid ) or die ( '
' 
          . mysql_error() .  
          '
' ); //执行SQL


原SQL中

SELECT first_name, last_name FROM users WHERE user_id = '$id'

中的$id可被用户控制,当黑客把$id变成

' union select user,password from users#

那么这条语句就会变成

SELECT first_name, last_name FROM users WHERE user_id = '' union select user,password from users#

这样导致了数据库中其他数据被黑客查询。 

 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
//medium.php中
if (isset( $_GET [ 'Submit' ])) {
  
     // Retrieve data
  
     $id = $_GET [ 'id' ];
     $id = mysql_real_escape_string( $id );
  
     $getid = "SELECT first_name, last_name FROM users WHERE user_id = $id" ;
  
     $result = mysql_query( $getid ) or die ( '
' 
            . mysql_error() .  
            '
' );
  
     $num = mysql_numrows( $result );

 

虽然$id经过了mysql_real_escape_string转义了’,可是因为后面的SQL语句$id没有单引号保护,会被系统认为是数值型,导致数值型注入

构造SQL注入语句

1 union select user,password from users

SQL语句就变成了

SELECT first_name, last_name FROM users WHERE user_id = 1 union select user,password from users 

SQL注入修补方法

字符型注入漏洞修补方法:

PHP5.3之前版本在php.ini中设置

magic_quotes_gpc=On; 

magic_quotes_quotes_gpc会对传入的$_POST,$_GET,$_SERVER里的 ‘,”,\进行转义。

但是PHP5.4之后,magic_quotes_quotes_gpc就被废除了。

还要使用mysql_real_escape_string()或addslashes()对传入参数进行过滤,或者使用str_replace()对一些关键词进行替换。

例:

 
?
1
2
3
4
5
6
7
8
9
10
if (isset( $_GET [ 'Submit' ])){
  
// Retrieve data
  
$id = addslashes ( $_GET [ 'id' ]);
  
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id'" ;
$result = mysql_query( $getid ) or die ( '
' 
            . mysql_error() .  
            '
' );
  
$num = mysql_numrows( $result );

 

修补后进行SQL注入

但是addslashes()和mysql_real_escape_string()在数据库字符集设为GBK时是可能被绕过的。

PHP字符编码绕过漏洞参考文 http://www.2cto.com/Article/201012/79778.html

如果数据库字符集是GBK的情况下,可以把

$mysqli->query('SET NAMES gbk'); 

修改为:

$mysqli->set_charset('gbk');

数值型注入:

数值型注入比较好修补,只需要判断传入的变量是否为数值型就可以了(或者强行改成字符型)

例:

 
?
1
2
3
4
5
6
7
8
$id = $_GET [ 'id' ];
$id = intval ( $id );
  
$getid = "SELECT first_name, last_name FROM users WHERE user_id = $id" ;
  
$result = mysql_query( $getid ) or die ( '
' 
            . mysql_error() .  
            '
' );
  
$num = mysql_numrows( $result );

 

修补后效果

XSS漏洞原理

黑客往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到黑客的特殊目的,比如窃取用户cookies.或者进行其他操作。 在

 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//low.php
if (isset( $_POST [ 'btnSign' ]))
{
  
    $message = trim( $_POST [ 'mtxMessage' ]);
    $name    = trim( $_POST [ 'txtName' ]);
  
    // Sanitize message input
    $message = stripslashes ( $message ); //stripslashes() 函数删除由 addslashes() 函数添加的反斜杠。
    $message = mysql_real_escape_string( $message ); //mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
  
    // Sanitize name input
    $name = mysql_real_escape_string( $name );
  
    $query = "INSERT INTO guestbook (comment,name) VALUES ('$message','$name');" ;
  
    $result = mysql_query( $query ) or die ( '
' 
            . mysql_error() .  
            '
' ); }
?>

 

从上面程序可以看出,$message,$name两个变量从$_POST传入,只是经过一些特殊字符的转换。并没有对尖括号进行转义,所以还是造成了XSS的产生。

直接插入XSS语句


 
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  
if (isset( $_POST [ 'btnSign' ]))
{
  
    $message = trim( $_POST [ 'mtxMessage' ]);
    $name    = trim( $_POST [ 'txtName' ]);
  
    // Sanitize message input
    $message = trim( strip_tags ( addslashes ( $message )));
    $message = mysql_real_escape_string( $message );
    $message = htmlspecialchars( $message );
  
    // Sanitize name input
    $name = str_replace ( '

你可能感兴趣的:(Web,security)