You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP密码重置页面遭滥用致批量发件,求漏洞排查与加固方案

密码重置表单安全漏洞排查与加固方案

一、现有代码中的安全漏洞

  • 输入校验缺失:未对login_var参数做严格格式验证,攻击者可提交任意内容;跳转URL直接拼接未转义的$login参数,存在XSS风险。
  • 无批量请求防护:未限制同一IP/邮箱的请求频率,自动化脚本可批量提交请求,引发邮件轰炸。
  • 错误处理不严谨:
    • mail函数前加@屏蔽错误,无法排查邮件发送异常;
    • header跳转后未执行exit()/die(),后续代码仍会运行,可能引发逻辑混乱;
    • 数据库操作(DELETE/INSERT)未严格判断执行结果,失败后仍继续流程,可能导致无效操作。
  • URL编码不规范:密码重置链接直接拼接$token,未做URL编码,不符合安全编码规范。
  • token无有效期:未给重置token设置过期时间,旧token长期有效,存在被滥用风险。

二、可能的攻击方式

  1. 邮件轰炸攻击:攻击者通过枚举网站注册用户邮箱(可通过表单错误提示?err=$login枚举存在的用户),用自动化脚本高频提交密码重置请求,利用服务器向目标邮箱发送大量重置邮件,导致域名被邮件服务商标记为垃圾邮件发送者,同时骚扰用户。
  2. XSS攻击:攻击者构造恶意login_var参数(如"><script>alert('xss')</script>),跳转后未转义的参数会在页面执行脚本,窃取用户会话或进行其他恶意操作。
  3. 潜在邮件头注入:若test_input函数未严格过滤换行符等特殊字符,攻击者可构造包含额外邮件头的输入,若后续逻辑疏漏,可能篡改邮件发件人或添加抄送地址,导致邮件被滥用。

三、安全加固方案

1. 输入输出安全处理

  • 严格校验输入格式:对login_var分场景验证:
    if(filter_var($login, FILTER_VALIDATE_EMAIL)){
        // 邮箱格式合法
    } else {
        // 用户名格式验证:限制长度1-20字符,仅允许字母、数字、下划线
        if(!preg_match('/^[a-zA-Z0-9_]{1,20}$/', $login)){
            header("location:forgot_password_page.php?invalid_input=1");
            exit();
        }
    }
    
  • 输出转义:跳转URL中的参数必须转义,避免XSS:
    header("location:forgot_password_page.php?err=".urlencode(htmlspecialchars($login)));
    exit();
    

2. 阻止批量请求

  • 添加速率限制:记录每个IP/邮箱的请求时间,限制1小时内最多5次请求:
    // 示例:用数据库记录请求日志
    $ip = $_SERVER['REMOTE_ADDR'];
    $check_query = "SELECT COUNT(*) FROM reset_requests WHERE ip=? AND created_at >= DATE_SUB(NOW(), INTERVAL 1 HOUR)";
    $stmt = $link->prepare($check_query);
    $stmt->bind_param("s", $ip);
    $stmt->execute();
    $count = $stmt->get_result()->fetch_row()[0];
    if($count >= 5){
        header("location:forgot_password_page.php?too_many_requests=1");
        exit();
    }
    // 记录本次请求
    $insert_query = "INSERT INTO reset_requests (ip, created_at) VALUES (?, NOW())";
    $stmt = $link->prepare($insert_query);
    $stmt->bind_param("s", $ip);
    $stmt->execute();
    
  • 添加人机验证:在表单中加入验证码(如reCAPTCHA),提交前验证用户身份,阻止自动化脚本。

3. 代码逻辑优化

  • 完善错误处理:
    • 移除mail函数前的@,保留错误信息并添加日志记录:
      if (mail($email, $subject, $msg, $headers,'-f'.$FromEmail)) {
          header("location:forgot_password_page.php?sent=1");
          exit();
      } else {
          error_log("Password reset email failed for: ".$email);
          header("location:forgot_password_page.php?servererr=1");
          exit();
      }
      
    • 所有header跳转后立即执行exit()/die(),终止后续代码执行;
    • 数据库操作严格判断执行结果:
      $sql = "DELETE FROM pass_reset WHERE email=?";
      if(!($stmt = mysqli_prepare($link, $sql))){
          header("location:forgot_password_page.php?db_err=1");
          exit();
      }
      mysqli_stmt_bind_param($stmt,"s", $email);
      if(!mysqli_stmt_execute($stmt)){
          header("location:forgot_password_page.php?db_err=1");
          exit();
      }
      
  • URL编码处理:对重置链接的token进行URL编码:
    $mlink = "https://mywebsite.de/password_reset_page.php?token=".urlencode($token);
    

4. 邮件发送安全升级

  • 使用PHPMailer/SwiftMailer替代原生mail函数,这类库自带邮件头过滤、身份验证功能,能有效防止邮件头注入,提升发送可靠性;
  • 配置SPF、DKIM、DMARC域名解析记录,验证邮件真实性,防止发件人被伪造,降低域名被标记为垃圾邮件的风险。

5. 密码重置token安全强化

  • 为token添加有效期,数据库新增expires_at字段:
    $expires_at = date("Y-m-d H:i:s", strtotime("+15 minutes"));
    $sql = "INSERT INTO pass_reset (email,token,expires_at) VALUES (?,?,?)";
    $stmt = mysqli_prepare($link, $sql);
    mysqli_stmt_bind_param($stmt,"sss", $email, $token, $expires_at);
    
  • 用户修改密码后,立即删除对应的pass_reset记录,避免token重复使用。

内容的提问来源于stack exchange,提问作者phil3450

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 19:36:32