XSS 攻击与防范
跨站脚本攻击
跨站脚本攻击,Cross-site scripting, 缩写 XSS, ( 以前的文档也有写作 CSS 的,但跟层叠样式表的缩写一样,为了区分,现在一般称作 XSS ),是一种非常常见的网络攻击方式,类似于 SQL 注入,也是一种注入攻击。
XSS 通过在网页中插入危险脚本,可以绕过同源策略之类的安全机制,获得执行危险操作的权限,达到攻击的目的。这些攻击可能涵盖访问敏感信息、篡改 HTML 内容、跳转到恶意网站、监控用户输入等等等,具有相当大的威胁。
攻击的逻辑
- 对于服务器来说,攻击代码是是一种普通数据(如一段 HTML 字符串),对服务器本身是没有特殊意义的,不会对服务器的行为有影响
- 对于客户端来说,攻击代码(如 HTML )是一种有特定意义的指令,会影响客户端的行为
- XSS 攻击通常会在客户端传递经过精心设计的恶意内容给服务器,这些数据会影响服务器正常组装 HTML、JavaScript、CSS 等指令代码的过程,让最终组装出来的指令代码包含恶意内容。
比如,通过传递经过巧妙设计的 URL 查询参数,让服务器使用该参数组装 HTML 标签时,意外提前闭合 HTML 标签,然后接续上一段攻击代码,这些包含攻击代码的 HTML 在浏览器上就反映为攻击。
XSS 的类型
XSS 根据特点,可以分为几种类型。
READ MORE...HTTP 请求报文
HTTP 报文结构
起始行
报文第一行内容即为起始行,请求报文和响应报文中有所区别
请求报文的起始行包含:
- HTTP 动作(GET, POST, PUT, DELETE, PATCH, …)
- 操作的资源
- HTTP 版本
例:
GET /example/example.jpg HTTP/1.1响应报文的起始行包含:
- HTTP 版本
- HTTP 状态码
- HTTP 状态描述
例:
HTTP/1.1 200 OK首部(headers)
首部内容紧接着起始行之后,每行代表一个首部字段。 一个 HTTP 报文可以拥有多个或者零个首部字段。
每个首部字段的结构是一个名值对,字段名后面跟着一个冒号,冒号之后是字段值。如:
Content-Type: text/html最后,首部以一个空行结束(即使后面没有 body 部分也不可省略)。
READ MORE...CSRF 攻击与防范
跨站请求伪造
跨站请求伪造 ( Cross Site Request Forgery, 缩写 CSRF ),是一种网络攻击方式。
原理上,它欺骗服务器,让服务器误认为攻击请求是用户自己发出的合法请求,以达到攻击的目的。
攻击的原理
- 用户登录 站点A。
- 没有注销 站点A 的情况下,访问包含攻击代码的 站点B。
- 站点B 向 站点A 发送包含敏感操作的请求,这时候浏览器会带上 站点A 的 cookie。
- 站点A 的服务器收到请求,通过 cookie 识别出了用户,开始执行请求的敏感操作。
我们可以发现,这里面的核心思想是,服务器没有或不能分辨包含敏感操作的请求是否是用户自己发出的。
防御攻击
既然明白了攻击的原理,那么就可以针对性的作出防御。核心在于,服务器需要甄别请求是否是用户自身发出的。
实践上有下面几种常见的防御手段。
READ MORE...Immutable.js
网络上找到的一张原理图:

- 对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象。
- 如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
- Immutable 实现的原理是 Persistent Data Structure(持久性数据结构)
- Immutable 使用了 Structural Sharing 来节省内存、提升效率(深拷贝效率低,内存占用大
全文完
READ MORE...阻塞、非阻塞IO,同步、异步IO
今天闲暇看 Node.js,看到这些概念,有些困惑的地方,Google 一番,做些笔记。 因为术业方向问题,可能理解有误,但记录下来便于日后复习的时候比对。
阻塞 IO (Blocking IO), 非阻塞 IO (Non-Blocking IO)
核心区别在于,发起调用的进程(或线程)是否会挂起等待 IO 完成。
下面举例说明用户进程发起一个 read 数据的阻塞 IO 操作的过程。 进程在发起系统调用后,就会一直干等。
- 首先等待 kernel 准备数据(如等待完整的网络数据包),这个阶段是 Blocking 的。
- 数据准备完毕后,kernel 将数据从缓冲区拷贝到用户空间,这个阶段也是 Blocking 的。
- 调用返回,用户进程也就解除了阻塞状态。
由上述过程可见,阻塞 IO 操作的流程很简单易懂,但也可以遇见,如果 IO 操作非常费时,那么用户进程在这个过程将会无法响应其他操作,这对某些应用来说,是无法接受的。
那么,一个非阻塞的 IO 又是怎么样的呢?
- 一个read的非阻塞IO,不会挂起用户进程,在 kernel 准备数据中的时候,收到系统调用后,会立即返回一个错误状态,用户进程不会被挂起,是Non-Blocking的。
- 发起调用的进程因为马上就能获得数据的准备的状态,因此可以周期性继续发起调用,直至 kernel 准备好数据。
- 当 kernel 准备好数据后,再接收到读取的调用的话,就会将数据拷贝到用户空间,这个阶段是Blocking的。
- 调用返回,圆满结束。
由上述过程可见,非阻塞 IO 操作的流程相比复杂一些,但因为用户进程不会被挂起,因此有机会在 IO 过程做其他事情,灵活很多。
同步 IO
通常情况下, 不论阻塞 IO 还是非阻塞 IO, 均是同步 IO。
异步 IO
着重说明下异步 IO, 因为这是我们 JavaScript 开发者接触最多的一个概念。
一个异步的 IO,发起调用后会立即返回,可以不必等待 IO 结果去做其他事情,当有结果之后,会收到一个信号通知,从而可以回头进入数据处理环节。
具体的流程如下:
- 发起异步 IO,立即返回,可以做其他事情
- kernel 会默默地准备数据、拷贝数据到内存用户空间,向用户进程发一个 signal 通知其IO已完成
- 调用发起者处理 IO 结果
由此可见,一个异步的 IO 全程不阻塞,也不必关心 IO 的过程状态,省心省事。
READ MORE...