资讯动态

网络安全十大常见漏洞:从原理到防御,一篇讲透

发布时间:2026/10/17 12:34:28 来源:尧图企业网站定制
很多刚接触网络安全的朋友第一次听到“漏洞”这个词总觉得是黑客电影里那种神秘又遥远的东西。其实漏洞就在我们身边小到个人博客大到企业核心系统每天都在被扫描、被试探。作为这些年一直在做安全测试和应急响应的人我可以很负责任地告诉你绝大多数安全事故翻来覆去用的都是那几个经典的漏洞类型。把“网络安全常见十大漏洞”的原理和防御吃透你就能挡住至少八成的基础攻击。这篇文章不搞虚的从零基础视角出发把每个漏洞的成因、危害、防御方案拆开揉碎讲清楚配合我实际踩坑得来的经验一篇看完就能上手排查自己的项目。1. SQL注入最经典的数据库杀手1.1 为什么一个输入框就能让数据库裸奔SQL注入是所有漏洞里历史最悠久、影响也最直接的一类。它的成因一句话就能概括开发者把用户输入的内容直接拼接到了SQL查询语句里让数据变成了代码的一部分。举个例子一个登录功能很多人早期会这样写SELECT * FROM users WHERE username admin AND password 123456如果用户名输入框里填的是admin --拼接之后语句就变成了SELECT * FROM users WHERE username admin -- AND password 123456--在SQL里是注释符后面的密码判断整个被注释掉攻击者不需要知道密码就能以admin身份登录。这只是最基础的单引号闭合。再往后还能用UNION SELECT把其他表的数据拖出来用LOAD_FILE读服务器文件甚至借助INTO OUTFILE写入web目录拿到系统权限。1.2 危害程度不是说说而已SQL注入的危害上限非常高。轻则绕过登录、篡改页面内容重则直接把整个数据库脱走——用户名、密码哈希、订单记录、身份证号全量泄露。我在一次应急响应中处理过一个用了开源电商系统二次开发的项目因为商品搜索功能存在注入点攻击者把所有会员表数据全部导出还在服务器上留下了后门脚本。事后排查发现注入点仅仅是搜索框没有做任何参数化处理。这里要特别强调一点很多人以为“我用了过滤函数就安全了”比如把单引号替换掉、把select替换掉。实际上黑名单过滤的思路在有经验的测试者面前不堪一击。大小写绕过、编码绕过、注释符绕过方法多到超乎想象。真正可靠的方案是下面要说的参数化查询。1.3 防御方案与实操要点防御SQL注入第一选择永远是预编译语句参数化查询。它的核心逻辑是SQL结构提前固定用户输入只作为“参数值”传入永远不会参与语句结构的拼接。# 错误示范拼接SQL sql SELECT * FROM users WHERE username username # 正确示范参数化查询 cursor.execute(SELECT * FROM users WHERE username %s, (username,))不同语言对应不同写法但思路一致Java用PreparedStatementPHP用PDO::prepareGo用database/sql的占位符。只要参数化做到位SQL注入基本就堵死了。另外两条必须配合的机制一是数据库账号最小权限应用账号不要用root或dba只给增删改查所需的表级权限二是在代码层面做输入校验比如搜索接口只允许字母和数字用白名单正则直接拦掉特殊字符。纵深防御的思路是即使第一层被绕过后面的权限限制还能兜底。2. XSS跨站脚本前端世界的信任危机2.1 反射型、存储型、DOM型怎么区分XSSCross-Site Scripting的本质是把恶意脚本注入到用户浏览器中执行。很多初学者分不清它的三种类型我用最直白的方式讲反射型恶意脚本通过URL参数带入服务端未经处理直接渲染回页面。比如搜索框输入scriptalert(1)/script页面立刻显示这段HTML。它只能打给点了链接的人属于“一次性利用”。存储型恶意脚本被保存到了数据库里任何访问该页面的用户都会触发。比如在留言板提交一段脚本之后每个打开留言板的人都会中招。这种杀伤力最大因为影响的人是持续的。DOM型不需要经过服务端纯粹是前端JavaScript读取URL参数并直接操作DOM时产生的。比如从location.hash取值插入页面客户端的脚本自己把自己卖了。2.2 一个Cookie被拿走意味着什么XSS最常用的危害是窃取Cookie。攻击者在页面上执行一段JavaScript把当前用户的Cookie发送到自己的服务器拿到Cookie就可以伪装成这个用户直接登进后台。这就是所谓的“会话劫持”。Cookie之外XSS还能做更多事情伪造登录表单诱导用户输入账号密码、窃取页面里的敏感信息、修改页面内容发布垃圾消息、甚至通过调用后台API执行敏感操作。尤其在后端接口没有做好CSRF防护时XSS几乎等于拿到了该用户的一切权限。2.3 三层防御缺一不可防御XSS不是靠一次操作就完事它需要三道防线同时生效第一层是输出编码。在服务端把用户输入的内容渲染到HTML页面之前对 等字符做HTML实体编码让脚本变成纯文本显示。不同位置HTML标签内、属性内、script内、CSS内需要不同的编码方式新手最容易漏掉属性内的编码导致 onmouseover...这种攻击手法生效。第二层是Content Security PolicyCSP。通过HTTP响应头限制页面允许加载的脚本来源Content-Security-Policy: default-src self; script-src self https://cdn.example.com这样即使攻击者成功注入了script src恶意地址浏览器也会直接拒绝加载。CSP是最后的“安全气囊”强烈建议所有Web项目默认开启。第三层是Cookie属性加固。设置HttpOnly后JavaScript无法读取Cookie值XSS窃取Cookie这条路就断了。再配合Secure属性要求HTTPS传输以及SameSite属性限制跨站发送会话劫持的成本大大提升。实操提示我处理过很多被XSS困扰的项目最常见的修复漏网点不是留言板、不是输入框而是URL参数直接回显的“搜索无结果”页面。开发者觉得这页没功能就忽略了输出编码结果整个入口全是洞。3. CSRF与SSRF两种方向相反的“伪造”3.1 CSRF借你的手干坏事CSRF跨站请求伪造的逻辑是攻击者构造一个恶意请求诱导已登录用户点击浏览器自动携带用户的Cookie发起请求服务端以为是用户本人的操作于是照单执行。最常见的场景是修改密码和转账。你登录了银行系统没有退出然后打开了攻击者精心构造的页面页面里悄悄嵌了一个表单form actionhttps://bank.example.com/transfer methodPOST input typehidden nameto valueattacker input typehidden nameamount value10000 /form scriptdocument.forms[0].submit();/script表单自动提交浏览器带上你的Cookie后端只验证了会话有效没有验证请求来源是不是你本人操作钱就这么转走了。防御CSRF的标准方案有三个CSRF Token服务端渲染页面时生成随机token存在Session里表单提交时必须带上后端比对不一致就拒绝。攻击者无法预知你的token自然构造不出有效请求。SameSite Cookie属性设置SameSiteLax或Strict浏览器跨站发送Cookie的行为会被禁止从根源上堵住“自动携带身份”。请求头校验校验Origin或Referer字段只允许同源请求。但注意Referer有时会被隐私设置剥离Origin更可靠一些。3.2 SSRF让服务器替你去内网“串门”与CSRF相反SSRF服务端请求伪造是攻击者诱导服务端去访问本不该访问的地址。很多功能都有这种隐患图片转码、URL预览、Webhook回调、导入远程文件——只要你的服务器会根据用户提供的URL发起请求就可能存在SSRF。攻击者把URL填成http://127.0.0.1:3306、http://169.254.169.254/latest/meta-data/云厂商元数据接口可能获取到临时密钥甚至内网其他主机的管理后台服务端就会代他去访问。我之前测试过一个“网页截图”功能传一个URL进去系统渲染截图返回给用户。把URL改成内部运维平台的登录页截图直接把内网面板内容暴露了出来这就是典型的SSRF。防御SSRF的核心是控制请求的边界解析URL后校验目标IP必须是公网合法地址禁止内网段、回环地址、链路本地地址、保留段禁止协议白名单之外的类型比如默认只允许HTTP/HTTPS防止通过file://、gopher://读取本地文件DNS解析之后再做一次IP校验防止“DNS重绑定”绕过尽量让请求走专用的代理或跳板机把SSRF的攻击面隔离出去4. 文件上传与文件包含通往服务器权限的后门4.1 上传一个“图片”怎么就Getshell了文件上传漏洞是所有Web木马中最常见的入口。场景再熟悉不过头像上传、附件上传、证件照片上传。攻击者尝试上传一个包含恶意代码的PHP、JSP、ASP文件如果服务器没有严格校验文件落到了web目录里访问它就能直接执行里面的代码——这一步通常叫做“GetShell”通俗讲就是拿到了服务器的执行权限。很多系统做得像模像样前端限制了图片格式后端也检查了Content-Type但依然被绕过。攻击者改扩展名shell.php.jpg、修改Content-Type为image/png、在图片尾部拼接PHP代码图片马再配合服务器解析漏洞或者包含漏洞照样能执行代码。防御文件上传我建议必须同时满足这几点扩展名白名单只允许业务必须的类型比如jpg、png、pdf黑名单思路不要用内容校验服务端用图像库重渲染图片彻底清除其中的脚本代码存储与执行分离文件存储在web目录外部或独立对象存储通过程序读取代为直接访问随机文件名不使用用户提供的原始文件名避免shell.php这种名字直接落地限制大小与频率防止恶意用户刷爆磁盘也为审计保留日志4.2 文件包含参数里的“路径”别乱传文件包含漏洞常出现在代码设计不良的PHP应用中核心逻辑是开发者把文件路径作为参数动态加载用户控制了路径内容。本地包含可以读取系统文件用../../../../etc/passwd这样的路径穿越一张张翻文件如果能包含日志文件或图片马就能在页面中解析出PHP代码执行命令。远程包含更直接加载攻击者服务器上的恶意脚本一键拿下执行权限。防御文件包含其实不复杂永远不要直接拼接用户输入的文件路径。一是对文件名做参数校验只允许预先定义好的白名单映射关系比如pageprofile对应加载profile.php二是关闭远程包含开关PHP的allow_url_include三是不用动态包含改写为静态引入。5. 命令注入与代码执行一旦存在就是最高权限5.1 为什么说命令注入是“杀招”命令注入的本质是开发者调用了系统命令但其中拼接了用户输入。最常见的场景是运维工具类系统Ping检测、域名查询、日志搜索代码里写system(ping . $ip);如果$ip被填成127.0.0.1 whoami回车之后服务器多执行一条命令。这一招的可怕之处在于命令是以Web服务运行用户的身份执行的通常是www或nobody。如果Web服务权限配置不当直接跑在root下攻击者的命令就是root权限执行整个服务器沦为肉鸡。命令注入之后攻击者通常会尝试连接外部的方式获取交互式权限然后做权限维持、横向移动。防御命令注入最根本的手段是尽量不调用系统命令。Ping检测用ICMP包构造库实现域名查询用dns解析库实现都能在代码层完成。如果非得用系统命令必须对参数做严格的模式匹配只允许IP的四个数字段顺带设置执行超时和命令白名单确保即使输入异常也跑不出既定范围。5.2 代码执行与表达式注入与命令注入类似代码注入是用户输入直接进入了eval()、assert()、create_function()这类函数。在模板引擎、动态报表、规则引擎里最容易出现。另一个变体是表达式注入比如Java的SpEL表达式、Python的eval、Node的vm沙箱逃逸它们都能从“一条数据”扩展成“一段逻辑”。这类问题的防御思路和命令注入一致别让用户触达代码解释器。如果业务必须支持那就用一个隔离度极高的沙箱配合资源限制和超时控制。我见过一个报表系统为了让用户自定义计算公式直接用了Python的eval排查时发现可以导入库执行系统调用。后来重构成白名单函数解析器才彻底解决。6. 反序列化漏洞与XXE藏在“数据交换”里的杀手6.1 反序列化数据还原竟成了代码执行序列化是把对象变成字符串便于存储传输反序列化是把这个字符串还原成对象。问题在于还原的过程中许多语言会触发对象里的魔术方法。Java的readObject、PHP的__wakeup、Python的pickle一旦攻击者精心构造了序列化数据还原时就会执行预埋的恶意逻辑。Java生态的反序列化漏洞在近年影响面极广因为很多框架默认依赖了带风险的组件。攻击者不需要账号只往接口发一段精心构造的序列化字节流就可能直接执行命令。这类漏洞经常被评为最高危因为它可以从前端一路打通到服务器。防御反序列化的措施优先级如下不要反序列化不可信数据用了就做加签校验HMAC确认数据没被篡改对Java对象流加白名单类过滤ObjectInputFilter把可能引入攻击面的组件升级到修复版本。对于RPC、MQ这类内部通信系统强制启用认证和加密别把接口裸奔在内网。6.2 XXEXML的老家被“外联”了XXEXML外部实体注入在新手圈里知道的人不多但危害一点不小。罪魁祸首是XML的DOCTYPE声明允许定义外部实体如果解析器开启外部实体加载攻击者可以在XML里这样写?xml version1.0? !DOCTYPE foo [ !ENTITY xxe SYSTEM file:///etc/passwd ] dataxxe;/data解析后xxe;会被替换成服务器本地文件内容通过报错信息或页面渲染泄露出来。如果目标允许访问内网地址XXE还能变成SSRF去探测内网服务。防御XXE简单有效禁止外部实体加载。在解析XML之前关闭DTD和外部实体功能。具体实现上JavaDocumentBuilderFactory设置setFeature禁用PHP禁用libxml_disable_entity_loaderPython的xml.etree换用defusedxml库。能不用XML就尽量不用XMLJSON、Protobuf这类格式天然没有外部实体的概念。7. 不安全配置与弱口令最容易被忽视的“同行人”7.1 一切默认值都是攻击者的好朋友还有一类漏洞和代码无关纯粹是“配置”问题。框架默认后台路径没改、调试模式在生产环境开启、目录列表打开、错误信息直接返回完整堆栈、版本号明文暴露。这些看似无关紧要的细节全部是攻击者的情报来源。比如生产环境开启了debug模式报错页面把数据库连接串、文件绝对路径、依赖版本全部打印出来等于把地图递到对手手里。目录列表开启备份文件.sql.bak、源码压缩包直接下载。版本信息暴露攻击者去漏洞库查对应版本CVE编号直接照着打。配置加固的原则是“默认安全”生产环境关闭一切调试信息移除默认后台入口改到独立端口或IP白名单内访问服务器响应头隐藏具体的Web容器版本静态目录禁止列目录备份文件一律不放在web可访问路径下。这些基线配置项目整理成SQL脚本部署时一键执行才是团队协作的正确姿势。7.2 弱口令为什么永远杀不完很多人觉得弱口令是“低级问题”但数据泄露事件里90%的突破口都是弱口令或者同一个密码走天下。后台账号用admin/admin123数据库用root/rootRedis无认证SSH开密码登录且口令简单这些都是真实案例里高频出现的项目。防御弱口令技术上能做的事情很多强制密码复杂度策略、启用多因素认证、限制登录失败次数并加入防暴力破解逻辑、禁止内网服务对外无认证暴露、定期做口令熵值评估。但比技术更重要的是一套规矩新员工入职默认开通MFA服务器登录统一走密钥认证数据库连接串从配置中心下发而不是硬编码在代码里。8. 常见问题与排查技巧实录8.1 明明用了参数化查询为什么还是被注入进了报表老代码有一次我给一个统计报表系统做审计发现一个数据导出功能存在注入。开发者很委屈地说“我全部用了预编译啊”。后来排查发现报表排序功能需要根据前端传的排序字段动态拼接ORDER BY开发者为了省事在这里用了字符串拼接。这就是典型的“只注意到查询条件、忘了排序字段也算动态内容”。排序字段必须走白名单映射前端传score就映射到固定的列名绝不允许直接进SQL语句。这类问题的排查思路是审计代码时不要只看有没有用预编译要看有没有任何字符串拼进SQL。全局搜、concat、String.format一个个确认变量来源。在开发阶段还应该加SQL日志输出到独立文件上线前人工检查一遍所有SQL日志中的动态部分。8.2 加了WAF依然被绕过问题出在哪有同行问过我系统前面挂了WAF为什么模拟攻击还是能打进测试环境答案通常有两个。一是WAF只对部分URL做了防护接口路径改个大小写、加个路径穿越.jsp/../api、或者换成带Content-Type为JSON的POST体规则就匹配不上了。二是WAF拦下了HTTP层的攻击但应用本身业务逻辑存在漏洞比如我前面讲的低权限用户遍历ID查看他人订单这属于越权类问题WAF根本无从感知。所以我的经验是WAF是“延迟满足”的补充项不是“一劳永逸”的防线。真正的重心永远在代码层修复和架构层隔离。不要因为挂了WAF就降低对开发的约束。8.3 发现漏洞后修复顺序怎么排实际项目里漏洞经常一抓一大把但资源有限怎么排优先级我的做法是四步评估规则该漏洞是否暴露在公网、是否涉及核心资产数据库、账号体系、资金交易、利用难度高不高、自带危害大不大。四个条件同时命中立即停工修复只命中部分定级为中期计划只是理论风险且攻击面受限放入日常迭代。8.4 学习路线与自查工具推荐零基础学习漏洞防御不需要一上来就啃几百页的协议书。我建议的路线是先把十大漏洞的“原理”看懂再去本地搭一个存在漏洞的靶场做代码审计练手注意不要针对未经授权的真实目标做测试。等能轻松找到靶场漏洞并给出修复建议后再系统学习HTTP、TCP这类基础协议最后研究代码审计方法论。在自查工具方面开源社区的扫描器可以作为辅助例如OWASP ZAP适合Web应用完整扫描针对依赖组件可以用开源依赖检查工具看看自己引的第三方包有没有公开漏洞记录。这里特别提醒一句扫描器报的风险等级参考价值有限误报和漏报都很常见所有告警必须手工验证。9. 结束前再分享一点我的实际体会这几年来我处理过不少“惨烈”的安全事故回头复盘每一桩几乎都能对应到上面的某类漏洞。SQL注入、XSS、弱口令这三样占了大头反序列化和XXE这类偏门漏洞一次没堵住造成的损失往往最重。安全工作没有一劳永逸新功能上线新漏洞面就跟着出现。我自己的习惯是把安全自查做成发布流水线里的一道关卡每次上线前自动跑一遍扫描和依赖检查“人人皆知安全”不如“流程里全是检查点”。这篇十大漏洞的总结写出来希望对你有一份真正的参考价值。如果你照着检查自己的项目发现一处问题、修掉一个隐患那这篇文章的目的就达到了。遇到具体漏洞卡住排查的时候再回来翻一翻对应章节按着防御清单一项项核对多半能找到突破口。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑