Web安全 学习日记6 - SQL注入 WAF绕过和防护方法

文章目录

    • SQL注入WAF绕过
        • 1、变换大小写
        • 2、16进制编码
        • 3、利用注释符
        • 4、重写
        • 5、比较操作符替换
        • 6、同功能函数替换
        • 7、二阶注入
        • 8、宽字节注入(%df')
    • SQL注入防护方法
        • 1、限制数据类型
        • 2、正则表达式匹配
        • 3、转义函数
        • 4、SQL语句预编译

SQL注入WAF绕过

1、变换大小写
  • WAF拦截了union,那就使用Union、UnloN等方式绕过
2、16进制编码
  • WAF检测敏感字’admin’,则可以用0x61646d696e代替
  • WAF检测敏感字select,可以在URL中将select变成%73elEcT结合大小写变换绕过WAF
  • 用%09、%0a、%0b、%Oc、%0d、%a0、/**/、/somewords/等来替换空格
3、利用注释符
  • 适用于WAF只过滤一次敏感字的情况,比如WAF只过滤一次union和select,则可以用/**/绕过:?id=1/union/union /select/select 1,2,3
4、重写
  • 适用于WAF只过滤一次敏感字的情况,比如WAF只过滤一次union,则可以写出类似ununionion这样的:?id=1 ununionion select 1,2,3
5、比较操作符替换
  • WAF过滤等号(=),可以用>和<来判断,比如要判断某个值是不是5,则可以判断是不是大于4,且小于6
  • WAF将=、>、<全部过滤,则可以利用like来绕过,如:?id=1’ or … like 1
  • WAF将=、>、<全部过滤,也可以用strcmp()函数绕过
6、同功能函数替换
  • 适用于某一函数被过滤的情况,如substring()被WAF过滤,可以用同功能的mid(),substr()等函数来替换,都是用来取字符串的某一位字符
7、二阶注入

简介: 指已存储(数据库、文件)的用户输入被读取后再次进入到 SQL 查询语句中导致的注入
补充: mysql_escape_string()函数,该函数和mysql_real_escape_string一样可以转移特殊字符,但不同的是经过mysql_escape_string处理的参数在存入数据库时会被还原成原来的数据
场景: 设想在登录页面username和password都经过了mysql_real_escape_string函数的转义,无法造成SQL注入。但注册页面使用的是mysql_escape_string函数,那么我们注册一个名为admin’#的用户,密码设为123456,登录该用户后,在修改密码页面修改密码为666666,这时admin’#的密码没有被修改,反而是admin的密码被修改了。
原理: 后端数据库执行的命令为,UPDATE users SET PASSWORD=‘666666’ where username=‘admin’#’ and password=‘123456’,等价于,UPDATE users SET PASSWORD=‘666666’ where username=‘admin’

8、宽字节注入(%df’)

前言:
- 当某字符的大小为一个字节时,称其字符为窄字节
- 当某字符的大小为两个字节时,称其字符为宽字节
- 所有英文默认占一个字节,汉字占两个字节
- 常见的宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS
原理: MySQL数据库编码与PHP编码不同导致,如MySQL数据库使用GBK编码而PHP编码为UTF8。MySQL认为两个字符是一个汉字(前一个字符ascii码要大于128,如%df),而当我们输入%df和单引号(%df’)时,MySQL会调用转义函数如addslashes,将单引号转义(添加 \ )后整个为 %df’ ,其中 \ 的十六进制是%5c,即 %df%5c’ ,而MySQL的GBK编码会认为%df%5c是一个汉字(運),而此时单引号仍然存在,可以实现闭合,从而造成SQL注入。
Web安全 学习日记6 - SQL注入 WAF绕过和防护方法_第1张图片
参考链接: 渗透测试-SQL注入之宽字节注入

SQL注入防护方法

1、限制数据类型
  • 比如使用函数 is_numeric() 判断为数字时才执行下一步,这样限制了字符从而也就限制了注入,但针对此函数可以16进制编码绕过
2、正则表达式匹配

比如这段PHP代码

$id=$_POST['id'];
if (preg_match('/and|select|insert|insert|update|[A-Za-z]|/d+:/i', $id)) { 
        die('stop hacking!'); 
    } else {
        echo 'good'; 
    }

3、转义函数
  • php自带的magic_quotes_gpc函数,不要对已经被 magic_quotes_gpc 转义过的字符串使用 addslashes(),因为这样会导致双层转义
  • addslashes、mysql_escape_string、mysql_real_escapse_string
4、SQL语句预编译
  • 防御SQL注入的最佳方式就是使用预编译SQL语句,绑定变量
  • 预编译相当于是将数据于代码分离的方式,把传入的参数绑定为一个变量,用?表示,攻击者无法改变SQL的结构

比如这段PHP代码

String query="select password from users where username='?' ";
$query="INSERT INTO myCity (Name,CountryCode,District) VALUES (?,?,?)";
$stmt=$mysqli->prepare($query);
$stmt->bind_param("sss",$val1,$val2,$val3);
$val1="Stuttgart";
$val2="DEU";
$val3="Baden";
//execute the statement
$stmt->execute();

即使攻击者插入类似 admin’ or 1=1# 的字符串,预编译会将传入的 admin’ or 1=1# 当做纯字符串的形式作为username执行,避免了类似sql语句拼接、闭合等非法操作

你可能感兴趣的:(Web安全,web安全,学习,sql)