初级:
if (($pass_new == $pass_conf)){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);
将特殊字符转义,然后进行MD5加密,然后更新数据库;
这段代码直接将新密码写进数据库,没有验证用户的旧密码,也没有对http引用进行确认,这样任何别的网站都可以用你cookies对你的帐户进行CSRF攻击。
绕过:直接更新新密码;低级别,无需输入原密码【伪造页面和链接,诱使受害者点击;注:GET方法:将会在页面有明显显示;POST方法:将可隐藏操作
GET:伪造http头部信息,加上?pass_new=111&pass_conf=111&change=change;让用户点击;
POST:查看网页源代码,直接修改表单的代码,保存成页面文件,诱使用户点击【使用burpsuite截断重放,保存成html文件,伪造链接,发给受害者
在Burpsuite中有一个用于实现检测CSRF漏洞的功能,在对Request包右键>Engagement tools>Generate CSRF PoC,其会自动生成一个HTML文件:
中级:
在获取新的密码和确认密码前,增加一个语句:
if ( eregi ( "127.0.0.1", $_SERVER['HTTP_REFERER'] ) ){ ,我的理解就是正则表达式网站跳转来源是否是这个IP,只有从这个IP跳转才可以;
对http引用进行确认,然后再写数据库。
- HTTP REFERER的作用告诉服务器我是从哪个页面链接过来的。
- 而eregi的作用就是对两个字符串比对匹配,匹配成功就返回true
- 这里就表示我是从服务器本地发来的http包
绕过: 截获我们本地浏览器的http请求包,然后将referer部分改成 127.0.0.1 这样就可以成功突破 实现CSRF。
高级:
对旧密码进行确认,确认后才更新新密码;
// Sanitise current password input
$pass_curr = stripslashes( $pass_curr ); 去除反斜线
$pass_curr = mysql_real_escape_string( $pass_curr ); 转义特殊字符
$pass_curr = md5( $pass_curr ); 加密;
// Check that the current password is correct
$qry = "SELECT password FROM `users` WHERE user='admin' AND password='$pass_curr';";
$result = mysql_query($qry) or die('<pre>' . mysql_error() . '</pre>' );
因为增加了确认的机制,所以如果攻击者不知道用户当前密码是没有办法进行CSRF攻击的,即几乎是不存在CSRF漏洞了。
自动扫描程序的检测方法【代码安全,确认机制角度】
在请求和响应过程中检查是否存在anti-CSRF token名
检查服务器是否验证anti-CSRF token的名值
检查token中可编辑的字符串
检查referrer头是否可以伪造
对策
Captcha
Referrer头 【可绕过机率较大】
降低会话超时时间
if (($pass_new == $pass_conf) && ( $result && mysql_num_rows( $result ) == 1 )){
$pass_new = mysql_real_escape_string($pass_new);
$pass_new = md5($pass_new);