【PHP代码审计】SQL注入漏洞


欢迎新同学的光临
… …
人若无名,便可专心练剑


我不是一条咸鱼,而是一条死鱼啊!


前言

SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据,致使非法数据侵入系统。 SQL注入的产生,是因为代码或者编码的不完善。代码的不完善往往是因为程序编写过程中没有考虑到代码的健壮性及安全性。而编码的不完善问题,只要通过规范使用几种函数就可以有效避免。介于代码和编码是两种不同层面的问题,我们将SQL注入也分为两大类:

  • 普通SQL注入:最为常见的sql注入,由于未对用户输入进行过滤或过滤不严而产生的漏洞,分为整数型和字符型注入,通常直接通过union联合查询就可以进行数据库查询。

  • 编码SQL注入:为了防御SQL注入,某些应用会对用户输入进行编码,但编码处理的函数本身也存在一些问题,导致可以通过输入一些编码函数不兼容的特殊字符,将输出字符变为危险数据,最常见的就是Mysql宽字节注入。

宽字节注入

宽字节注入原理

虽然现在呼吁所有的程序都使用unicode编码,所有的网站都使用utf-8编码,实现统一的国际规范,但仍然有很多网站仍然使用着自己国家的一套编码(比如gbk),作为自己默认的编码类型。 为了防御普通的Sql注入,有些网站会开启magic_quotes_gpc或者使用addslashes、mysql_real_escape_string等函数对用户输入进行过滤时,这时候输入参数中存在的单引号,就会被强制添加\(转义符)而转移转义。这种方式确实可以一定程度上的防御 Sql注入,但是如果数据库恰好使用的是 GB2312、GBK、GB18030 等宽字节的编码,就会造成宽字节注入。

宽字节注入实例

代码如下:

<?php
    # 打开非持久的 MySQL 连接
    $conn=mysql_connect('localhost','root','');
    # 函数设置活动的 MySQL 数据库。
    # 如果成功,则该函数返回 true。如果失败,则返回 false
    # 设置连接数据库,且指定数据默认数据库
    mysql_select_db("CA_sql",$conn);
    
    # mysqli_query() 函数执行某个针对数据库的查询
    mysql_query("SET NAMES 'GBK'",$conn);

    # addslashes() 函数返回在预定义字符之前添加反斜杠的字符串
    $uid = addslashes($_GET['id']);
    $sql = "SELECT * FROM books where tid='$uid'";

    # mysqli_query() 函数执行某个针对数据库的查询
    $result = mysql_query($sql,$conn);
    print_r('SQL:'.$sql.'<br />');
    
    # mysql_fetch_row() 函数从结果集中取得一行作为数字数组
    print_r(mysql_fetch_row($result));

    # mysql_close() 函数关闭非持久的 MySQL 连接
    mysql_close();
?>

登录访问宽字节注入实例页面成功

在这里插入图片描述
输入?id=1回显正常:

在这里插入图片描述

输入 ?id=1’也没有报错,可以看到是因为对’做了转义,变成了’:

在这里插入图片描述
输入id=-1’ union select database(),user(),version()%23是没法成功注入的,因为单引号闭合后union后面的语句不会执行。(使用-1而不是1是因为有时候sql查询回显是有长度限制的,使用-1查不到任何数据,才能回显union后面的查询结果):

在这里插入图片描述
我们知道mysql会将\编码为%5c,所以我们考虑能否在前面再加上%df,组合成了%df%5c,这不就恰好对应编码中的運字吗?答案是可以的!宽字节中两个字节代表一个汉字,所以%df和后面的\也就是%5c变成了一个汉字“運”,使用这种方法成功绕过转义,就是所谓的宽字节注入。

[注释]:<其实不光可以用%df,只要第一个字节ascii码大于128,基本上就可以了。比如我们不用%df,用%a1也可以:> 输入id=-1%df’ union select database(),user(),version()%23(%23对应#):如上图,查询成功

在这里插入图片描述
如上图,查询成功

宽字节注入防御

对于宽字节注入,有如下几种防御方式:

  • 使用mysql_set_charset函数设置连接所使用的字符集,再调用mysql_real_escape_string来过滤用户输入。

  • 将character_set_client设置为binary(二进制)

  • 使用参数化查询、pdo查询

参考链接:https://www.shiyanlou.com/courses/895


我自横刀向天笑,去留肝胆两昆仑


猜你喜欢

转载自blog.csdn.net/Ananas_Orangey/article/details/120549055