“你在浏览器敲入域名后,到底发生了什么?浏览器是怎么获得你请求的内容的?中间会发生什么攻击行为吗?”
首先会从上层端对端通信进行讲解,其中涉及到很多TCP/IP四层协议后续会分析。
代理服务器:实现请求和响应的转发,只修改源ip地址,不修改其他内容。分为客户端和服务器端:
(1)客户端:主要作用是隐藏客户端的ip,突破目标主机的访问限制,也就是常说的技术。
(2)服务器端:缓存资源,可以减轻web服务器的负担
网关:其实网关也类似于服务器端的代理服务器,但是它还可以实现协议的转换(代理不会改变请求的内容)。主要目的是隔绝外网,保护内网。
(1)如果设置了代理服务器,客户端的请求经代理转发,到达域名对应主机的网关。
(2)网关转发客户端的请求给内网中的Web服务器,如IIS、Apache、Nginx、Lighttpd。
(3)web服务器解析请求中的文件名,并返回该文件的html内容给客户端。
这种想法在早期网络请求还不复杂的时候很美好,但是随着技术的发展,产生了动态资源的请求,而web服务器只能响应静态资源如html、css、js文件的请求。
因此中间件出现了,如果有动态资源的请求,web服务器会转发给中间件处理,中间件包含对应语言的解释容器,能够解析动态资源文件内代码,返回html内容。
如果是JSP文件,web服务器会将请求转发给Servlet(服务端的Java应用程序)处理,Tomcat即是Servlet的一种,Servlet包含Java容器实现java解释。
而如果是PHP文件,web服务器会直接与php容器进行通信。
因此请求PHP具体的过程是:收到一个php文件请求 -> web服务器启动一个Fastcgi进程 – 基于Fastcgi协议传输请求数据 -> php-fpm(Fastcgi进程管理器) -> php解释器。
请求http://www.a.com/a.jpg/.php时,实际会请求了/a.jpg,并且以php解析了a.jpg文件,因此结合文件上传可实现RCE。
接下来解释一下原理。Fastcgi数据包中typ变量表示协议的类型,type=4时,表明数据包中body部分是以键值对形式存储的环境参数。假设浏览器请求http://www.a.com/a.jpg/.php,php-fpm发现一个type=4的Fastcgi数据包,它知道这个数据包里的报文是环境参数,提取出来后就知道要请求的是哪一个文件了:
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/a.jpg/.php',
'SCRIPT_NAME': '/a.jpg/.php',
'QUERY_STRING': '',
'REQUEST_URI': '/a.jpg/.php',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1'
}
存在漏洞的原因是php.ini中fix_pathinfo选项设置为1。Nginx/IIS7根据URL请求中.php的后缀,认为是PHP文件的请求,将其交给了php-fpm。
根据Fastcgi数据包所传送的环境参数SCRIPT_FILENAME,php-fpm认为请求的文件是/var/www/html/a.jpg/.php。 如果fix_pathinfo=1,php-fpm发现请求的文件不存在后,会自动去除最后一个/及其后面的内容,继续匹配文件,直到请求的文件存在,因此最终请求的文件是/var/www/html/a.jpg,且这个文件交给了php解释器解释执行。(所以这不是nginx/IIS的锅)
防御方法:(1) php.ini中fix_pathinfo=0(php>7.2后配置默认是1),请求前先判断文件是否存在。(2)借助PHP-FPM的security.limit_extensions配置项,设置只有指定后缀名能被解析为php。
php-fpm默认监听9000端口,若该服务暴露在公网上,可以构造Fastcgi协议直接进行通信。可以通过构造环境变量实现RCE,例如构造:
{
'GATEWAY_INTERFACE': 'FastCGI/1.0',
'REQUEST_METHOD': 'GET',
'SCRIPT_FILENAME': '/var/www/html/a.php',
'SCRIPT_NAME': '/a.php',
'QUERY_STRING': '',
'REQUEST_URI': '/a.php',
'DOCUMENT_ROOT': '/var/www/html',
'SERVER_SOFTWARE': 'php/fcgiclient',
'REMOTE_ADDR': '127.0.0.1',
'REMOTE_PORT': '12345',
'SERVER_ADDR': '127.0.0.1',
'SERVER_PORT': '80',
'SERVER_NAME': "localhost",
'SERVER_PROTOCOL': 'HTTP/1.1',
'PHP_VALUE': 'auto_prepend_file = php://input',
'PHP_ADMIN_VALUE': 'allow_url_include = On'
}
就可以类似实现一个文件包含+php伪协议执行任意代码,并且可以绕过disable_function,因为是在和php解释器直接通信。蚁剑上已有插件可以实现与php-fpm直接通信。
(1)基于DNS协议解析域名对应的ip:
a)客户端向本地域名服务器发起DNS解析请求。
b)本地域名服务器检查缓存文件,是否有解析记录;没有则向公网上其他域名服务器发起请求。
c) 本地域名服务器向根、顶级、二级、权威域名服务器(子域名)依次询问。
客户端和本地域名服务器是递归查询,本地域名服务器和公网上的域名服务器是迭代查询.
递归:A问B,B不知道,B问C、D、E…最后返回答案给A
迭代:A问B,B说不知道,但是C可能知道;A去问C,C说不知道,但是D可能知道,A去问D…最后获得答案
(2)向解析获得的ip发送HTTPS请求, HTTPS请求要在TCP连接中进行
首先建立TCP三次握手:
a)客户端向服务端发送SYN请求连接报文
b)服务器端返回SYN+ACK应答报文
c)客户端返回ACK报文,成功建立连接
然后基于SSL/TLS协议协商密钥:
a)客户端给出支持的SSL协议版本号、加密方法等给服务器端
b)服务器响应请求,发送自己的数字证书、数字签名(用自己私钥加密数字证书的散列值)给客户端,证书内容包括颁发者、用户身份信息(域名、机构名等)、所用的加密算法、公钥等
c)客户端用服务器公钥解密得到数字证书散列值hash1,计算浏览器CA中保存的服务器数字证书的散列值hash2,比对hash1==hash2,保证数字证书不被篡改。完成身份认证后用服务器的公钥加密客户端自己定义的随机数(作为后面加密传输数据的对称密钥)给服务器
d)服务器用自己的私钥解密,获得对称密钥,后续通信数据用密钥进行对称加密
Q: 中间人能否在服务器端给客户端数字证书时修改其证书或截取转发自己的数字证书给客户端,从而实现伪造服务器端与客户连接?
A: 不可能修改证书,因为没有服务器端私钥无法伪造数字签名。
不可能修改,因为证书内包含域名信息,浏览器解析数字证书时发现域名信息不对应则拒绝请求,返回"你的连接不是私密连接"警告信息。
(3)在TCP连接中进行HTTPS请求
HTTP/1.1之后,一个TCP连接中可以建立多个HTTP请求
(4)TCP报文到达网络层,网络层进行寻址和路由,到达目的ip所在的网段
一般都是到达目的web服务器所在网段的网关,而不是和web服务器进行直接通信。
(5)网关基于NAT协议将外网的ip:port转换为内网ip:port,IP报文的目的ip更改为内网web服务器的ip
(6)IP报文到达链路层,进行ARP寻址,获得web服务器的MAC地址后,在链路层进行转发
(7)报文最终到达web服务器,服务器对其进行响应,并将响应内容逐层解封装返回给客户端。(如何响应请返回上面“端对端的通信过程”的解释)
Dos攻击
(1)应用层上的CC攻击
利用代理服务器或大量肉鸡向目标主机发送大量看似合法的请求,但都是请求服务器上需要加载大量数据的页面,导致服务器资源浪费,看不到大量异常的流量因此难以溯源。
(2)应用层上DNS查询洪水攻击
客户端发起的域名解析,最终会请求到权威域名服务器,查询它的子域。向目标主机发送大量域名解析请求,且该域名不存在,会导致主机需要不断递归查询。例如请求http://hack.github.com,请求会到github.com权威域名服务器上,向其查询是否存在hack子域名。
(3)SSL DOS:发送大量HTTPS请求,利用SSL协商密钥会消耗资源,降低速度。
(4)TCP三次握手中的SYN Flood攻击
利用SYN半开连接,第二次握手时服务器返回SYN+ACK给客户端,等待客户端返回ACK,但是客户端不返回ACK报文,服务器会在超时连接前等待并重发SYN+ACK报文。如果有大量的等待连接占用服务器资源,会导致其无法处理正常请求。
DNS劫持
(1)本地DNS服务器劫持:getShell后修改PC上DNS配置(hosts文件/DNS服务器地址/DNS缓存)、拿下内网的DNS服务器或入侵路由器修改请DNS服务器配置
(2)DNS解析路径上被劫持:
a)请求转发给恶意路由器
b)截取响应包,进行恶意应答
c)缓存污染:解析路上的一个链路节点首先伪装成目标域名的解析服务器返回结果,查询者只能接受最先返回的结果
(3)篡改公网上权威DNS服务器的记录
ARP欺骗
条件:由于ARP包不能路由,路由器收到ARP包不会转发,因此只能在同网段进行攻击
原理:
ARP协议采用一问一答的机制:
询问:who has 192.168.1.1 tell 192.168.1.2
应答:arp reply 192.1.1.1 is at 00:ff:11:22:33:44
没有对应答主机进行身份验证,且采用后到优先的原则(选择相信最新的应答报文),因此通过不断发伪造的应答包覆盖真实的应答来伪造身份,如不断发包伪造网关:arp reply 192.1.1.1 is at [攻击者MAC地址]
菜鸡的学习总结,如果有不对的地方请大佬修正ヽ(。◕‿◕。)ノ゚