网站首页 > 技术文章 正文
介绍
本文目标是:
- 了解无论您使用哪种编码语言都适用的通用安全编码进行最佳实践。
- 了解使用 Go 编码时如何应对 OWASP 十大(2017)安全风险。
特别是这个:
- 了解数据清理和最佳实践。
- 了解输入验证和最佳实践。
在此先感谢您的时间!
通用安全编码最佳实践
在开始本节之前,我想强调以下几点:当你为生活而编码时,我真的认为你有责任在你的理解范围内尽可能地做到最好。希望这种理解将通过自我激励的学习不断增长。这包括拥有嵌入到您的编码实践中的安全注意事项。请记住,无论您编写什么代码,都反映了您的专业精神。此外,您的代码构成了一个应用程序,该应用程序可能会在现实世界中以一种或另一种方式影响/影响人们。以此为荣!
让我们开始!
实践涉及以下几个领域:
- 输入验证
- 输出编码
- 身份和认证管理
- 会话管理
- 访问控制
- 密码实践
- 错误处理、日志记录和指标
- 数据保护
- 通讯安全
- 系统配置
- 数据库安全
- 文件管理
- 内存管理
- 其他
请注意,此列表基于OWASP SCP 快速参考指南 (v2)。但是,您会找到的内容还包括多年来获得的知识,并突出了一些额外的要点。
输入验证
每当讨论输入验证时,数据清理都会与之共存。请注意,有些人也使用术语数据验证;不幸的是,它的用法并不一致,有时相当于输入验证,而其他一些则相当于数据清理。另外,我希望您记住,数据清理的应用因域而异:例如数据擦除、数据处理、数据隐私等。无论如何,我们需要澄清每个术语及其过程,我认为最好的方法是做它的上下文和例子。
对,所以,让我们考虑一个有表单的网站,并且在表单中只有一个用于电子邮件地址的输入字段。为了简单起见,我们假设一个真实的人填写了表单并点击了提交按钮。
在继续之前,我希望您考虑以下问题:
- 填写表格的人是普通用户还是恶意用户有关系吗?
- 或者,或者,如果一个脚本填写了表格?
两者的答案都是:不,不是。您应该始终为最坏的情况做好准备:默认情况下,所有输入的数据都是不安全的。有趣的是,有一个完整的对话与我之前的陈述有关:已知的已知、已知的未知和未知的未知。我不会在本文中讨论它,但是如果您有兴趣,请在评论部分告诉我。记住这一点,让我们继续!
在这个领域和上下文中,数据清理意味着:删除(或转换)任何具有恶意目的的数据(即字符)。换句话说,您希望数据在验证之前是安全的。但是,您应该始终考虑可用性和实用的方法。鉴于我们正在处理电子邮件地址输入字段,我们不能简单地从收到的输入中删除数据。因此,如果数据不合适,我们应该停止与数据相关的进程并向用户返回消息;消息应该提醒用户可以使用的字符(正面反馈)和/或在这种情况下,电子邮件地址的标准语法。
请记住,与数据相关的进程应始终在受信任的系统(例如后端)上进行,否则它们可能会被恶意用户/脚本禁用/绕过(例如前端)。
输入示例:
example<script>alert('Tacos!');</script>@domain.com
通过阅读上面的输入,我们可以直接判断这肯定不是电子邮件地址,而且它正试图通过数据传递脚本有效负载。但是,这种欣赏来自我们的视觉解读。
从编码的角度来看,应该通过应用以下前提来实施数据清理:什么是允许的?这也称为允许列表。建议在阻止列表的前提下使用这种方法:什么是不允许的?原因很简单:对于允许的和不允许的,你有一组已知的有限可能性。
在任何编码语言中实现允许列表的最有效方法可能是使用regex。
Golang 正则表达式示例:
package main
import (
"fmt"
"regexp"
)
func main() {
input := "example<script>alert('Injected!');</script>@domain.com"
re := regexp.MustCompile("^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*#34;)
fmt.Printf("Pattern: %v\n", re.String()) // print pattern
fmt.Printf("\nEmail: %v :%v\n", input, re.MatchString(input))
}
结果):
Pattern: ^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$
Email: example<script>alert('Injected!');</script>@domain.com :false
是的,所以,我们已经看到了如何使用 Golang 实现正则表达式。
是为了数据清理吗?不。
当您处理现实世界的应用程序时,您将不得不捕获其他类型的输入,具体取决于您的应用程序。因此,这里有六点需要考虑:
- 在执行数据清理之前始终执行数据规范化;规范化很重要,因为在 Unicode 中,同一个字符可以有许多不同的表示形式,这会对数据清理过程产生负面影响;请查看 Golang 编码示例的链接。
- 如果您接收路径(例如目录、链接等)作为输入,请在执行数据清理之前对其进行规范化;绝对或相对路径可用于恶意目的,因为它们可能包含文件链接,例如符号(软)链接、硬链接、快捷方式、阴影、别名和连接;因此,它们应该得到彻底的解决;此外,请记住您的方法并验证它是否适用于您预期的操作系统。
Golang 规范化示例:
package main
import (
"fmt"
"path/filepath"
)
func main() {
input := "/usr/local/bin/kubectl"
resolvedPath, _ := filepath.EvalSymlinks(input)
fmt.Printf("Input: %v :%v\n", input, resolvedPath)
}
结果):
Input: /usr/local/bin/kubectl :/usr/local/Cellar/kubernetes-cli/1.17.2/bin/kubectl
- “默认情况下所有输入数据都是不安全的”假设也适用于隐藏的表单字段、URL、HTTP 标头内容等。
- 请注意,可以尝试对您的系统进行双重编码或其他形式的混淆攻击,并且可以通过规范化来解决它们。
- 检查空字节:<%00>。
- 检查换行符。
数据清理结束后,应进行输入验证。正如术语明确指出的那样,输入验证确保数据遵守适用于/定义为一种输入类型的规则。这意味着什么……如果一种输入与知识领域或业务规则相关联,那么,应该强制执行其中规定的任何特征。对于我们根据存储能力或处理目的定义的规则也是如此:例如,我们允许为此类输入存储多少字符。
为了理解输入验证,让我们考虑一个有表单的网站,并且在表单中只有一个输入字段first name。同样,为了简单起见,我们将对表单的使用/填写做出与之前相同的假设。
输入示例:
John Alejandro Dumas Patricio O'Neil
这是一个非常有趣的例子。技术已经足以连接世界大部分地区,这在我们提供服务时产生了巨大影响。让我们从数据清理的角度开始。某些实现不允许使用 <'> 作为名字的一部分。就个人而言,我认为这没有考虑到全球化和连通性。用户不需要从外国访问网站,他/她的名字就不会符合“预期”的限制。我鼓励您阅读这篇文章,以便您做出适当的决定:世界各地的个人姓名
话虽如此,在数据清理之后可以进行什么样的输入验证?假设我们的数据存储中的名字有 30 个字符空间的限制。这个输入是否有效?
Golang 示例:
package main
import (
"fmt"
)
func main() {
input := "John Alejandro Dumas Patricio O'Neil"
fmt.Printf("First name: %v :%d\n", input, len(input))
}
结果):
First name: John Alejandro Dumas Patricio O'Neil :36
从上面的结果中,我们可以看出它不是一个有效的输入,因为它超过了允许的最大字符数。请注意,上面的实现是一个非常简单的实现,它也可以使用正则表达式来执行。我认为代码应该尽可能简单,但这取决于你想要实现你的方法有多“花哨”。
话虽如此,在输入验证方面还有几点需要您考虑:
- 无论您实现什么输入验证功能/方法,都让它们集中可用;这也适用于数据清理;理由是您希望在您的应用程序和团队中使用相同级别的标准。
- 所有验证失败都应导致输入拒绝。
- 验证数据类型和数据范围;确保在适当的时候进行边界检查。
结论
我们现在已经涵盖了这两个术语,那么它们与 OWASP Top 10 有什么关系呢?
输入验证和数据清理与以下内容直接相关:
- A1:注射
- A4:XML 外部实体 (XXE)
- A7:跨站脚本(XSS)
在下一篇文章中,我将介绍解决输出编码后的 OWASP 十大风险。
延伸阅读:
- 十大安全编码实践
- 前 25 个软件错误
希望您发现本教程很有用,如果您这样做了,或者如果您需要进一步的帮助,请不要犹豫,在下面的评论部分告诉我!再次感谢您的宝贵时间!
猜你喜欢
- 2024-11-02 武汉课工场大数据培训:Java正则表达式入坑指南
- 2024-11-02 Go语言进阶之路:并发爬虫,爬取空姐网所有相册图片
- 2024-11-02 golang常用库:gorilla/mux-http路由库使用
- 2024-11-02 golang 使用pprof和go-torch做性能分析
- 2024-11-02 Golang Gin 入门 (一)(golang官方教程)
- 2024-11-02 日志文件转运工具Filebeat笔记(日志转载)
- 2024-11-02 Linux 命令行下搜索工具大盘点,效率提高不止一倍
- 2024-11-02 SlimTrie:战胜Btree单机百亿文件的极致索引-实现篇
- 2024-11-02 Go的安全编程和防御性编程(输入验证和过滤)
- 2024-11-02 清华学神尹成带你学习golang2021(56)(Go语言测试命令)
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)