简介《2021年全国职业院校技能大赛网络安全竞赛试题》是一份面向职业院校网络安全赛项选手、指导教师及安全运维初学者的赛题文档围绕竞赛常见任务组织内容可用于备赛训练、课堂实训与命题参考。压缩包共1个docx文件约119KB篇幅紧凑便于打印或对照环境逐项练习。文档覆盖Windows与Linux双平台的登录安全加固、密码与用户管理、MySQL数据库加固、HTTP到HTTPS重定向、事件审核监控以及SSH、VSFTPD、IIS服务加固和防火墙策略等任务并延伸至网络安全事件响应、数字取证调查与应用安全模块能帮助读者理解赛题要求、梳理加固思路并核对关键配置。该赛题已有959人学习适合需要系统刷题和查漏补缺的竞赛选手使用。1. 从一份赛题说起它更像一份能照着做的加固清单「网络安全 技能大赛」的题很多人只在赛前翻一遍就扔进网盘吃灰。我这次把一份 2021 年的赛题当成作业本重做发现它其实是一份结构相当完整的加固与应急清单A 模块六个任务横跨 Windows 和 Linux 两个平台从账户策略、数据库降权、Web 强制 HTTPS一路做到审计、服务加固和防火墙收口B 模块直接给一个失陷现场要求从内存、流量、端口三个入口倒推攻击链。适合谁刚接手上机整改清单、知道要改什么却不知道改到哪个文件的人也适合已经会敲命令但缺一套「改完怎么读回来验证」习惯的运维。下面按加固顺序往下走每一处都给可复制的配置、参数含义和失败时的观察点。2. 账户与登录面加固16 位密码、Banner 和 5 分钟超时落到哪账户和登录是攻击面里最靠前的一层也是整改单上最容易被写成「已按要求配置」却没人验证的一层。这一章把四项东西拆开密码最小长度、登录横幅、非活动会话超时、单个用户的登录时段与来源限制。它们分散在四五个文件或策略节点里Windows 和 Linux 的实现路径完全不同但考核点是一样的——不是「改过」而是「改完还能登录且策略真的拦得住」。2.1 密码策略Windows 本地安全策略与 login.defs 的双写Linux 侧的第一反应是/etc/login.defs题面也是这么写的把PASS_MIN_LEN改成 16。这一步没错但要清楚它管的是passwd、chpasswd这类工具在创建或修改口令时的长度校验走 PAM 的登录流程未必读它。真正在现代发行版上生效的是pam_pwquality也就是/etc/security/pwquality.conf里的minlen。两处都写才不会有「文件改了但用户仍能设 8 位密码」的尴尬。# 先备份改配置文件永远留一份原件 cp /etc/login.defs /etc/login.defs.bak # 匹配行首的 PASS_MIN_LEN如果这行被注释掉sed 不会命中要先 grep 确认 sed -i s/^PASS_MIN_LEN.*/PASS_MIN_LEN\t16/ /etc/login.defs grep -E ^PASS_MIN_LEN /etc/login.defs # PAM 层同步收紧minlen 才是 passwd 真正读的默认值 sed -i s/^# *minlen.*/minlen 16/ /etc/security/pwquality.conf grep -E ^minlen /etc/security/pwquality.confsed那条里\t是制表符login.defs用空白分隔字段写成空格也能解析但保持制表符更贴近原文件风格。第二段的# *minlen是为了兼容默认文件里# minlen 8这种带注释的写法不同发行版注释后有没有空格不一致# *两种都能匹配。改完不要立刻登出开一个新终端试一次改密码能设 15 位被拒、16 位通过这条才算落地。Windows 侧有图形路径管理工具 → 本地安全策略 → 账户策略 → 密码策略 → 最小密码长度。命令行等价物是net accounts但这里有个版本边界要先说清楚net accounts /minpwlen:在部分系统上上限是 14想设 16 会直接报参数错误而图形界面和组策略可以设到更高。所以命令行改不动不是命令写错了是接口本身的限制。:: 先看当前值确认改的是本地 SAM 而不是域策略 net accounts :: 最小长度 16若报“参数无效”改用 secpol.msc 图形界面或组策略 net accounts /minpwlen:16 :: 顺带把最长使用期和密码历史一起收紧单改长度意义有限 net accounts /maxpwage:90 /uniquepw:5net accounts的改动只作用于本机 SAM 数据库域环境里成员机真正生效的是「默认域策略」里那条同名项本地改了也会被域策略覆盖。所以复现赛题时先确认机器是不是加域状态没加域才有意义。/maxpwage单位是天/uniquepw是记住多少个历史密码这两个参数题面没要求但实际整改里几乎总是一起出现顺手带上不吃亏。2.2 登录横幅issue、sshd Banner 和交互式登录消息横幅看着是个形式主义的需求其实是合规检查里最容易被抽查的一条登录前后必须出现「仅限授权用户」的提示。Linux 上有两个不同的位置本地控制台和远程 SSH 各管各的很多人只改了一个就交差。# 本地 tty 在 getty 登录提示前打印注意这里不要用反斜杠开头的转义 cat /etc/issue EOF For authorized users only EOF # SSH 横幅单独一个文件权限要求 root 可读、其他用户不可写 cat /etc/ssh/banner EOF For authorized users only EOF chmod 644 /etc/ssh/banner # sshd_config 里 Banner 默认是注释状态sed 兼容有井号和无井号两种写法 sed -i s|^#\?Banner.*|Banner /etc/ssh/banner| /etc/ssh/sshd_config sshd -t systemctl reload sshdsshd -t是语法自检配置写错时它会给出行号比直接 reload 后连不上再回头找要省事得多。这里用reload不用restart是为了不打断已经建立的会话。文件权限那条别省sshd在StrictModes yes默认值下会检查横幅文件的属主和写权限如果文件对 other 可写横幅会被静默忽略日志里只留一行不太好找的警告。/etc/issue里的\n、\r、\m会被 getty 展开成系统信息写欢迎语时避开反斜杠开头否则会出现莫名其妙的换行或主机名。Windows 侧对应的是「交互式登录试图登录的用户的消息标题」和「消息文本」两条策略在本地安全策略 → 本地策略 → 安全选项里。图形界面之外直接写注册表更快而且立刻生效、不用重启# 这两条注册表项就是 secpol 里那两条策略的落点 $path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System New-ItemProperty -Path $path -Name LegalNoticeCaption -Value For authorized users only -PropertyType String -Force New-ItemProperty -Path $path -Name LegalNoticeText -Value For authorized users only -PropertyType String -Force-Force的作用是值已存在时覆盖不加会报「属性已存在」。标题和正文是两条独立的项题面要求出现「For authorized users only」这句提示写在标题或正文里都能显示但截图时只截标题栏往往看不出内容稳妥做法是两条都填。这条策略对远程桌面同样生效所以 RDP 登录前也会弹一次。2.3 会话超时ClientAliveInterval 的乘法题与 RDP-Tcp 的三档时间「非活动会话连接超时应小于等于 5 分钟」这句在两地实现差异最大。Linux 的 SSH 不是靠一个参数而是两个参数相乘ClientAliveInterval是探活间隔ClientAliveCountMax是连续多少次没响应就断开实际超时 间隔 × 次数。题面只提了这两个参数名没说取值这里就是最容易算错的地方。# 300 秒探活一次1 次无响应即断开合计 300 秒满足“小于等于 5 分钟” sed -i s|^#\?ClientAliveInterval.*|ClientAliveInterval 300| /etc/ssh/sshd_config sed -i s|^#\?ClientAliveCountMax.*|ClientAliveCountMax 1| /etc/ssh/sshd_config sshd -t systemctl reload sshd # 复核实际生效值sshd -T 会打印合并后的配置 sshd -T | grep -i clientaliveClientAliveCountMax设成 0 的含义是「一次间隔后直接断开」不是「不断开」语义上和很多人直觉相反。用 300 × 1 是最好解释的组合如果想更细60 × 5 也是 5 分钟但探活频率高了会多出一些无谓流量。sshd -T这个命令值得记住它输出的是 sshd 真正加载后的完整配置比翻文件可靠也能顺手验证PermitRootLogin、Port有没有改对。Windows 的 RDP 超时在「远程桌面会话主机设置」里对应 RDP-Tcp 连接属性的「会话」页三档活动会话时间限制、活动但空闲的会话时间限制、断开的会话时间限制。题面要求的是非活动超时盯的是第二档。注册表里对应MaxIdleTime和MaxDisconnectionTime单位是毫秒$rdp HKLM:\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp # 5 分钟 300000 毫秒 Set-ItemProperty -Path $rdp -Name MaxIdleTime -Value 300000 Set-ItemProperty -Path $rdp -Name MaxDisconnectionTime -Value 300000 Get-ItemProperty -Path $rdp | Select-Object MaxIdleTime, MaxDisconnectionTime两个值的含义不同MaxIdleTime是会话空闲到点直接断开MaxDisconnectionTime是网络断了以后保留会话让用户还能接回来的时长。整改单上通常两条都要设只设前者的话拔网线的那种「断连」场景不会在 5 分钟内清掉。改注册表后需要重启远程桌面服务或者重启系统才完全生效这一点和 SSH 的 reload 不一样。2.4 user1 的登录时段与「从网络访问此计算机」白名单题面里user1只能在周一至周五 9:00 到 18:00 登录命令行的写法很紧凑但格式错一个字符就会静默失败或者报语法错误。:: M周一 F周五24 小时制逗号分隔时段不要加空格 net user user1 /time:M-F,9:00-18:00 :: 复核输出里会有一行 Logon hours allowed net user user1/time:后面如果留空效果是清空所有限制、允许全天登录所以这条命令误操作的方向是「放开」而不是「收紧」执行前务必确认。图形界面上「登录时间」的最小单位是小时命令行填到分钟在界面上会显示成整点区间赛题要求截图本质就是让你证明在界面上能看到这段时间被涂蓝。域用户走的是账户属性 → 帐户 → 登录时间路径不同但语义一致。「只允许管理员账号从网络访问本机」这条在组策略里计算机配置 → Windows 设置 → 安全设置 → 本地策略 → 用户权限分配 → 从网络访问此计算机。默认包含Everyone、Users、Power Users等要全部删掉只留Administrators。这里有个连带影响如果这台机器上跑着 IIS应用程序池用的是普通账户删掉Users之后站点访问共享目录或走网络身份验证会直接 401 或 500。常见做法是先确认机器上有没有依赖网络登录的服务账户有的话单独加回那一个而不是把Users整组放回去。3. 数据库与 Web 传输MySQL 降权与 IIS 强制 HTTPS中间层的加固比系统层更容易出「配了但没生效」的问题因为涉及服务和配置文件两套加载顺序。这一章处理 MySQL 的运行账户、默认库与管理账号、口令哈希、最小权限授权以及 IIS 上把 80 端口的流量钉到 443 的那条重写规则。数据库部分能直接跑 SQLWeb 部分落到web.config。3.1 用普通账户跑 mysqlduser 参数、目录属主与启动链「禁止 mysql 以管理员权限运行」这句话落到实现上就是让mysqld进程的属主不是 root。my.cnf的[mysqld]段里user这一项作用是当服务以 root 启动时进程降权到指定用户。注意它的前提是「以 root 启动」如果 systemd 单元里已经写了Usermysql那进程压根不会以 root 起来my.cnf里的user就是个冗余但无害的保险。# 确认 [mysqld] 段存在再把 usermysql 插到它后面一行 grep -n ^\[mysqld\] /etc/my.cnf sed -i /^\[mysqld\]/a usermysql /etc/my.cnf # 数据目录属主必须跟着是 mysql否则重启直接失败 chown -R mysql:mysql /var/lib/mysql systemctl restart mysqld # 验证进程属主第一列是 mysql 才算降权成功 ps -o user,pid,cmd -C mysqldps -o user这一列是最直接的证据比看配置文件有说服力。sed的/a是追加到匹配行之后如果my.cnf里已经有user跑两次会出现重复项MySQL 对重复参数的处理是后者覆盖前者不至于启动失败但配置文件会越来越脏跑之前grep ^user /etc/my.cnf看一眼更稳。chown那步不能省尤其是从别处拷过来的数据目录属主不对时错误日志里给的是权限拒绝不会直接告诉你是属主问题。3.2 删 test 库、把管理员改名DROP 与 RENAME USER 的差别删默认库没什么争议DROP DATABASE IF EXISTS test;就够IF EXISTS是为了让脚本可重复执行。改管理员用户名这一步题面给的是update user set userSuperRoot where userroot;这条在 MySQL 5.x 上能跑通在 8.x 上则要面对权限表结构变化和一堆连带问题。更稳的写法是RENAME USER它会把权限行、主键、索引一起搬过去。-- 删之前先看有没有业务库挂在 test 名下 SHOW DATABASES; DROP DATABASE IF EXISTS test; -- 改名用专门语句别直接 UPDATE mysql.user RENAME USER rootlocalhost TO SuperRootlocalhost; FLUSH PRIVILEGES; -- 复核原来的 rootlocalhost 应该消失 SELECT user, host FROM mysql.user ORDER BY user;RENAME USER的语法要求用户名和主机部分都写全只写SuperRoot会报错。这里还有个高频遗漏mysql.user里往往同时存在rootlocalhost、root127.0.0.1、root::1三条记录题面只说改管理员用户只改localhost那条的话用 IP 连进来仍然是 root。整改时按SELECT user,host FROM mysql.user WHERE userroot;把结果全改一遍或者干脆确认业务只走 socket 连接。FLUSH PRIVILEGES在RENAME USER之后其实不是必须的权限表由语句本身维护但在直接 UPDATE 权限表的场景下必须执行养成习惯没坏处。3.3 密码那一行MD5()、PASSWORD() 与 authentication_string题面写的是Update user set passwordmd5(password) where useruser1;这条语句的语义是「把 password 字段的现有值再做一次 MD5」而不是「把明文 Pssw0rd1! 做 MD5 写进去」。照抄的结果是得到一个谁也不知道原文的哈希用户直接登不上。正确的意图是把明文口令哈希后写入认证字段。-- 5.7 及更早字段名叫 password UPDATE mysql.user SET password MD5(Pssw0rd1!) WHERE user user1 AND host localhost; -- 8.0字段改名为 authentication_string且默认插件不再是 mysql_native_password UPDATE mysql.user SET authentication_string MD5(Pssw0rd1!) WHERE user user1 AND host localhost; FLUSH PRIVILEGES;字段名这块要先DESC mysql.user;看一眼再动手两个版本的列名不一样写错列名报的是「Unknown column」比较好排查麻烦的是写对了列但插件不对——MySQL 8 默认caching_sha2_password直接塞一个 32 位十六进制的 MD5 进去认证阶段会失败因为长度和格式都不匹配。赛题环境一般是 5.x按老写法来真实环境里 MD5 存口令本身已经是应该淘汰的做法用ALTER USER ... IDENTIFIED BY让服务端自己算哈希才是现在的常规操作。这里把边界说清楚比背一条 SQL 有用。3.4 最小权限授权与 IIS 的 HTTP 到 HTTPS 强制跳转授权这条题面写得很清楚user1对testdb所有表只有增删改查。落地就一句GRANT但顺序有讲究——GRANT在用户不存在时会顺手创建用户而且创建出来的是空密码账户。-- 先建用户设密码再授权避免 GRANT 隐式创建空密码账户 CREATE USER IF NOT EXISTS user1localhost IDENTIFIED BY Pssw0rd1!; GRANT SELECT, INSERT, UPDATE, DELETE ON testdb.* TO user1localhost; FLUSH PRIVILEGES; -- 复核应当只有 USAGE 加四条 DML没有 DDL、没有 GRANT OPTION SHOW GRANTS FOR user1localhost;testdb.*是库级授权表级写成testdb.表名。SHOW GRANTS的输出是唯一可信的验证方式USAGE那行表示「能连但没权限」是正常现象。注意别顺手加上WITH GRANT OPTION那等于把授权能力也给了业务账户最小权限就破了。IIS 那边的目标是 80 进来的请求全部 301 到 443做法是在站点根目录放一条 URL Rewrite 规则。前提有两个服务器装了 URL Rewrite 模块站点已经绑好 443 和证书。configuration system.webServer rewrite rules rule nameForce HTTPS stopProcessingtrue match url(.*) / conditions !-- 只在明文请求时跳避免 443 上再跳一次形成循环 -- add input{HTTPS} pattern^OFF$ / /conditions action typeRedirect urlhttps://{HTTP_HOST}/{R:1} redirectTypePermanent / /rule /rules /rewrite /system.webServer /configurationredirectTypePermanent是 301浏览器会缓存调试阶段建议先用Found302确认没问题再换 301否则改错了要清浏览器缓存才能看到效果这个坑我踩过不止一次。{R:1}是正则里第一个捕获组也就是路径部分写成{URL}会丢掉查询串之外的一些细节。条件判断放在conditions里而不是写进match是这条规则能不能避免循环重定向的关键。4. 审计、服务与防火墙把该记的记下来把该关的关掉这一章的三个部分彼此独立但顺序有讲究先开审计才有日志可查再加固服务改动才留痕最后收防火墙避免前面改端口时把自己关在门外。顺序反了排查时你连「谁在什么时候改的」都找不到。4.1 审核策略四类子类别和它们在事件查看器里的落点题面要求开四类登录事件成功/失败、特权使用成功、策略更改成功/失败、进程跟踪成功/失败。图形路径是组策略里的「审核策略」命令行用auditpol更快但中文系统上子类别的名字是中文直接照英文写会报「找不到子类别」。:: 先列出本机实际的子类别名称中文系统上是中文 auditpol /get /category:* :: 按题面四类逐条开子类别名以实际输出为准 auditpol /set /subcategory:Logon /success:enable /failure:enable auditpol /set /subcategory:Privilege Use /success:enable auditpol /set /subcategory:Policy Change /success:enable /failure:enable auditpol /set /subcategory:Process Tracking /success:enable /failure:enable :: 复核 auditpol /get /category:*事件落点要心里有数登录成功 4624、失败 4625特权使用 4672策略更改 4739进程创建 4688。Process Tracking这一类默认只记进程启动不带命令行需要在「审核进程创建」里额外打开「包括命令行」才有完整参数。这类事件量很大磁盘和日志滚动策略要提前规划否则一两天就把安全日志撑满反而把关键事件挤掉。改完策略不用重启但审计策略属于「计算机配置」域环境下会被域策略覆盖本地测试要确认没加域。4.2 SSH端口 2222 与 PermitRootLogin 的两处连带改动改 SSH 端口这件事配置文件只是第一步真正让人连不上的是后面两道门SELinux 和防火墙。cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak sed -i s/^#\?Port .*/Port 2222/ /etc/ssh/sshd_config sed -i s/^#\?PermitRootLogin .*/PermitRootLogin no/ /etc/ssh/sshd_config # 语法自检出错会给行号 sshd -t systemctl restart sshd # SELinux 放行新端口不加这条服务起来但连接被拒 semanage port -a -t ssh_port_t -p tcp 2222 # 防火墙放行 firewall-cmd --permanent --add-port2222/tcp firewall-cmd --reload # 验证端口在听、横幅能出来 ss -lntp | grep 2222 ssh -p 2222 -o BatchModeyes 127.0.0.1 true 21 | head -3semanage port -a在端口已存在时会报错改已有条目用-m。ss -lntp能看到 2222 在监听说明 sshd 起来了此时从外部连不上问题一定在 SELinux 或防火墙这两处是独立的门缺一个就是「服务正常但连不上」。PermitRootLogin no生效后用 root 直接连会被拒得先用普通用户登录再su或sudo测试时别把自己锁在外面——这也是为什么先开一个新终端验证、再关旧终端。sshd -T能打印合并后的最终配置比翻文件可靠。4.3 VSFTPD匿名开关与那一族 timeout 参数anonymous_enableNO是最基本的一条但只改这一条匿名用户在某些配置下仍然能上传因为anon_upload_enable是独立开关。超时这块题目给了一组参数其中idle_session_timeout600和「无任何操作超时 5 分钟」是对不上的——600 秒是 10 分钟。CONF/etc/vsftpd/vsftpd.conf # 匿名相关三条一起关 sed -i s/^anonymous_enable.*/anonymous_enableNO/ $CONF sed -i s/^#\?anon_upload_enable.*/anon_upload_enableNO/ $CONF sed -i s/^#\?anon_mkdir_write_enable.*/anon_mkdir_write_enableNO/ $CONF # 无操作超时按 5 分钟写 300 秒先删旧值再加避免重复项 sed -i /^idle_session_timeout/d $CONF echo idle_session_timeout300 $CONF echo data_connection_timeout300 $CONF systemctl restart vsftpd grep -E anonymous|timeout $CONF参数含义要分清idle_session_timeout是控制连接上多久没敲命令就踢data_connection_timeout是数据传输连接多久没数据就断connect_timeout和accept_timeout分别是主动模式和被动模式下建立连接的超时。题面把这几个并列写出来考核点其实是「知道哪个对应无操作」。另外不同发行版的配置文件路径不一样有的在/etc/vsftpd.conf有的在/etc/vsftpd/vsftpd.conf改之前rpm -qc vsftpd或dpkg -L vsftpd | grep conf确认一下别改了个没被加载的文件。4.4 IIS 日志字段与最大并发连接数IIS 日志要求 W3C 格式只记录日期、时间、客户端 IP、用户名、方法五项。图形路径是网站 → 日志 → 选择字段命令行用WebAdministration模块。Import-Module WebAdministration $site IIS:\Sites\Default Web Site # W3C 格式 Set-ItemProperty $site -Name logFile.format -Value W3C # 字段用 W3C 内部名不是界面上的中文 Set-ItemProperty $site -Name logFile.fields -Value Date,Time,c-ip,cs-username,cs-method # 最大并发连接数 1000 Set-ItemProperty $site -Name limits.maxconnections -Value 1000 # 复核 Get-ItemProperty $site | Select-Object logFile, limitslogFile.fields的取值是 W3C 规范的内部字段名写「日期」「时间」会直接报错这一点在只有中文界面的环境里很容易卡住。limits.maxconnections就是高级设置里「限制」下的「最大并发连接数」设太小会直接 503设 1000 是题面要求实际生产要看压测结果。日志字段砍到五项之后排查时就没有sc-status和time-taken了这是按题面要求做的取舍真实环境建议至少保留状态码。4.5 iptables23 端口、禁 ping 与 SSH 白名单的顺序问题防火墙这块题面给了一条iptables -A INPUT -p tcp --dport 23 -j DROP这条本身没错。问题出在第 18 条要求「禁止所有人通过 SSH 连接除了 172.16.1.1」题面给的命令只有一条 ACCEPT没有配套的 DROP照抄等于什么都没限制。# 禁用 23 端口telnet iptables -A INPUT -p tcp --dport 23 -j DROP # 禁 ping只挡 echo requesttype 8不影响本机 ping 出去 iptables -A INPUT -p icmp --icmp-type 8 -j DROP # SSH 白名单ACCEPT 必须在 DROP 之前顺序反了白名单也进不来 iptables -A INPUT -s 172.16.1.1 -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --dport 22 -j DROP # 落盘否则重启后规则全丢 iptables-save /etc/sysconfig/iptables iptables -S | grep -E dport (22|23)|icmpiptables 是按顺序逐条匹配命中即执行目标动作所以-A追加到链尾的顺序就是执行顺序ACCEPT 写在 DROP 后面等于白写。--icmp-type 8是 echo request只挡别人 ping 你你自己 ping 外面不受影响想彻底关掉 ICMP 应答也可以走 sysctl# 临时生效重启失效 echo 0 /proc/sys/net/ipv4/icmp_echo_ignore_all # 永久生效0 是允许 ping1 才是禁止写反了就是“改了没用”的经典现场 echo net.ipv4.icmp_echo_ignore_all 1 /etc/sysctl.conf sysctl -p cat /proc/sys/net/ipv4/icmp_echo_ignore_allsysctl -p是从文件重新加载不执行这一步/etc/sysctl.conf改了也不会立刻生效这是禁 ping 失败最常见的原因之一。另外icmp_echo_ignore_all和 iptables 的 ICMP 规则是两套机制同时开着不冲突但排查时要分清到底是哪一层在挡。5. 避坑与排查五个「明明改了却没生效」的现场这一章按现象写每条都能对上前面某一节。加固类任务最耗时间的从来不是改而是改完不确定有没有生效本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?