起因:
最近在看《白帽子讲web安全》有关CRLF注入的一节。里面有个例子是这样的。(例子是.NET形式的)
日志将每个用户登陆的情况记录在日志中,正常情况下是这样的:
user login failed zhangsan;
user login failed lisi;
但是通过CRLF注入,如果用户名输入“wangwu;\n user login failed admin;”日志中将会出现:
user login failed wangwu;
user login failed admin;
这样就伪造了一条登陆记录。
于是我就着手模拟这一过程。
先写个模拟登陆的界面,html界面如下:
<?php
$fp = fopen("../log.txt",'a');
if(!$fp){
echo '文件不存在';
exit;
}
$username = $_POST['username'];
$username1 = "ooooooo\n";
echo strlen($username);//9
echo strlen($username1);//8
if($username != $username1){
echo "不相等";
}else{
echo "相等";
}
echo "$username"."log faild \n";
fwrite($fp,$username);
fclose($fp);
?>
在文本框里输入ooooooo\n登陆失败在web见中显示如下:
结果表明,在php环境下这种方式的CRLF注入不奏效。
在代码里我们可以看到直接在文本框里输入的字符串的长度是9,而在代码里定义的字符串长度是8,这说明文本框中的字符每个都被当作独立的字符。而代码里直接声明并在双引号里包含的字符会被当作一个个整体,因为php解析器对双引号里的进行匹配,如果里面有变量则替换有也会被当作chr(13)。
那么会不会是POST请求方式作用的结果呢?
查阅资料知道表单里的数据在此种请求方式下数据放在请求体里。抓包结果:
看到content-type字段后面值为x-www-form-urlencoded,这表明浏览器将表单里的数据以URLencode形式编码成键值对的字符串封装在请求体里发送给服务器。
总结
php以不可描述的方式将表单里的数据当作是独立的字符。其中深层系的原因留待有缘人来解答。