国家信息安全漏洞库(CNNVD)将信息安全漏洞划分为 26 种类型:配置错误、代码问题、资源管理错误、数字错误、信息泄露、竞争条件、输入验证、缓冲区错误、格式化字符串、跨站脚本、路径遍历、后置链接、SQL 注入、注入、代码注入、命令注入、操作系统命令注入、安全特征问题、授权问题、信任管理、加密问题、未充分验证数据可靠性、跨站请求伪造、权限许可和访问控制、访问控制错误、资料不足
国家信息安全漏洞共享平台(CNVD)根据漏洞产生原因,将漏洞分为 11 种类型:输入验证错误、访问验证错误、意外情况处理错误数目、边界条件错误数目、配置错误、竞争条件、环境错误、设计错误、缓冲区错误、其他错误、未知错误
sql 注入是最危险的 web 漏洞之一
var name;
name = Request.form("name");
var sql = "select * from test where name = '"+ name +"'";
如果用户输入 XiaoMing,则 SQL 语句会执行 select * from test WHERE name = 'XiaoMing'
如果攻击者构造输入语句 XiaoMing';drop table test--
则会执行 SQL 语句 select * from test WHERE name = 'XiaoMing';drop table test--'。在查询后又执行了删除表的操作,使用单引号闭合了前面的单引号,使用 -- 注释掉了后面的单引号
注入攻击的本质:把用户输入的数据当作代码执行
关键条件
相似得还有 xml 注入、代码注入、xpath 注入等等
XSS:攻击者在网页中嵌入客户端脚本,通常是JavaScript编写的恶意代码,当用户使用浏览器浏览被嵌入恶意代码的网页时,恶意代码会在用户的浏览器上执行
xss 破坏力巨大,被视为 web 安全的头号大敌,OWASP TOP10 多次把其位列榜首
JavaScript 可以用来获取用户的 Cookie、改变网页的内容、URL 跳转等,那么存在 XSS 漏洞的网页就可以盗取用户的 Cookie、黑掉页面、导航到恶意网站等,而攻击者仅需向网页注入 JS 代码
只是简单地把用户输入的数据反射给浏览器,即攻击者往往需要诱使用户“点击”一个恶意链接才能攻击成功
<?php
$input = $_GET["param"];
echo"<div>".$input."</div>";
?>
以上代码将用户的输入作为参数直接输出到页面上
比如提交 http://www.test.com/test.php?param=这是一个测试!
则页面的源代码就变成了 <div>这是一个测试!</div>
攻击者注入脚本如 http://www.test.com/test.php?param=<script>alert(xss)</scrpt>
此时攻击者输入的 Script 脚本被写入了页面中,网页跳出弹窗,内容为 xss
网页源代码变成 <div><script>alert(xss)</scrpt></div>
攻击者可以在<script>之间输入 JS 代码实现一些特殊效果
如使用 <script src="恶意网址/x.txt"></scrpt> 来加载恶意脚本,其中存放着恶意的 JS 代码
JS 加载外部的代码文件可以是任何扩展名(也可以没有扩展名),即使文件为.jpg 格式,只要文件中包含 JS 代码,都会被执行
直白的举例:我是某个论坛的忠实用户,攻击者发现该论坛存在反射型 XSS 漏洞,并精心构造了 JS 代码用于盗取用户的 Cookie 发送到攻击者指定站点,然后攻击者将含有 XSS 漏洞的 URL 私信我诱惑我点击,我点击了 URL 一探究竟,我的 Cookie 就被发到了攻击者那,攻击者就可以直接使用 Cookie 用我的身份登录论坛为所欲为了

会把用户输入的数据存储在服务器端,是最危险的 XSS
允许用户存储数据的 web 应用程序都可能存在存储型 XSS
攻击者提交一段 XSS 的 payload 后被服务器接受并存储,当其他用户访问该页面时,这段 XSS 代码被程序读出返回给浏览器,造成 xss 跨站攻击
直白的例子:攻击者在存在 XSS 漏洞的 web 应用中发表了一篇含有恶意 JS 代码的博客文章,该文章连同恶意代码一起被存储到服务器,所有访问该文章的用户就会在他们的浏览器中执行这段恶意 JS 代码
是通过修改页面的 DOM 节点形成的 XSS
DOM(Document Object Model 文档对象模型)定义了访问 HTML 和 XML 文档的标准,使用 DOM 可以允许程序和脚本动态地访问和更新文档的内容、结构和样式,通过 JS 可以重构整个 HTML 页面
DOM 通过 HTML DOM 树为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构
DOM 规定:
- HTML 文档中的每个成分都是一个节点
- 整个文档是一个文档节点
- 每个 HTML 标签是一个元素节点
- 包含在 HTML 元素中的文本是文本节点
- 每一个 HTML 属性是一个属性节点
- 节点和节点之间都有等级关系
<!注释:点击“write”按钮后,会在当前页面插入一个超链接,其地址为文本框的内容--/>
<script>
function test(){
var str = document.getElementByID("test").value;
document.getElementByID("t").innerHTML = "<a href='"+str+"' >testLink</a>";
}
</script>
<div id="t" ></div>
<input type="test"id="test"value="" />
<input type="button"id="a"value="write"onclick="test()" />
在 test()函数中修改了页面的 DOM 节点,通过 innerHTML 属性把一段用户数据当作 HTML 写入到页面中,这就造成了 DOM XSS
法一:
对于上述 DOM XSS 构造 'onclick=alert(xss) //
输入后页面变成 <a href=''onclick=alert(xss) //' >testLink</a>
首先用一个单引号闭合 href 的第一个单引号,然后插入一个 onclick 事件,最后再用//注释掉第二个单引号
点击这个新生成的链接,脚本将被执行
法二:
输入构造 '><img src=# onerror=alert(xss) /><'
页面变成 <a href=''><img src=# onerror=alert(xss) /><''>testLink</a>
用>闭合掉<a>,并插入一个新标签
攻击者伪造表单,让用户在提交表单、访问恶意链接时,执行攻击者想要执行的敏感操作
CSRF 攻击是建立在会话之上的,欺骗用户访问攻击者构造的 URL
CSRF 攻击是攻击者借助受害者 Cookie 骗取服务器的信任,但攻击者不能的得到 Cookie,所能做的就是给服务器发送请求
当请求某个 web 服务器时,浏览器和该服务器就会建立一个会话,会话没有结束,则默认所有操作都是可信的合法的,就可以用自己的权限对网站进行某些操作,如:发表删除文章等,会话结束后就会提示会话已过期
如:
在某个博客网站上,只需要访问 http://blog.test.com/entry.do?m=delete&id=123456就可以删除编号为 123456 的文章
攻击者首先在自己的网站 http://www.test.com/csrf.html构建一个页面
页面内容为:<img src="http://blog.test.com/entry.do?m=delete&id=123456" />,使用 img 标签指向删除文章的链接(从指定的 src 加载图片,即向 src 服务器发送了 get 请求)
然后引诱用户访问攻击者的网站,用户看到了一张无法显示的图片,回头才发现,编号为 123456 的文章已经被删除
攻击者构造请求,由服务端发起请求,其攻击的目标是通常是外网无法访问的内部系统,如访问内部资源、绕过防火墙、发起攻击内部系统
因为 ssrf 的请求是由服务端发起的,所以服务端能请求到与自身相连而与外网隔离的内部系统。
原理:由于服务器端提供了从其他服务器应用获取数据的功能且没有对目标地址做过滤与限制
SSRF 攻击过程:
from flask import Flask,request
import requests
app = Flask(__name__)
@app.route('/fetch',methods=['GET'])
def fetch():
url = request.args.get('url')
# 发起请求,获取内容
response = requests.get(url)
content = response.text
return content
if __name__ == '__main__':
app.run(debug=True)
如有一个简单的网站,允许用户输入一个 URL,然后该网站通过服务器端发起请求并返回结果,服务器端接收一个名为 url 的参数,然后使用 requests.get 发起了一个 GET 请求。这个代码存在 SSRF 漏洞,因为用户可以通过构造恶意的 url 参数来请求任意地址,包括服务器内部的敏感资源。
攻击者构造 url 输入:http://internal-server/internal-resource
点击劫持是一种视觉上的欺骗手段,攻击者使用一个透明的、不可见的 iframe,覆盖在一个网页上,然后诱使用户在该网页上进行操作,此时用户在不知情的情况下点击透明的 iframe 页面,通过调整 iframe 页面的位置,可以诱使用户恰好点击在 iframe 页面的一些功能性按钮上

点击劫持攻击与 CSRF 攻击都是在用户不知情的情况下诱使用户完成一些动作,但在 CSRF 攻击中如果出现了与用户的交互页面,则攻击可能无法顺利完成。而点击接触利用的就是与用户产生交互的页面
Flash 点击劫持
首先攻击者制作一个 Flash 游戏,并诱使用户来玩,让用户去点击“CLICK”按钮,每点一次按钮位置发生变化,在其最上方隐藏着一个看不见的 iframe,某些点击是有意义的,攻击者通过诱导点击最终控制了用户的摄像头,而用户并不知情
用户上传可执行脚本文件,并通过此脚本文件获得了执行服务器端命令得能力
文件上传的本质是服务器端为用户上传的文件处理逻辑不够安全
文件上传的常见示例
上传 web 脚本能被服务器解析即 webshell 攻击要满足如下条件
DDOS 是利用合理的请求造成资源过载,导致服务不可用
将正常请求放大了若干倍,通过若干个网络节点同时发起攻击,以达成规模效应,这些网络节点往往是攻击者所控制的“肉鸡”,数量到达一定规模后就形成了一个僵尸网络。
常见的 DDOS 攻击有 SYN flood、UDP flood、ICMP flood
SYN flood 最为经典且仍具备强大的生命力,它利用了 TCP 协议中设计的缺陷,而 TCP/IP 协议是整个互联网的基础,因次修复这样的缺陷几乎不可能

正常情况下 TCP 三次握手过程如下
- 客户端向服务器端发送一个 SYN 包,包含客户端使用的端口号和初始化序列 x
- 服务器端收到客户端发送来的 SYN 包后,向客户端发送一个 SYN 和 ACK 都置位的 TCP 报文,包含确认号 x+1 和服务器端的初始序列号 y
- 客户端收到服务器返回的 SYN+ACK 报文后,向服务器端返回一个确认号为 y+1、序号为 x+1 的 ACK 报文,一个标准的 TCP 连接完成
SYN flood 在攻击时,首先伪造大量的源 IP 地址,分别向服务器端发送大量的 SYN 包,此时服务器端会返回 SYN/ACK 包,由于源 IP 地址是伪造的,所以伪造的 IP 并不会应答,服务器端没有收到伪造 IP 的回应,会重试 3~5 次,并且等待一个 SYN Time(一般是 30 秒~2 分钟),如果超时则丢弃这个连接。攻击者会大量发送这种伪造源地址的 SYN 请求,服务器端将会消耗非常多的资源来处理这种半连接,同时还要不断的对这些 IP 进行 SYN+ACK 重试,最后的结果是服务器无暇理睬正常连接,导致拒绝服务
对抗 SYN flood 的主要措施有 SYN Cookie 等,通过为每一个 IP 分配一个 Cookie,并统计 IP 的访问频率,若短时间内收到大量来自同一个 IP 的数据包,则认为受到攻击,来自这个 IP 的包将被丢弃
攻击发生在应用层,TCP 三次握手已经完成,因次发起攻击的 IP 都是真实的
CC 攻击的前身是一个叫 fatboy 的攻击程序,当时黑客为了挑战绿盟的一款反 DDOS 设备开发,绿盟开发了一款名为“黑洞(Collapasar)”的反 DDOS 设备能有效清洗 SYN flood 等有害流量,黑客则挑衅似的将 fatboy 所实现的攻击方式命名为 Challenge Collapasar(简称 CC)
原理:对一些消耗资源比较大的应用页面不断发起正常的请求,以达到消耗服务器端资源的目的,如查询数据库、读写硬盘文件等操作
例如$sql = "select * from post where tagid='$tagid'order by postid desc limit $start,30";
当 post 表数据庞大,翻页频繁,$start 数字急剧增加时,查询影响结果集=$start+30,该查询效率呈现明显下降趋势,而多并发的频繁调用因查询无法立即完成,资源无法立即释放,会导致数据库请求连接过多,数据库阻塞,网站无法正常打开
应用层 DDOS 攻击是一种针对服务器性能的攻击,优化服务器性能的方法都能缓解这种攻击,最常见的方法就是在应用中针对每个客户端做一个请求频率的限制。
由于程序逻辑的不严谨或逻辑太过复杂,导致一些逻辑分支不能够正常处理或处理错误,如任意密码修改、越权访问、密码找回、交易支付金额修改等
逻辑错误漏洞非常隐蔽,危害巨大
攻击者挖掘逻辑错误漏洞的一般步骤
比如购物,挑选商品,立即购买,显示订单、提交订单、付款
程序提供了直接执行 Shell 命令的函数的场景,当攻击者不合理使用,且开发者对用户参数未考虑安全因素的话,就会执行恶意的命令调用,被攻击者利用。
如
$userInput = $_GET['filename'];
$command = "touch" . $userInput;
system($command);
程序直接提供的 shell 命令的操作且未对用户输入进行任何过滤
攻击者可以构造恶意输入 file.txt;rm -rf *,当前目录下的文件会被全部删除
预防措施:
对用户输入进行验证和过滤,确保只接受符合预期格式的数据。不信任并过滤掉不安全的字符和符号。
尽量使用安全的 API 或库来执行系统命令,而不是直接构造命令字符串。这可以减轻许多与命令注入相关的问题。
在执行系统命令的过程中,使用最小的权限原则,确保应用程序不会意外地执行敏感操作。
配置应用程序和服务器,限制执行环境,禁用不必要的系统命令或功能。
当计算机向缓冲区内填充数据时超过了缓冲区本身的容量,溢出的数据覆盖在合法数据上。
理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符,但是绝大多数程序都会假设数据长度总是与所分配的储存空间相匹配,这就为缓冲区溢出埋下了隐患
操作系统所使用的缓冲区,又被称为"堆栈"。在各个操作进程之间,指令会被临时储存在“堆栈”中,“堆栈”也会出现缓冲区溢出。
入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,可以使程序崩溃拒绝服务,或者跳转并执行恶意程序
#include <stdio.h>
#include <string.h>
void vulnerableFunction(char *input) {
char buffer[10];
strcpy(buffer,input); // 潜在的缓冲区溢出漏洞
}
int main(int argc,char *argv[]) {
if(argc!= 2) {
printf("Usage: %s <input>\n",argv[0]);
return 1;
}
vulnerableFunction(argv[1]);
printf("Program executed successfully!\n");
return 0;
}
**vulnerableFunction** 函数接收一个字符串作为参数,并使用 **strcpy** 函数将输入复制到一个长度为 10 的缓冲区中。如果用户提供的输入超过了缓冲区的大小,将导致缓冲区溢出。攻击者可以利用这种漏洞,覆盖相邻的内存区域,改变程序的行为。
如执行以下命令 ./buffer_overflow_example ABCDEFGHIJKLMNOPQRSTUVWXYZ
缓冲区溢出的预防措施
使用安全的函数来处理字符串,如 strncpy 替代 strcpy,以确保不会超出目标缓冲区的大小。
在处理数组或缓冲区时,进行边界检查,确保不会写入超过分配空间的数据。