注入型隐患
通过插入引号或分隔符等用于表示“数据部分边界”的字符,从而改变文本的结构。
隐患名 | 接口 | 恶意手段 | 数据部分边界 |
---|---|---|---|
跨站脚本 | HTML | 注入JavaScript | <"等 |
HTTP消息头注入 | HTTP | 注入HTTP响应消息头 | 换行符 |
SQL注入 | SQL | 注入SQL命令 | ‘等 |
OS命令注入 | Shell脚本 | 注入系统命令 | ;|等 |
邮件头注入 | sendmail命令 | 注入或更改邮件头或正文 | 换行符 |
输入处理
输入处理指对输入值作如下处理
1.检验字符编码的有效性
2.必要时转换字符编码
3.检验参数字符串的有效性
检验字符编码
PHP中用mb_check_encoding函数检验字符编码
bool mb_check_encoding(string $var, string $encoding)
第一个参数$var是检验对象字符串,第二个参数$encoding是字符编码,可以省略,省略时使用PHP内服字符编码,如果$var字符串编码正确则函数返回ture。
转换字符编码
PHP中自动转换是通过设置php.ini文件,手动设置是使用mb_convert_encoding手动转换字符编码。
string mb_convert_coding(string $str, string $to_encoding, string $from_encoding)
参数分别是:转换前的字符串,转换后的字符编码,转换前的字符编码。
输入校验
空字节攻击
例用正则表达式ereg检验变量$p的之中仅包含数字
if (ereg ( '^[0-9] + $ ' , $p))=== FALSE){
die (' 请输入整数值 ‘’) ;
}
输入php?=1%00<script>alert('XSS')</script>,则弹出对话框,说明ereg被绕过。
因为%00就是空字节,被视作字符串的结束。由于%00字符串被忽略,检验对象字符串就是“1”,满足“仅限数字”的要求。Javascript被执行。
在应用程序的入口处使用二进制安全的函数检验输入值中是否有空字节,如果含有空字节就报错。
仅检验输入值并不是安全性策略,输入校验是根据应用程序的软件规格而实施的操作,例如,假设规格书中规定允许输入任何字符,那么在输入阶段就无法进行任何安全性防范措施。
在允许输入任何字符情况下,就需要
校验控制字符。指换行符(CR和LF),Tab(通常不显示在页面上),ASCII编码中0x20以下以及0x7F(DELETE)的字符,空字节也是控制字符。
校验字符数,定义所有输入项目的最大字符数,假设限制字符数最大长度为10的话,即使攻击者发现SQL注入隐患时也无法实施攻击。
正则表达式
使用preg_match
if (preg_match ( ' / \ A [ a - z 0 - 9 ] { 1, 5 } ] \ z / ui ' , $p ) == 0 ) {
die ( ' 请输入1-5个字符长度的字母或数字 ' )
}
' / 正则表达式的开始
\ A 字符串的开头
[ a - z 0 - 9 ] 匹配字母和数字
{ 1, 5 } 1 ~ 5个字符
\ z 字符串的结尾
u 在中文环境使用preg_match函数时,无论检验对象是否含有中文,都必须指定表示字符编码为UTF-8的u修饰符。
i 表示匹配时不区分大小写
\ A 和 \ z 有时会被 ^ 和 $替代,$会匹配换行符,所以当它们被用于匹配数据开头和结尾是可能产生bug。
使用mb_ereg
mb_regex_encoding ( ' UTF-8 ' ) ;//只要在程序开头设置一次即可。
作用为指定mb_ereg函数的字符编码。如果php.ini已经设置了内部字符编码,此步骤可以忽略。
mb_ereg与preg_match不同之处有3点:ereg的表达式不用 / 括起来;不适用u修饰符;没找到匹配时返回false,不是0,由于ereg返回值为整数或布尔型,ereg用===,match用==
当输入值为住址等字符数较长的值时,应当检查是否有控制字符混入。可以使用POSIX字符集合[ [ : ^ cntrl : ] ]来表示“非控制字符的字符”。