MIT 6.858 计算机系统安全讲义 2014 秋季(一)(1)

简介: MIT 6.858 计算机系统安全讲义 2014 秋季(一)

MIT 6.858 计算机系统安全笔记 2014 秋季

2014 年由Nickolai Zeldovich 教授James Mickens 教授教授授课的 6.858 讲座笔记。这些讲座笔记略有修改,与 6.858 课程网站上发布的内容略有不同。

  • 1讲:介绍:什么是安全,意义何在,没有完美的安全,策略,威胁模型,假设,机制,缓冲区溢出
  • 2讲:控制劫持攻击:缓冲区溢出,栈金丝雀,边界检查,电子围栏,胖指针,影子数据结构,Jones & Kelly,松松边界检查
  • 3讲:更多松松边界和返回导向编程:边界检查的成本,不可执行内存,地址空间布局随机化(ASLR),返回导向编程(ROP),堆栈读取,盲目 ROP,小工具
  • 4讲:OKWS:特权分离,Linux 自主访问控制(DAC),UIDs,GIDs,setuid/setgid,文件描述符,进程,Apache web 服务器,chroot 监狱,远程过程调用(RPC)
  • 5讲:渗透测试 嘉宾讲座 由 Paul Youn,iSEC Partners
  • 6讲:Capsicum:混淆副手问题,环境权限,能力,沙盒,自主访问控制(DAC),强制访问控制(MAC),Capsicum
  • 7讲:Native Client (NaCl):沙盒化 x86 本机代码,软件故障隔离,可靠的反汇编,x86 分段
  • 8讲:Web 安全,第一部分:现代网络浏览器,同源策略,框架,DOM 节点,cookies,跨站请求伪造(CSRF)攻击,DNS 重绑定攻击,浏览器插件
  • 9讲:Web 安全,第二部分:跨站脚本(XSS)攻击,XSS 防御,SQL 注入攻击,Django,会话管理,cookies,HTML5 本地存储,HTTP 协议的歧义,隐蔽通道
  • 10讲:符号执行 嘉宾讲座 由 Armando Solar-Lezama 教授,MIT CSAIL
  • 11讲:Ur/Web 嘉宾讲座 由 Adam Chlipala 教授,MIT,CSAIL
  • 12讲:TCP/IP 安全:威胁模型,序列号和攻击,连接劫持攻击,SYN 洪水攻击,带宽放大攻击,路由
  • 13讲:Kerberos:Kerberos 架构和信任模型,票证,认证者,票证授予服务器,更改密码,复制,网络攻击,前向保密性
  • 14讲:ForceHTTPS:证书,HTTPS,在线证书状态协议(OCSP),ForceHTTPS
  • 15讲:医疗软件 嘉宾讲座 由 Kevin Fu 教授,密歇根大学
  • 16讲:时序攻击:侧信道攻击,RSA 加密,RSA 实现,模指数运算,赛里斯剩余定理(CRT),重复平方,蒙哥马利表示,卡拉茨巴乘法,RSA 蒙蔽,其他时序攻击
  • 17讲:用户认证:你拥有什么,你知道什么,你是谁,密码,挑战-响应,可用性,部署性,安全性,生物特征,多因素认证(MFA),万事达卡的 CAP 读卡器
  • 18讲:私密浏览:私密浏览模式,本地和网络攻击者,虚拟机级隐私,操作系统级隐私,浏览器实现了什么,浏览器扩展
  • 19讲:Tor客座讲座,由 Nick Mathewson 主讲,Tor 项目
  • 2012 年的 6.858 课程笔记关于匿名通信:洋葱路由,Tor 设计,Tor 电路,Tor 流,Tor 隐藏服务,阻止 Tor,用餐密码学家网络(DC-nets)
  • 20讲:手机安全:Android 应用程序,活动,服务,内容提供者,广播接收器,意图,权限,标签,参考监视器,广播意图
  • 21讲:信息流跟踪:TaintDroid,Android 数据泄漏,信息流控制,污点跟踪,污点标志,隐式流,x86 污点跟踪,TightLip
  • 22讲:麻省理工学院信息服务与技术部 客座讲座,由 Mark Silis 和 David LaPorte 主讲,麻省理工学院信息服务与技术部
  • 23讲:安全经济学:网络攻击的经济学,垃圾邮件价值链,广告,点击支持,实现,CAPTCHA,僵尸网络,支付协议,道德

2015 年的新笔记

  • 8讲:英特尔软件保护扩展(SGX):隔离,Iago 攻击,飞地,证明,Haven

论文

我们阅读的论文列表(papers/):

  • 松松垮垮的边界检查
  • 盲目黑客
  • OKWS
  • 困惑的代理(或者为什么可能发明了能力)
  • 辣椒 (capabilities)
  • 本地客户端(沙箱化 x86 代码)
  • OWASP 前十名,最关键的 Web 应用程序安全风险
  • KLEE(符号执行)
  • Ur/Web(面向 Web 的函数式编程)
  • 回顾“TCP/IP 协议套件中的安全问题”
  • 凯伯罗斯:用于开放网络系统的认证服务
  • ForceHTTPs
  • 值得信赖的医疗设备软件
  • 远程时序攻击是可行的
  • 替代密码的探索
  • 私密浏览模式
  • Tor:第二代洋葱路由器
  • 了解 Android 安全
  • TaintDroid:一种用于智能手机实时隐私监控的信息流跟踪系统
  • 点击轨迹:垃圾邮件价值链的端到端分析

“新” 论文

其他论文

  • 赛里斯防火墙安全政策

介绍

**注意:**这些讲座笔记略有修改,来源于 2014 年 6.858 课程网站上发布的内容课程网站

什么是安全性?

  • 在对手存在的情况下实现某个目标。
  • 许多系统连接到互联网,而互联网上存在对手。
  • 因此,许多系统的设计可能需要考虑安全性。
  • 即,在有对手的情况下系统是否能正常工作?
  • 高层次的安全性思考计划:
  • **政策:**您想要实现的目标。
  • 例如,只有艾丽丝应该读取文件F
  • *常见目标:*保密性,完整性,可用性。
  • **威胁模型:**对攻击者可能做什么的假设。
  • 例如可以猜测密码,但无法物理抓取文件服务器。
  • 最好假设攻击者可以做某事。
  • **机制:**系统提供的旋钮,帮助维护政策。
  • 例如,用户帐户,密码,文件权限,加密。
  • **最终目标:**在威胁模型内部,对手无法违反政策。
  • 请注意,目标与机制无关。
  • 为什么安全性很难?这是一个负面目标。
  • 对比:检查是否实现了积极目标很容易,例如,艾丽丝实际上可以读取文件F。更难的是检查没有可能的方式让艾丽丝读取文件F
  • 你甚至如何开始列举艾丽丝可能读取文件的所有可能方式?艾丽丝可以利用多少层次的漏洞来获取文件F的访问权限。
  • 需要保证政策,假设威胁模型。
  • 很难想象攻击者可能如何入侵的所有可能方式。
  • 现实的威胁模型是开放式的(几乎是负面模型)。
  • 最弱的环节很重要。
  • 迭代过程:设计,根据需要更新威胁模型等。

如果我们无法实现完美的安全性,那有什么意义呢?

  • 在这门课程中,我们将推动每个系统的边界,看看它何时会崩溃。
  • 每个系统可能都会有一些导致妥协的破坏点。
  • 这并不一定意味着系统没有用:这取决于上下文。
  • 重要的是了解系统能做什么,以及系统不能做什么。
  • 实际上,必须管理安全风险与收益。
  • 更安全的系统意味着某些妥协的风险(或后果)更小。
  • 不安全的系统可能需要手动审计以检查攻击等。
  • 攻击成本越高,将有更多的对手被阻止。
  • 更好的安全性通常使新功能变得实用和安全。
  • 假设你想在系统上运行某些应用程序。
  • 大公司有时会禁止用户在其台式机上安装未经批准的软件,部分原因是出于安全考虑。
  • 浏览器中的 Javascript 是隔离的,这使得运行新代码/应用程序而无需手动检查/批准变得可以接受(或虚拟机,或本地客户端,或更好的操作系统隔离机制)。
  • 同样,VPN 使得减轻允许员工从互联网的任何地方连接到公司网络的风险变得实际可行。

出现问题的原因之一:政策问题

  • 雅虎电子邮件账户有用户名、密码和安全问题。
  • 用户可以通过提供用户名和密码登录。
  • 如果用户忘记密码,可以通过回答安全问题来重置。
  • 安全问题有时比密码更容易猜到。
  • 一些对手猜到了萨拉·佩林的高中、生日等信息。
  • 政策总结为:可以使用密码或安全问题登录。
  • (无法强制执行“只有用户忘记密码,然后…”)
  • Gmail 密码重置:向备用电子邮件地址发送验证链接。
  • 谷歌贴心地打印了备用电子邮件地址的一部分。
  • 马特·霍南的备用地址是他的苹果@me.com账户。
  • 苹果密码重置:需要账单地址,信用卡的最后 4 位数字。
  • 地址可能很容易获取,但如何获取用户信用卡号的 4 位数字?
  • 亚马逊:可以向账户添加信用卡,无需密码。
  • 亚马逊密码重置:提供用户的任意一张信用卡号。
  • 哈哈。
  • 亚马逊:不会打印信用卡号… 但会打印最后 4 位数字!
  • 对于合法用户来说,有时很难证明他们拥有一个账户!
  • 如何解决?
  • 仔细思考政策声明的含义。
  • 一些政策检查工具可以帮助,但需要一种指定不良内容的方法。
  • 在分布式系统中很困难:不知道每个人在做什么。

出了什么问题 #2:威胁模型/假设问题

  • 例子:未考虑人为因素。
  • 钓鱼攻击。
  • 用户收到一封要求续订电子邮件账户、转账或…的电子邮件。
  • 技术支持接到一个声音很像用户的电话要求重置密码。
  • 例子:计算假设随时间变化。
  • 麻省理工学院的 Kerberos 系统使用 56 位 DES 密钥,自 20 世纪 80 年代中期以来。
  • 当时,似乎可以假设对手无法检查所有 2⁵⁶ 个密钥。
  • 不再合理:现在大约需要 100 美元
  • 几年前,6.858 期末项目表明可以在一天内获取任何密钥。
  • 例子:所有 SSL 证书 CA 都是完全受信任的。
  • 要连接到启用 SSL 的网站,Web 浏览器会验证证书。
  • 证书是服务器主机名和加密密钥的组合,
  • 由某些受信任的证书颁发机构(CA)签名。
  • 浏览器信任的证书颁发机构(CA)长列表(数百个)。
  • 如果任何 CA 受到损害,对手可以拦截 SSL 连接。
  • 为任何服务器主机名创建一个“伪造”证书。
  • 2011 年,两个 CA 受到损害,为许多域(谷歌、雅虎、Tor 等)签发了伪造证书,显然在伊朗使用。
  • 2012 年,一家 CA 无意中签发了一个适用于任何域的根证书。
  • *例子:*假设你的硬件是可信的。
  • 如果 NSA 是你的对手,结果可能并不是一个好的假设。
  • *例子:*假设密码学中有良好的随机性。
  • 需要高质量的随机性来生成无法被猜测的密钥。
  • 问题:嵌入式设备、虚拟机可能没有太多的随机性。
  • 结果,许多密钥相似或容易被猜测攻击。
  • *例子:*颠覆军事操作系统安全。
  • 在 80 年代,军方鼓励研究安全操作系统。
  • 操作系统被破坏的一个意想不到的方式:
  • 对手获取了开发系统的访问权限,修改了操作系统代码。
  • *例子:*颠覆防火墙。
  • 对手可以连接到防火墙后面的不安全无线网络。
  • 对手可以欺骗防火墙后面的用户来禁用防火墙。
  • 可能只需点击链接http://firewall/?action=disable就足够了。
  • 或者也许在 CNN.com 购买广告,指向那个 URL(有效)?
  • *例子:*断开与互联网连接的机器安全吗?
  • Stuxnet 蠕虫通过 USB 驱动器上的特制文件传播。
  • 如何解决?
  • 更明确的威胁模型,以了解可能存在的弱点。
  • 更简单、更通用的威胁模型。
  • 更好的设计可能会消除/减少对某些假设的依赖。
  • 例如,不依赖完全信任 CA 的替代信任模型。
  • 例如,不容易受到钓鱼攻击的身份验证机制。

问题出在哪里 #3:机制问题–漏洞

  • 人们经常选择弱密码;通常可以在几次尝试(1K-1M)后猜中。
  • 大多数服务,包括苹果的 iCloud,会对登录尝试进行速率限制。
  • 苹果的 iCloud 服务有许多 API。
  • 一个 API(“查找我的 iPhone”服务)忘记实现速率限制。
  • 对手可以多次尝试猜测密码。
  • 可能和他们发送数据包的速度一样快:>> M/day.
  • 花旗银行允许信用卡用户在线访问他们的账户。
  • 登录页面要求输入用户名和密码。
  • 如果用户名和密码正确,将重定向到账户信息页面。
  • 账户信息页面的 URL 包含一些数字。
  • 结果这些数字与用户的账号相关。
  • 更糟糕的是,服务器没有检查您是否已登录到该帐户。
  • 对手尝试不同的数字,获取不同人的账户信息。
  • 可能是错误的威胁模型:与现实世界不匹配?
  • 如果对手通过浏览器浏览网站,系统是安全的。
  • 如果对手自己合成新的 URL,系统就不安全了。
  • 很难说开发人员是否有错误的威胁模型,或者有错误的机制。
  • 拥有所有者私钥的任何人都可以花费比特币。
  • 许多安卓上的比特币钱包应用使用了 Java 的SecureRandom API。
  • 结果系统有时忘记了给 PRNG 种子!
  • 结果,一些比特币密钥很容易被猜到。
  • 对手搜索可猜测的密钥,花费任何相应的比特币。
  • 例子:沙箱中的漏洞(NaCl,Javascript,Java 运行时)。
  • 允许对手逃离隔离,执行他们本不应执行的操作。
  • 例子:Moxie 的 SSL 证书名称检查漏洞
  • 空字节与长度编码。
  • 例子: 缓冲区溢出(见下文)。

案例研究:缓冲区溢出

  • 考虑一个网络服务器。
  • 通常情况下,网络服务器的代码负责安全性。
  • 例如,检查可以访问哪些 URL,检查 SSL 客户端证书,…
  • 因此,服务器代码中的漏洞可能导致安全妥协。
  • 威胁模型是什么,策略是什么?
  • 假设对手可以连接到网络服务器,提供任何输入。
  • 策略有点模糊:只执行程序员意图的操作?
  • 例如,不希望对手窃取数据,绕过检查,安装后门。
  • 考虑来自某个网络服务器的简化示例代码:

webserver.c:

int read_req(void) {
        char buf[128];
        int i;
        gets(buf);
        i = atoi(buf);
        return i;
    } 
  • 编译器在内存布局方面生成了什么?
  • x86 栈:
  • 栈向下增长。
  • %esp指向栈上最后(最底部)有效的内容。
  • %ebp指向调用者的%esp值。

read_req() stack layout:

+------------------+
    entry %ebp ----> | .. prev frame .. |
                     |                  |
                     |                  |
                     +------------------+
    entry %esp ----> |  return address  |
                     +------------------+
    new %ebp ------> |    saved %ebp    |
                     +------------------+
                     |     buf[127]     |
                     |       ...        |
                     |      buf[0]      |
                     +------------------+
                     |        i         |
    new %esp ------> +------------------+
                     |       ...        |
                     +------------------+ 
  • 调用者的代码(比如,main()):
  • 调用read_req()

read_req()的汇编代码:

push    %ebp
    mov     %esp -> %ebp
    sub     168, %esp        # stack vars, etc
    ...
    mov     %ebp -> %esp
    pop     %ebp
    ret 
  • 对手如何利用这段代码?
  • 提供长输入,覆盖超出缓冲区的栈上数据。
  • 有趣的数据:返回地址,被ret使用。
  • 可以将返回地址设置为缓冲区本身,在其中包含一些代码。
  • 对手如何知道缓冲区的地址?
  • 如果一台机器的内存是另一台的两倍会发生什么?
  • 幸运的是对手,虚拟内存使事情更加确定。
  • 对于给定的操作系统和程序,地址通常是相同的。
  • 如果栈向上增长,而不是向下,会发生什么?
  • 查看gets()的栈帧。
  • 一旦对手执行代码,他们可以做什么?
  • 使用进程的任何权限。
  • 经常利用溢出来更容易地进入系统。
  • 最初在 Unix 上,运行 shell /bin/sh(因此称为“shell 代码”)。
  • 如果进程以 rootAdministrator 运行,可以做任何事情。
  • 即使不是,仍然可以发送垃圾邮件,读取文件(Web 服务器,数据库),…
  • 可以攻击防火墙后面的其他机器。
  • 为什么程序员会写出这样的代码?
  • 旧代码,未暴露在互联网上。
  • 程序员没有考虑安全性。
  • 许多标准函数曾经是不安全的(strcpygetssprintf)。
  • 即使是安全版本也有陷阱(strncpy 不会在末尾加上空字符)。
  • 更一般地说,任何内存错误都可能转化为漏洞。
  • 在释放后继续使用内存(释放后使用)。
  • 如果写入,覆盖新的数据结构,例如函数指针。
  • 如果读取,可能会调用一个已损坏的函数指针。
  • 两次释放相同的内存(双重释放)。
  • 可能会导致 malloc() 之后再次返回相同的内存。
  • 将栈指针递减到栈的末尾之外,进入其他内存。
  • 一个字节的错误写入可能导致受损。
  • 甚至可能不需要覆盖返回地址或函数指针。
  • 可以足以读取敏感数据,如加密密钥。
  • 可以通过改变一些位来满足需求(例如int isLoggedInint isRoot)。

如何避免机制问题?

  • 减少安全关键代码的数量。
  • 不要依赖整个应用程序来执行安全性。
  • 将在实验 2 中进行。
  • 避免安全关键代码中的错误。
  • 例如,不要使用 gets(),而是使用 fgets() 可以限制缓冲区长度。
  • 使用常见、经过充分测试的安全机制(“机制的经济性”)。
  • 审计这些常见的安全机制(有很多动力这样做)。
  • 避免开发可能存在错误的新的一次性机制。
  • 良好的机制支持多种用途、策略(更有动力进行审计)。
  • 常见机制的示例:
  • 操作系统级别的访问控制(但是,通常可以更好)。
  • 网络防火墙(但是,通常可以更好)。
  • 加密,加密协议。

缓冲区溢出,松散的边界

注意: 这些讲座笔记略有修改,来自 2014 年 6.858 课程网站

缓冲区溢出攻击回顾

在上一讲中,我们看了执行缓冲区溢出攻击的基础知识。该攻击利用了几个观察结果:

  • 系统软件通常用 C 编写(操作系统、文件系统、数据库、编译器、网络服务器、命令外壳和控制台实用程序)
  • C 本质上是高级汇编语言,所以…
  • 暴露原始指针到内存
  • 不对数组执行边界检查(因为硬件不这样做,而 C 希望让你尽可能接近硬件)
  • 攻击还利用了关于 x86 代码如何工作的架构知识:
  • 栈增长的方向
  • 栈变量的布局(尤其是数组和函数的返回地址)

read_req.c:

void read_req() {
      char buf[128];
      int i;
      gets(buf);
      //. . . do stuff w/buf . . .
    } 

编译器在内存布局方面生成了什么?x86 栈看起来像这样:

%esp points to the last (bottom-most) valid thing on
  the stack.
  %ebp points to the caller's %esp value.
                     +------------------+
    entry %ebp ----> | .. prev frame .. |
                     |                  |  |
                     |                  |  | stack grows down
                     +------------------+  |
    entry %esp ----> |  return address  |  v
                     +------------------+
    new %ebp ------> |    saved %ebp    |
                     +------------------+
                     |     buf[127]     |
                     |       ...        |
                     |      buf[0]      |
                     +------------------+
    new %esp ------> |        i         |
                     +------------------+ 

对手如何利用这段代码?

  • 提供长输入,覆盖缓冲区后的栈数据。
  • 关键观察 1: 攻击者可以覆盖返回地址,使程序跳转到攻击者选择的位置!
  • 关键观察 2: 攻击者可以将返回地址设置为缓冲区本身,在其中包含一些 x86 代码!

攻击者在执行代码后可以做什么?

  • 利用进程的任何权限!如果进程以 root 或管理员身份运行,它可以在系统上做任何想做的事情。即使进程不以 root 身份运行,它也可以发送垃圾邮件、读取文件,有趣的是,攻击或破坏防火墙后面的其他机器。
  • 嗯,但为什么操作系统没有注意到缓冲区已经溢出?
  • 就操作系统而言,没有发生任何奇怪的事情!请记住,粗略地说,操作系统只在 Web 服务器进行 IO 或 IPC 时才被调用。除此之外,操作系统基本上只是坐下来让程序执行,依靠硬件页表防止进程篡改彼此的内存。然而,页表保护无法防止进程“针对自身”发起的缓冲区溢出,因为溢出的缓冲区、返回地址和所有相关内容都在进程的有效地址空间内。
  • 在本讲座的后面,我们将讨论操作系统可以采取的措施使缓冲区溢出更加困难。

修复缓冲区溢出

方法 #1: 避免 C 代码中的错误。

  • 难以或不可能实现。
  • 程序员应仔细检查缓冲区、字符串、数组等的大小。特别是,程序员应使用考虑到缓冲区大小的标准库函数(strncpy() 而不是 strcpy()fgets() 而不是 gets() 等)。
  • 现代版本的 gcc 和 Visual Studio 在程序使用不安全函数(如 gets())时会发出警告。一般来说,你不应该忽略编译器警告。 将警告视为错误!
  • 好处: 首先避免问题!
  • 坏处: 很难确保代码是无错误的,特别是如果代码库很大。此外,应用程序本身可能定义不使用fgets()strcpy()作为基本操作的缓冲区操作函数。

方法 2: 构建工具来帮助程序员找到错误。

  • 例如,我们可以使用静态分析在编译之前找到源代码中的问题。想象一下,如果你有这样一个函数:

foo.c:

void foo(int *p) {
        int offset;
        int *z = p + offset;
        if(offset > 7){
            bar(offset);
        }
    } 
  • 通过静态分析控制流,我们可以知道 offset 在未初始化的情况下被使用。
  • if语句还限制了我们可能传播到 bar 的偏移量。
  • 我们将在后续讲座中更多地讨论静态分析。
  • 提供随机输入的“模糊器”可以有效地发现错误。请注意,模糊化可以与静态分析结合以最大化代码覆盖率!
  • 坏处: 很难证明完全没有错误,尤其是对于像 C 这样的不安全代码。
  • 好处: 即使是部分分析也是有用的,因为程序应该变得更少有错误。例如,松散的边界检查可能无法捕捉所有内存错误,但它可以检测到许多重要类型。

方法 3: 使用内存安全语言(JavaScript,C#,Python)。

  • 好处: 通过不向程序员暴露原始内存地址,并通过自动处理垃圾回收来防止内存损坏错误。
  • 坏处:低级运行时代码确实使用原始内存地址。因此,运行时核心仍然需要正确。例如,堆喷射攻击
  • 坏处: 仍然有很多使用不安全语言(FORTRAN 和 COBOL)的遗留代码。
  • 坏处: 也许你需要访问低级硬件功能(例如,你正在编写设备驱动程序)
  • 坏处:性能比调优良好的 C 应用程序差?
  • 过去是一个更大的问题,但硬件和高级语言变得更好了。
  • JIT 编译万岁!
  • asm.js的性能接近本机 C++性能的 2 倍!
  • 使用谨慎的编码来避免关键路径中的垃圾回收抖动。
  • 也许你是一个不懂得如何选择合适工具的坏人/ 语言沙文主义者。如果你的任务是 I/O 绑定的,原始计算速度就不那么重要了。另外,不要成为那个用 C 语言编写文本处理程序的笨蛋。

上述 3 种方法都是有效且广泛使用的,但在实践中缓冲区溢出仍然是一个问题。

  • 大量/复杂的用 C 语言编写的遗留代码非常普遍。
  • 即使是用 C/C++编写的新代码也可能存在内存错误。

尽管存在有缺陷的代码,我们如何减轻缓冲区溢出?

  • 在“传统”缓冲区溢出中发生了两件事:
  • 对手控制执行(程序计数器)。
  • 对手执行一些恶意代码。
  • 这两个步骤存在哪些困难?
  • 需要覆盖一个代码指针(稍后被调用)。常见目标是使用堆栈上的缓冲区的返回地址。在实践中,任何内存错误都可能起作用。函数指针,C++ vtables,异常处理程序等。
  • 需要一些有趣的代码在进程的内存中。这通常比#1 更容易,因为:
  • 在缓冲区中放置代码很容易,因此
  • 进程中已经包含了许多可能被利用的代码。
  • 然而,攻击者需要将这段代码放在可预测的位置,以便攻击者可以将代码指针设置为指向恶意代码!


MIT 6.858 计算机系统安全讲义 2014 秋季(一)(2)https://developer.aliyun.com/article/1484145

相关文章
|
6天前
|
传感器 Web App开发 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(四)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(四)
33 1
|
6天前
|
存储 缓存 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(四)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(四)
25 0
|
6天前
|
存储 安全 Linux
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(4)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
59 0
|
6天前
|
存储 Web App开发 网络协议
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(3)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
40 0
|
6天前
|
存储 缓存 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
30 0
|
6天前
|
Web App开发 安全 JavaScript
MIT 6.858 计算机系统安全讲义 2014 秋季(三)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(三)
58 0
|
6天前
|
网络协议 安全 网络安全
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(4)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
30 0
|
6天前
|
存储 传感器 缓存
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(3)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
38 2
|
6天前
|
JavaScript 前端开发 安全
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(2)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
72 0
|
6天前
|
JavaScript 安全 前端开发
MIT 6.858 计算机系统安全讲义 2014 秋季(二)(1)
MIT 6.858 计算机系统安全讲义 2014 秋季(二)
90 2

热门文章

最新文章