麻省理工学院的课程“计算机系统安全”。 第11课:Ur / Web编程语言,第3部分

麻省理工学院。 讲座课程#6.858。 “计算机系统的安全性。” Nikolai Zeldovich,James Mickens。 2014年


计算机系统安全是一门有关开发和实施安全计算机系统的课程。 讲座涵盖了威胁模型,危害安全性的攻击以及基于最新科学研究的安全技术。 主题包括操作系统(OS)安全性,功能,信息流管理,语言安全性,网络协议,硬件安全性和Web应用程序安全性。

第1课:“简介:威胁模型” 第1 部分 / 第2 部分 / 第3部分
第2课:“控制黑客攻击”, 第1 部分 / 第2 部分 / 第3部分
第3讲:“缓冲区溢出:漏洞利用和保护” 第1 部分 / 第2 部分 / 第3部分
讲座4:“共享特权” 第1 部分 / 第2 部分 / 第3部分
讲座5:“安全系统从何而来?” 第1 部分 / 第2部分
讲座6:“机会” 第1 部分 / 第2 部分 / 第3部分
讲座7:“本地客户端沙箱” 第1 部分 / 第2 部分 / 第3部分
讲座8:“网络安全模型” 第1 部分 / 第2 部分 / 第3部分
讲座9:“ Web应用程序安全性” 第1 部分 / 第2 部分 / 第3部分
讲座10:“符号执行” 第1 部分 / 第2 部分 / 第3部分
第11课:“ Ur / Web编程语言” 第1 部分 / 第2 部分 / 第3部分

我们需要做的最后一件事,将是非常有启发性的,就是通过指示其中的room模块来更改此代码,然后像上一个示例一样尝试访问room表。 不允许使用此选项,因为不允许这样做。



这就像能够在Java中读取和写入私有类字段。 确实,我们收到了一条相当简单的消息,基本上是说这里我们有一个不相关的变量,即room参数的未知表达式。



我们可以提到这个附加模块,我们只是为了好玩而创建的。



但是,那将是不同的表。 我们可以轻松访问它。 因此,我将其分为两部分,我们将从简单地调用room方法开始,然后做一点不同的事情来读取其元素。



显示结果列表,反之亦然,这与程序以前的工作方式大致相同,不同之处在于使用各种数据类型。 让我们看看这带来了什么。 现在,我们回到第1会议室的聊天室,并在该行中输入所有消息。 您会看到它们全部显示没有错误。



也就是说,现在我们有了这个封装,因此您可以将这个房间的结构视为一个库,但是您不必担心。

有很多地方可能会破坏系统的内部不变性。 也许您希望在添加消息后它永远不会消失。 所有这些都在杂志上。 这种结构独立于其他代码(例如,编写聊天室模块的代码)提供此类属性。

学生:所以您更改了房间的定义,在这种情况下,数据库表会怎样?

教授:如果要保留旧数据,则必须手动运行alter table命令。 但是,当应用程序启动时,它将查询系统数据库目录并验证该架构是否仍符合预期。 然后,您将得到一个静态错误。 希望这为您提供了应该在数据库中更改的线索。

学生:但是它不会自动删除数据库或类似的东西吗?

教授:我希望不会。 我认为编译器不应该这样做。 您可以想象自定义编译器以了解数据库的演变。 我认为您需要编写alter table命令才能启动,因为编译器现在不这样做。



现在,我们来谈谈跨站点请求伪造及其预防。 实际上,在执行此操作之前,让我们看一下此页上的代码。 这里有一个传统的HTML表单。 而且,当然,没有针对跨站点请求伪造的保护措施,我认为这很好。 因为据我所知,伪造跨站点请求的问题是应用程序随每个请求发送的隐式上下文。

假设有某种不知道您的隐式上下文的攻击者。 举一个非常简单的例子,假设您的密码存储在cookie中。 当攻击者在单击所需链接时欺骗您时,浏览器会自动发送一个隐式上下文,并强制应用程序执行攻击者无法直接执行的操作。



在这种情况下,没有隐式上下文,因此没有伪造跨站点请求的风险。 在我继续之前,是否有人想挑战系统的此功能? 对我来说可能非常有用。 如果不是,则在此处添加隐式上下文。 在这种情况下,系统将根据对程序的分析自动采取正确的对策,该程序可以理解现在存在隐式上下文。

现在,我将在此处插入Cookie。 实际上,作为模块封装的另一个示例,我将在这里放置一个完整的用户身份验证系统,在该系统中,我们拥有用户帐户以及标识符和密码的抽象类型。 因此,您不能简单地直接创建任何这些数据类型的值。 您将必须通过一些认可的方法来构造这些类型的值。

我将把桌子放在签名中。 我还将对此加以限制,说它的关键是ID表格。



但是事实是,在此用户表中,ID和密码是抽象数据类型。 因此,该代码看不到密码,并且无法一致地生成所有标识符并在此表中尝试使用它们。 由于它使用抽象类型,因此无法确定ID的外观,也无法找到密码。 它们只是来自此表,它们是不透明的标记。

但是我们可以允许它们作为污水的输入。 您可能希望允许在字符串和这些类型之间进行一个方向的转换。 现在,我将在这里做一些事情,主要是细节,并且我将不解释它们。 但这就像声明您被允许将字符串转换为ID一样。 对于那些熟悉Haskell的人来说,这是一个即时类型类,具有将字符串转换为ID的权限。



我们不会再申请其他权限,因为我们不希望能够将ID转换回其他内容。 让我们对密码进行相同的操作。 我们希望能够读取用户的密码,但是我们不会接受该密码并将其转换为一个字符串,该字符串将告诉我们用户已进入聊天。

因此,代码的其他部分将能够接受来自用户的密码,将其转换为这种类型,并将其传输到用户模块以进行验证。 但是他们做不到的是查询用户表,并以他们可以提取其文本表达形式的形式获取所有密码。

然后,我们可以有一个登录方法,该方法接受ID和密码这两个组成部分,并且仅作为副作用,这实际上在代码中已说明。 我们还将需要一种方法来找出哪个用户已注册。 这是执行创建ID的事务的代码。



第一步是简单地复制此定义。 然后是一个惊喜。 事实证明,用户ID和密码是字符串,但是这种情况不会在模块外部公开。



现在,我们将创建cookie。 Cookies是该语言内置的另一件事。 实际上,它们充当可变的全局变量,每个使用您的应用程序的客户端都有一个副本。

因此,我们将创建一个cookie,该cookie将为每个用户简单地存储我们在此处具有的两个相同字段的副本。



这些cookie是此模块专用的。 代码的其他部分将无法读取Cookie,因为它们根本没有此私有字段。 因此,没有人能够直接看到为该用户保存的ID和密码。 但是,当查看各种页面时,它们将被保存,就像普通的cookie一样。

现在,我将插入登录功能,该功能将启动检查数据库的过程,并确定这是否是正确的用户名和密码对。 此过程仅检查我们是否可以在数据库中找到包含此用户ID和密码的行。

如果我们找到它,那么好,那么这就是正确的含义。 让我们将其保存在cookie中。 我们使用一种更改Cookie值的方法。 而且我们必须在此处放置一些内容,为简单起见,我将说此cookie不会过期。 我不想在这里运行SSL,因此我想说在这种情况下我们不需要安全性,请将参数设置为Secure = false。

但是,如果您真的关心安全性,那么显然您将编写Secure = true。 如果检查失败,并且模块发出错误信号,程序将停止,并给出此错误的说明。



最后,我们可以创建此函数,该函数通过接收当前cookie值来告知哪个特定用户已登录。 如果用户尚未登录,也可以将此参数设置为none,在这种情况下,我们将收到另一条错误消息。 或者它可能是我们上面使用的确切类型的某种记录。 因此,我将其复制到此处并运行相同的检查。 如果这行得通,那么我们只需返回我们刚刚在数据库中检查过的那部分ID记录。



因此,让我检查一下。 我们启动编译器,您会在屏幕上看到结果。



所有这些实施细节的核心。 但是在此模块之外,我们从接口的角度考虑它。 ID和密码有一些未知的类型。 此用户表表示允许您将字符串转换为标识符和密码的术语,反之亦然。 我们有两种方法可以首先输入登录名,并且在此阶段检查哪个用户已登录。 对这个有疑问吗?

学生:您是否需要扩展用户表?

教授:之所以这样做,是因为我以后想将其用作外键,所以这不是重要的原因。 因此,我们几乎可以向您展示CSRF保护的实际应用。

首先,登录系统非常容易。 好吧,我们现在在程序中还能做什么? 让我们在这里添加页面的另一部分,这是您输入登录名的地方。 在这里,您必须输入用户名和密码,然后单击“提交操作”按钮。 此操作将提供对登录功能的调用。



让我们将登录定义为执行这些操作的函数。 实际上,这只是从该模块调用login函数的包装,在该模块中,我们采用了每个组件,并将其从字符串转换为抽象类型。



她检查阅读错误。 该错误表示如果登录不起作用,此刻操作将被中断,该功能将返回到程序的主要部分。
现在我们可以登录。 我们可能想要创建一个允许我们登录的帐户,所以让我创建一个用户名a和密码a的用户。





现在,我可以以用户a身份登录,请相信我。 我们有一组Cookie来记录此信息,因此让我们进入聊天室并发送一条消息,例如asfasf。 您会看到,单击“添加”按钮后,它便出现在聊天室中。



实际上,我们没有在此处添加任何访问控制,因此此处没有发生任何特殊情况。 但是我们可以检查。



这里有cookie,但是系统已确定我们不使用cookie。 当我们提交此表格时,cookie是不可读的。 因此,到目前为止,这里无需添加CSRF保护。 因此,现在我们需要添加一种使用cookie的方法,并查看保护将如何表现出来。

学生:什么是Cookie内容?

教授:这是您希望从代码中收到的内容。 换句话说,cookie被声明为具有此记录的类型-标识符和密码。



因此,这正是其中包含的某种序列化形式。 现在,让我们实际使用cookie。 尽管我们将间接使用cookie,但我们应该看到这一点,因为我们将在room模块中使用它,它与cookie没有关系。 但是我们将调用与cookie的使用间接相关的自定义模块方法。 然后系统将了解这意味着我们依赖它。

因此,让我们非常简单地进行操作,并调用whoami方法。 实际上,我只是忽略它,反之亦然,让他做点什么。 让我们确定我们创建的用户真的很特别,只有该用户可以发布任何内容。 如果不是这种情况,那么我们将收到一条错误消息。



我将向用户模块添加一个ID,然后应该可以使用,因为ID类型支持相等性检查。



现在一切都应该井井有条,我们可以使用此ID进行更多操作,这可能会导致一些安全问题。



这使我们可以添加访问控制检查,因此让我们看一下它的工作方式并返回主页。



现在,这四个字母“ a”出现在聊天中。

在界面控制台中,我们看到表单现在已自动接收到隐藏的输入名称sig,这是所有cookie值的加密签名。 此sig使用服务器专有的密钥对cookie进行签名。 并且,当表单准备就绪时,应用程序会知道-因为编译器已告知它-应用程序应检查签名以检查下一组操作。 为此,我们有一个发言权操作。



学生:签名有时间戳吗?

教授:不,签名没有时间戳。

学生:在这种情况下,如果攻击者设法“间谍”了这些数据,则他可能会假装成为用户,因为这些cookie永远不会过期。

教授:是的,它永远不会过期。 只需更改语言实现而不更改应用程序,然后快速部署它,就可以更改此内容。 但这现在不在这里。 而且我了解为什么添加此功能会很有用。

学生:您还可以通过在签名上简单地添加时间戳来解决此问题。

教授:是的,您是对的,您可以通过更改应用程序的方式来足够频繁地有意更改Cookie数据,即使签名过期。
学生:您可以重新分配URL吗?

教授:是的,您想看什么调动?

学生:任何,我只想看看如何完成。

教授:因此,编译器分配...如我们所见,我们称say函数,该函数调用被序列化为特定形式的URL。 假设我们不喜欢这种形式。



我们决定要重写URL,可以这么说,在room模块中,在演示中。 最好坚持下去。 因此,我们想将URL分配给Demo / Room /说给Demo / Room / Speak。



我们启动编译器,然后转到应用程序的主屏幕。 让我们看看会发生什么。 一切都井井有条,我们还可以输入任何短信,它们会出现在聊天行中。 在这些规则中,可以使用不可预测的字符将一个前缀替换为另一个前缀,并且编译器将确保每个函数都有单独的URL方案,但是默认情况下会自动生成URL。

学生:您提到HTML并非特定于编译器,它只是一个库。 是否有其他格式的其他库?

教授:还有其他一些库,它们不检查具有相同功能完整性的类型,但是,例如,有一个用于序列化和反序列化JSON的库,以及许多用于管理类型结构的自动化方法。 这样,您可以执行未集成到编译器中的操作。

学生:假设我们仍然想用JavaScript编写,例如,使页面上的某些东西动画化……

教授:让我下载这个的Ajax版本,它将回答您的问题。 此版本具有客户端代码。 让我们继续前进到名为demo3的程序版本。 我在聊天行的主页上输入了数据,它们也出现在聊天的底部。 信不信由你,这次加载项通过Ajax调用工作。 这是由于按钮标签的按钮值。 它具有onclick属性,当用户单击按钮时,具有该属性的行下方的所有这些代码都可以在客户端使用。

]

但这是Ur / Web代码,这不是JavaScript代码。 如果用户不想在浏览器中手动修改该属性,则编译器会为您将其翻译为JavaScript,并确保将所需的抽象属性保存在列表中。

学生:我认为,如果您想自己重新编码所有内容,那么今天有许多库在做有用的事情,在许多情况下是复杂的事情。 它们与Ur / Web的JavaScript有什么交互方式?

教授:是的,有一个外部函数接口,可让您将Ur / Web函数名称提供给JavaScript函数名称和调用。 但是,当您使用外部函数的接口时,您将无法再使用所有这些有用的构造函数。 在这种情况下,您必须非常小心。

您必须了解其中一些抽象的实现,以免干扰它们。 只要我有这段代码,就让我向您展示其他内容。

我们仍然具有与以前相同的话语功能。 但是现在,我们不再进行引用调用,而是进行了一个函数调用,该函数调用中填充了来自onclick处理程序上下文的参数。



我们只是将此函数包装在rpc语法中。 这意味着这是一个客户端调用函数,但是调用本身是在可访问数据库和其他服务器资源的服务器上启动的,然后将结果传输回此处。

, , JavaScript .
, . , , , .



, , , . , , .

, - , . GUI , , , , .

, , , . , DOM. , , .



, GUI, , , , .

, , .

: ?

: , , . , - .

: . , ?



: — . , . , , . , .

: — Ur?

: Ur — , , . , . .


.

感谢您与我们在一起。 你喜欢我们的文章吗? 想看更多有趣的资料吗? 通过下订单或将其推荐给您的朋友来支持我们, 为我们为您发明的入门级服务器的独特模拟,为Habr用户提供30%的折扣: 关于VPS(KVM)E5-2650 v4(6核)的全部真相10GB DDR4 240GB SSD 1Gbps从$ 20还是如何划分服务器? (RAID1和RAID10提供选件,最多24个内核和最大40GB DDR4)。

VPS(KVM)E5-2650 v4(6核)10GB DDR4 240GB SSD 1Gbps至12月免费,在六个月内付款,您可以在此处订购。

戴尔R730xd便宜2倍?在荷兰和美国,我们有2台Intel Dodeca-Core Xeon E5-2650v4 128GB DDR4 6x480GB SSD 1Gbps 100电视(249美元起) 阅读有关如何构建基础架构大厦的信息。 使用价格为9000欧元的Dell R730xd E5-2650 v4服务器的上等课程?

Source: https://habr.com/ru/post/zh-CN426001/


All Articles