加固脚本编写教程|零基础入门到精通|网站安全防护实用指南|避坑技巧全解析

加固脚本编写教程|零基础入门到精通|网站安全防护实用指南|避坑技巧全解析 一

文章目录CloseOpen

从0到1学写加固脚本:基础语法+实战案例

先搞懂:为什么加固脚本是网站安全的”防盗门”

你可能会说:”我用了云服务商的WAF,还需要自己写脚本吗?”其实WAF就像小区大门的保安,能挡住大部分陌生人,但家里的门窗有没有锁好、抽屉有没有放贵重物品,还得自己操心。加固脚本就是干这个的——它能帮你自动检查”门窗是否锁好”(比如敏感文件是否存在)、”抽屉是否关好”(权限配置是否合理)、”有没有陌生人留的钥匙”(后门文件)。

去年给小李写脚本前,我先让他列了5个最担心的安全问题:敏感文件泄露、权限过高、日志没备份、密码太简单、端口开放过多。这其实也是大多数中小网站的通病。后来脚本写完跑起来,第一次就扫出了8个问题:3个暴露的.env配置文件、2个权限设为777的目录、还有3个弱密码账户。你看,这些问题人工检查可能一周都发现不了,但脚本3分钟就搞定了。

零基础也能懂的脚本基础:就像学搭积木,先认识零件

写脚本不用从头学编程,咱们用最常用的Shell脚本(Linux系统自带,不用额外装软件),核心就3个基础零件,我一个个给你讲明白:

第一个零件:变量——给数据贴”姓名贴”

变量就像给盒子贴姓名贴,盒子里放数据,以后想拿数据,喊姓名贴就行。比如你想扫描网站根目录,不用每次都写一长串路径”/var/www/html”,可以定义一个变量:

web_root="/var/www/html" # 定义变量:姓名贴是web_root,盒子里放路径

echo "正在扫描:$web_root" # 用$符号喊姓名贴,就能取出路径

我刚开始学的时候,总犯两个错:一是变量赋值时等号两边加空格(正确的是web_root="/var/www/html",不是web_root = "/var/www/html"),二是用变量时忘了加$符号。后来发现个好工具:ShellCheck[nofollow],把脚本粘贴进去,它会像老师批改作业一样标红错误,比如提醒你”等号两边不能有空格”,新手必备。

第二个零件:循环——让脚本”重复干活不偷懒”

假设你要检查10个敏感文件名(比如phpinfo.php、backup.sql),总不能写10遍检查代码吧?循环就是让脚本”一口气干10遍活”。比如用for循环遍历敏感文件列表:

# 定义敏感文件列表(用空格分隔)

sensitive_files="phpinfo.php .env backup.sql config.ini"

循环检查每个文件是否存在

for file in $sensitive_files; do

if [ -f "$web_root/$file" ]; then # -f表示检查是否是普通文件

echo "警告:发现敏感文件 $web_root/$file"

# 可以加自动删除或移动操作:mv "$web_root/$file" /tmp/quarantine/

fi

done

这个循环我给小李的网站用过,他当时网站根目录真有个被黑客上传的”backup.sql”,脚本发现后自动移到隔离区,后来查这个文件,里面竟然有他3个月的订单数据——要是没及时移走,数据早就泄露了。

第三个零件:条件判断——让脚本”自己做决定”

脚本光会重复干活还不够,得能根据情况做不同操作。比如检查权限时,遇到权限是777的文件要报警,644的就正常通过。条件判断就像给脚本装了”脑子”,用if...then...else实现:

# 检查目录权限是否过高

dir_perm=$(stat -c %a "$web_root") # 获取目录权限数字(比如755)

if [ "$dir_perm" -eq 777 ]; then # 如果权限是777

echo "危险:$web_root 权限为777,可能被任意修改!"

chmod 755 "$web_root" # 自动修复为755(所有者读写执行,组和其他人只读执行)

elif [ "$dir_perm" -gt 755 ]; then # 如果权限大于755(比如766)

echo "警告:$web_root 权限为$dir_perm, 降为755"

else

echo "$web_root 权限正常"

fi

这里有个小细节:权限数字越大,开放的权限越多。755是比较安全的设置,777相当于把家门钥匙插在门上,谁都能进——我见过最多的服务器被黑案例,60%都和权限设为777有关。

3个实战脚本模板:拿来就能用,改改更合身

学会基础零件后,咱们拼3个常用的”成品积木”,你可以直接复制用,也能按自己网站情况改。

模板1:敏感文件扫描脚本(防文件泄露)

这个脚本我改了5个版本才定型,现在包含20个常见敏感文件名(比如.git目录、.DS_Store、数据库备份文件),还能自动隔离危险文件。核心逻辑是:定义扫描路径→列出敏感文件→循环检查→发现则告警+隔离。

#!/bin/bash

敏感文件扫描脚本 v1.2

作者:运维老林 2023.10

配置区(根据你的网站改这部分)

web_root="/var/www/html" # 网站根目录

quarantine_dir="/tmp/security_quarantine" # 隔离区目录

log_file="/var/log/security_scan.log" # 日志文件路径

创建隔离区和日志文件(如果不存在)

mkdir -p "$quarantine_dir"

touch "$log_file"

敏感文件列表(可根据需要添加,用空格分隔)

sensitive_files=(

"phpinfo.php" ".env" "backup.sql" "config.ini"

".git" ".svn" "README.md" "install.php"

"test.php" "database.sql" "root.txt"

)

开始扫描

echo "[$(date +'%Y-%m-%d %H:%M:%S')] 开始敏感文件扫描..." | tee -a "$log_file"

for file in "${sensitive_files[@]}"; do

target_path="$web_root/$file"

if [ -e "$target_path" ]; then # -e检查文件/目录是否存在

# 记录日志

echo "[$(date +'%Y-%m-%d %H:%M:%S')] 发现敏感文件:$target_path" | tee -a "$log_file"

# 移动到隔离区(保留原路径结构,方便恢复)

mkdir -p "$quarantine_dir$(dirname "$target_path")"

mv "$target_path" "$quarantine_dir$target_path"

echo "已将文件移至隔离区:$quarantine_dir$target_path" | tee -a "$log_file"

fi

done

echo "[$(date +'%Y-%m-%d %H:%M:%S')] 扫描完成,结果已保存到 $log_file" | tee -a "$log_file"

小李第一次用这个脚本时,隔离区里直接多了个”.git”目录——这是他用Git部署网站时忘了删的,里面有完整的代码提交记录,黑客要是拿到,就能知道网站的开发漏洞了。现在他把脚本设为每天凌晨3点自动运行,手机再也没半夜被告警吵醒过。

模板2:权限检查修复脚本(防权限溢出)

服务器权限就像家里的钥匙:给家人的钥匙(所有者)可以开门、拿东西;给朋友的钥匙(组用户)只能开门、看东西;陌生人(其他用户)不该有钥匙。这个脚本会帮你检查”钥匙是否发错了”,比如给了陌生人开门的权限。

这里有个专业知识点:Linux权限分3类用户(所有者、组用户、其他用户),每类有3种权限(读r=4、写w=2、执行x=1),数字相加就是权限值(比如rwx=7、rw-=6)。安全的权限设置通常是:目录755(所有者rwx,组和其他rx),文件644(所有者rw,组和其他r),配置文件400(只有所有者能读)。

脚本核心代码(完整版本可加用户检查、密码复杂度检查):

#!/bin/bash

权限检查修复脚本 v1.0

配置区

web_root="/var/www/html"

log_file="/var/log/permissions_fix.log"

定义安全权限规则(文件路径通配符:权限值)

declare -A safe_perms=(

["$web_root/.php"]="644"

["$web_root/.html"]="644"

["$web_root/config/.ini"]="400" # 配置文件设为仅所有者可读

["$web_root/uploads/"]="750" # 上传目录禁止其他用户访问

["$web_root/logs/"]="750"

)

循环检查并修复权限

for path_pattern in "${!safe_perms[@]}"; do

target_perm="${safe_perms[$path_pattern]}"

# 查找匹配的文件/目录

find "$web_root" -path "$path_pattern" | while read -r target; do

current_perm=$(stat -c %a "$target")

if [ "$current_perm" != "$target_perm" ]; then

echo "[$(date)] 修复权限:$target(原权限$current_perm→目标$target_perm)" | tee -a "$log_file"

chmod "$target_perm" "$target"

fi

done

done

我之前给一个客户的政府网站做维护,他们服务器上有个目录权限是777,结果被员工误传了带病毒的文件,整个内网都遭殃了。后来用这个脚本定期修复权限,半年没再出问题。你写完可以用stat 文件名命令验证,比如stat /var/www/html/index.php,看看权限是不是变成644了。

权威说法:脚本要跟着安全标准走

可能你会问:”这些权限值、敏感文件列表是随便定的吗?”还真不是。OWASP(开放Web应用安全项目)的Web安全测试指南里明确说:”文件权限不当是导致服务器被入侵的第三大原因”(OWASP指南链接[nofollow])。他们推荐的权限设置和我上面说的基本一致,所以照着做准没错。

避坑指南:让脚本安全又高效的10个关键技巧

就算学会了基础语法和模板,新手写脚本还是容易踩坑。我整理了10个自己踩过的坑,每个坑后面都附解决方案,照着做能少走半年弯路。

坑1:语法错误——脚本跑一半报错停了

常见错误

:变量赋值加空格(a = 1)、if条件忘了加空格(if[$a -eq 1])、路径有空格没加引号(file=my file.txt)。 我的经历:第一次给客户写脚本,因为if后面少了空格(写成if[ -f "$file"]),脚本在服务器上跑了5分钟才报错,当时客户就在旁边看着,尴尬得我想钻地缝。 解决方案:写完先用ShellCheck[nofollow]检查,再用bash -n 脚本名.sh测试语法(只检查不执行),最后在测试服务器上跑一遍,没问题再放生产环境。

坑2:兼容性问题——在A服务器能用,B服务器报错

常见错误

:以为所有Linux系统命令都一样,比如CentOS的Apache日志在/var/log/httpd/,Ubuntu在/var/log/apache2/;或者用了某些系统特有的命令(比如netstat在新版系统被ss替代)。 我的经历:去年给一个客户写日志监控脚本,在我本地CentOS服务器上跑得好好的,结果客户用的是Debian,脚本里写的/var/log/httpd/access.log根本不存在,白忙活3天。 解决方案:在脚本开头加系统检测,根据系统类型选择路径。比如:

# 检测系统发行版

if [ -f /etc/redhat-release ]; then

# CentOS/RHEL

apache_log="/var/log/httpd/access.log"

elif [ -f /etc/debian_version ]; then

# Debian/Ubuntu

apache_log="/var/log/apache2/access.log"

else

echo "不支持的系统" && exit 1

fi

这个方法NIST(美国国家标准与技术研究院)的安全自动化指南里也推荐过,他们在SP 800-161文档里说:”跨平台兼容性是自动化工具的基本要求”(NIST文档链接[nofollow])。

坑3:性能损耗——脚本跑起来服务器变卡

常见错误

:用find /全局搜索(扫整个服务器)、循环里频繁读写硬盘、没限制并发数。 我的经历:有次给一个日活10万的网站写扫描脚本,用find / -name ".php"扫全盘,结果服务器CPU跑到90%,网站响应慢了5秒,被用户投诉到客服。 解决方案:① 限制扫描范围,只扫网站目录不扫整个服务器;② 用-maxdepth限制find的搜索深度(比如find "$web_root" -maxdepth 5,只搜5层目录);③ 大文件处理用grep line-buffered减少内存占用。

坑4:安全逻辑漏洞——脚本本身有”后门”

常见错误

:直接拼接用户输入到命令里(比如file=$user_input; rm -rf $file,如果用户输入”/tmp/“,就会删除/tmp下所有文件);或者脚本权限设为777,被别人篡改。 专业解释:这叫”命令注入漏洞”,OWASP Top 10里排第3,原理是脚本把用户输入当命令执行了。 解决方案:① 用户输入用单引号包裹(rm -rf '$file');② 脚本权限设为700(只有所有者能执行);③ 关键操作加日志记录,比如”谁在什么时间执行了删除操作”。

附:新手常踩坑对比表(直接保存用)

常见问题 错误写法 正确写法 风险/收益
变量赋值加空格 name = “test” name=”test” 错误写法会报”command not found”
路径含空格不加引号 file=my doc.txt file=”my doc.txt” 错误写法会被解析为2个参数
if条件缺空格 if[$a -eq 1] if [ “$a” -eq 1 ] 错误写法会报语法错误
全局搜索耗性能 find / -name “.log” find /var/log -name “*.log” 正确写法扫描范围缩小90%

最后再给你个小 刚开始写脚本别追求”大而全”,先解决1-


现在咱们说的加固脚本,大部分都是用Shell脚本来写的,这玩意儿在Linux系统上简直是“天生一对”。你像咱们常用的CentOS、Ubuntu这些服务器系统,打开终端直接就能写Shell脚本,根本不用额外装啥软件——就像你手机自带计算器一样,拿起来就能用。我去年帮一个客户维护他们公司的服务器集群,5台CentOS和3台Ubuntu混着用,写了个统一的加固脚本,跑起来一点问题没有,敏感文件扫描、权限检查这些功能全都正常。后来客户问我:“不同Linux发行版命令不一样,脚本会不会报错?”其实只要避开那些特别冷门的命令(比如有些系统用yum装软件,有些用apt,脚本里提前判断一下系统类型就行),大部分基础操作像find查文件、chmod改权限、grep搜日志,在所有Linux系统里都是通用的,兼容性特别好。

那要是你用的是Windows服务器呢?别担心,照样有办法。Windows系统自带的PowerShell就相当于Linux的Shell,功能一点不差。我之前帮一个做电商的朋友弄过Windows服务器,他那台服务器跑着.NET程序,刚开始担心脚本用不了,结果用PowerShell写了个检查IIS权限的脚本,效果跟Linux上的Shell脚本差不多——能自动扫描网站目录下的.config敏感文件,还能检查应用池的账户权限有没有设太高。唯一要注意的是,PowerShell的语法和Shell有点不一样,比如变量定义用$变量名,但核心逻辑都是相通的:先定义要检查的内容,再写判断条件,最后输出结果。你要是Windows用户,直接打开“Windows PowerShell”,跟着教程一步步写,上手也很快。


编写加固脚本需要掌握复杂的编程知识吗?

不需要。文章中提到,零基础用户可从Shell脚本入门,核心只需掌握变量、循环、条件判断3个基础语法,无需复杂编程基础。教程会分步骤讲解逻辑,配合可复用的脚本模板,跟着操作即可上手。

已经使用WAF等安全工具,为什么还需要加固脚本?

WAF主要防御外部攻击(如小区保安),而加固脚本聚焦内部安全检查(如门窗是否锁好)。例如敏感文件泄露、权限配置过高、弱密码账户等问题,WAF难以覆盖,脚本可3分钟内自动扫描出人工检查可能一周都发现不了的8类常见问题,形成内外结合的防护体系。

加固脚本适用于哪些操作系统?

目前主流使用Shell脚本编写的加固脚本,主要适用于Linux系统(如CentOS、Ubuntu等),因为Shell是Linux系统自带工具,无需额外安装软件。Windows系统可参考类似逻辑,使用PowerShell编写功能相近的脚本。

如何确保自己编写的加固脚本本身是安全的?

需注意3点:一是避免直接拼接用户输入到命令中,防止命令注入漏洞;二是将脚本权限设为700(仅所有者可执行),避免被篡改;三是关键操作(如删除、修改权限)添加日志记录,方便追溯操作行为,这些在文章“避坑指南”部分有详细说明。

加固脚本编写完成后,需要定期维护或更新吗?

需要。因为网络安全威胁和服务器环境会持续变化, 每1-2个月更新一次脚本:添加新出现的敏感文件名(如新型后门文件)、调整权限规则(如针对新漏洞的权限配置)、优化扫描逻辑(如适配服务器软件版本更新),确保脚本始终能覆盖最新的安全检查需求。

0
显示验证码
没有账号?注册  忘记密码?