如您所知,BlackHat黑客的大多数攻击旨在破坏Web应用程序和服务的服务器数据。 同时,至少在今天,客户端受到了攻击。 根据干燥的定义,任何攻击都是黑客针对网络和数据传输,数据及其替代,网络应用程序实现的基础结构和技术功能而采取的一系列措施。 因此,国际公司要求开发工程师对客户端应用程序的安全性采取更负责任和彻底的方法。
在我的项目示例中,我将讨论客户端应用程序今天如何受到攻击以及如何避免这些威胁。
2013-2017年的十大威胁。如您所见,在主要威胁中,注入,错误触发,身份验证绕过和不安全的机密数据居于首位。 使用具有已知漏洞的组件的威胁仍然很重要。 还出现了新的威胁:访问控制机制遭到黑客攻击,数据不安全的反序列化和序列化,详细的日志记录和监控不充分。
2001年,Mark Curfy和Dennis Groves创立了OWASP (开放Web应用程序安全项目)。 这是一个国际性的OpenSource项目,旨在交流有关消除客户端应用程序中的漏洞的经验,众多应用程序安全工程师参与其中。 OWASP社区在门户中填充了大量文章,其中包含漏洞信息,培训材料,用于测试和消除攻击的工具。 描述了真实的攻击,揭示了它们的各个方面,并描述了需要采取哪些措施来防止威胁。
要了解什么威胁对项目是危险的,您需要对其进行彻底的测试。 为此,网络具有可自动识别某些漏洞的应用程序,框架和在线服务。 对于本地测试,我建议使用应用程序和框架,对于正在运行的项目进行测试,添加在线服务也非常有用。

但是,即使测试工具没有在报告中告诉您重大漏洞(不太可能),仍然要注意在版本控制系统中存储敏感数据,构建应用程序,身份验证机制,密码哈希算法,敏感数据加密以及日志记录系统并监视整个Web应用程序。 在这种情况下,最好发挥安全性,不要盲目相信自动化。
吉特
首先,让我们谈谈Git中的敏感数据。 理想情况下,分配一个单独的机密存储库来存储敏感数据。 在调试组装过程中,从中提取机密数据并将其缝入应用程序中。 如今,Hashicorp Vault,Keywhiz,Docker机密,Azure Key Vault和许多其他产品很受欢迎。
但是,如果您没有这样的存储空间,该怎么办? 您可以使用工具来编码和隐藏具有机密信息的文件,这些信息将扩展版本控制系统的功能。
首先想到的是通用的BlackBox解决方案。 它可以与任何版本控制系统一起使用,例如Mercurial,Git等。 另外,Git有两个扩展:git-crypt和git-secret。 我建议使用第二个,因为在我看来,它在官方文档中使用起来最方便且更易理解。 安装git-secret之后,您需要在Git存储库中对其进行初始化。 切记在.gitattributes文件中指定要使用的扩展名。 接下来,配置机密的可访问性:确定要向其提供对敏感数据的访问权限的用户。 然后添加包含敏感数据的文件,并通过git-secret-hide
它们。 您可以通过git-secret-reveal.
获取隐藏文件git-secret-reveal.
brew install git-secret //
git secret init //
git secret tell your@gpg.email  //
git secret add <files...> //
git secret hide  //
git secret reveal  //
Webpack
消除威胁的另一种方法是正确配置Webpack。 为了防御XSS,XEE和类似的攻击,您需要考虑遵守CORS(跨域资源共享)和CSP(内容安全策略)策略。 在这两种情况下,跟随标题很重要,以便检查项目中使用的某些脚本的真实性。 浏览器具有检查特定来源可靠性的机制,例如,如果未正确配置CORS和CSP,Safari将在每个步骤中发出警告。
有两种方法可以符合CORS和CSP。 第一种是在服务器端配置头以响应请求。 第二个是通过元标记和属性注册两个策略。 如果您有懒惰的后端开发人员,他们总是很忙并且对安全策略不感兴趣,则建议使用后一种方法。 构建应用程序时,可以立即注册元标记。 诸如html-webpack-plugin,html-webpack-exclude-assets-plugin,script-ext-html-webpack-plugin,csp-html-webpack-plugin和crypto之类的插件将帮助我们实现这一目标。 另外,如果您的项目中有第三方资源(例如,链接到CSS中使用的外部字体;从CDN加载的资源,等等),那么我建议您也使用webpack-subresource-integrity-plugin。 因此,您将通知浏览器,脚本中已加载的资源是可靠的,其中没有注入,它们是完整且未损坏的。 即使有人将恶意数据注入到资源中,并且您将其上传,您也必须为此做好准备,并保护您的项目免受此类威胁。
我要特别注意插件的类实例的创建顺序。 顺序应如下所示:
const SHA256 = (str) => CRYPTO.createHash('sha256').update( str, 'utf8').digest('base64'); const sha256Str = SHA256( '' + Date.now() ); […] new HtmlWebpackPlugin({ filename: 'index.html', template: 'public/index.html' }), new ScriptExtHtmlWebpackPlugin({ custom: [{ test: /\.js$/, attribute: 'nonce', value: 'nonce-' + sha256Str }] }), new HtmlWebpackExcludeAssetsPlugin(), new CspHtmlWebpackPlugin({ 'base-uri': '\'self\'', 'object-src': '\'none\'', 'script-src': ['\'self\'', '\'unsafe-eval\'', '\'nonce-' + sha256Str + '\''], 'style-src': ['\'unsafe-inline\'', '\'self\''] }, { devAllowUnsafe: false, enabled: true, hashingMethod: 'sha256' }), new SriPlugin({ hashFuncNames: ['sha256', 'sha384'], enabled: true }), […]
然后,在组装期间, <hed>
将显示http-equiv=content-security-policy
元标签。 指令将写在content
属性中,该属性说明可以信任哪些脚本和资源。
base-uri
指令显示了哪个基本URL用于加载脚本,CSS,图像等。
对象通常不加载,因此请不要将其设置为object-sr
c指令。
script-src
指令适用于JS脚本。
不要忘记每次注册一个类型为nnce-<hshVlue>
的属性。 此外,必须使用SHA256或SHA512算法计算哈希。
至于style-src
指令,我们的项目有一个特点:我们使用样式化组件为每个组件编写CSS并将它们彼此隔离。 因此,有必要指定在style-src
中使用unsafe-inline
和self
style-src
,否则样式组件将掉线。

script
标签将自动设置为nnce-<hshVlue>
, integrity
和cross-origin
。 他们告诉浏览器资源正在从可靠来源中获取。 否则,如果浏览器发现资源与CSP或CORS不匹配,那么它将根本不会加载此脚本或CSS文件,它将在控制台中写一些内容,例如: “请注意此脚本,在此行中进行初始化他。 看,你出了点问题!” 。
MDN ,OWASP和W3C文档提供了实施CSP和CORS策略的指南。 此外,任何渗透测试工具都将报告项目中是否符合CORS和CSP规则。 任何将对项目进行自动测试的框架或工具都将指出缺陷。
用户认证
我们使用OpenID Connect和Kerberos协议。 相当普遍的OpenID标准用于认证外部用户。
Kerberos更适合内部网络,在银行中,它用于对员工进行自动身份验证。 假设有一个本地计算机,组织的员工在该计算机上工作。 他在这台计算机上进行了一次身份验证,然后就无需在任何地方再次输入登录名和密码:员工登录到任何应用程序,系统都会立即对其进行身份验证。 Kerberos对本地计算机具有微妙的设置,这很困难,因为必须为每台计算机和每个浏览器进行配置。 如果Internet Explorer通常拉出默认设置,而Chrome拉起IE设置,则Firefox必须单独进行配置。 MacOS X上的Safari会自行找到设置,但Windows上的Safari则需要手动指定设置。
您需要在所有浏览器中检查应用程序,无论它在任何地方都可以正常工作。 例如,如果我使用Windows,则在本地安装Safari并在其中测试我的项目;如果使用Mac,则在虚拟机中提升Windows,以在相应版本的浏览器上运行该应用程序。
可以使用Passport.js和express-session程序包以及Auth0 SDK在现代应用程序中实现身份验证。
如果您无法通过OpenID Connect或任何其他协议开发身份验证服务,请使用Proxy0之类的代理层,以便通过专门为用户提供对Internet资源的安全访问权限的第三方公司进行身份验证。
当我们将某些应用程序升级到Node.js时,建议在服务器上使用Passport.js,express-session等软件包。 为了确保客户端的安全性,我们独立提出了用于身份验证的组件。 不要忘记在身份验证表单上指定自动完成关闭属性,以排除表单字段的自动完成。
密码哈希
OWASP网站建议您不要使用数据库中内置的密码哈希机制。 为此,最好使用Argon2,PBKDF2,ccrypt和bcrypt之类的软件包。 在我的实践中,我使用Argon2-这是GCC,PGP / GPG算法等的包装,但是它要求您首先安装GCC软件包。 Argon2使用方案:
1. GCC >= 4.8 install $ brew install gcc
2. - $ npm install -g node-gyp
3. Argon2 $ npm install argon2
4. import * as ARGON from 'argon2'; ARGON.generateSalt().then( (salt: string) => { ARGON.hash('some-user-password', salt) .then((hash : string) => { console.log('Successfully created Argon2 hash:', hash);
混淆
混淆允许您修改代码,以便无法将其解析为组件。 毕竟,攻击者-不仅是攻击者-经常使用逆向工程:程序员获取一些JS文件并开始分析源代码。 因此,他可以学习使用的方法或了解特定脚本的工作机制,以实施恶意代码。 或使用这些机制来入侵Web应用程序并进行隐身攻击。
黑客不会惹上麻烦。 首先,他们对资源进行探索,确定漏洞和攻击媒介。 例如,他们操纵数据或利用传输协议中包含的漏洞。 攻击媒介可以针对特定操作系统的漏洞;任何UNIX系统中都有很多漏洞。 但是,只有在管理员配置的安全策略配置不正确(例如,错误地设置了外部URL)时,才能使用漏洞。
因此,对于侦察,使用逆向工程。 完全排除它是不可能的,但是却很难。 为此,在我的情况下,使用了各种混淆器-javascript-obfuscator。 在此基础上,制作了webpack插件-webpack-obfuscator。 也为webpack创建了混淆器加载器。 该软件包针对不同级别的偏执狂推荐了设置:低,中和高,可在官方网站上找到。 如果使用此混淆器,请记住它与webpack内置的缩小机制一起使用时效果很差。 不要同时使用缩小和混淆,否则混淆器会完全破坏脚本代码。
另外,混淆器增加了脚本的数量及其加载。 在这里,您需要自己做出决定:要么增强安全性,稳定性和可靠性,但又失去便利性和速度。 要么在乎速度,但在安全方面却忘了遵循任何准则。
威胁记录与监控
存在诸如使用已知漏洞的软件包之类的威胁。 威胁分析器(例如npm audit,Snyk和LGTM)将在这种情况下提供帮助。 Npm audit是npm内置的标准实用程序,但是您必须不断调用此命令或提出拐杖。 因此,我建议您使用Snyk。 该项目有其自己的数据库,存在漏洞。 当您开始测试时,Snyk将访问此数据库并将报告秘密上载到您的Snyk项目,而外部人员则无法访问该项目。 没错,您只能免费检查项目300次,并且当您检查每个预提交时,这300次免费尝试很快就会结束。 因此,最好对预推或预合并挂钩进行测试。
人是任何系统中最重要的漏洞。 因此,请确保在开始构建应用程序之前检查项目,因为即使源代码也可能包含恶意软件。 只有一个人可以访问该项目,这很好,但是通常我们作为团队工作。 如果出现某种“好心人”,决定“美丽地”离开公司并留下印记,该怎么办? 还必须牢记这一点。
我建议从项目一开始就使用Snyk程序包,然后从控制台开始扫描。 一切都很简单:安装后,设置帐户的登录名和密码,然后可以像这样执行测试:
- 在安装了npm我snyk —D依赖项并在package.json中指定“ snyk”:true后,运行:
./node_modules/.bin/snyk wizard --dev
{ ... "scripts": { ... "test": "npm run test:snyk && npm run test:jest", ... "test:snyk": "snyk test --dev", ... "prepare": "npm run prepare:snyk", "prepare:snyk": "snyk protect" }, "husky": { "hooks": { "commit-msg": "commitlint -E HUSKY_GIT_PARAMS", "pre-commit": "npm run test:snyk && npm run lint && npm run test:jest", "pre-push": [ "npm run test:snyk", "npm run lint", "npm run test:jest", "npm run build:production" ], ... } }, "snyk": true }
上面,我们查看了本地检查是否存在安全威胁。 要检查软件包中是否存在已知威胁,我还建议使用LGTM。 将此项目与GitHub或Bitbucket结合使用(直到您尝试了,没有必要),并且每次推送都会立即检查代码。
应用监控
在前端领域,这些工具已经非常完善;可以使用各种口味的工具来记录和监视客户端部分。 最著名的是Sentry,TrackJS和InsightOps。 Sentry Server可以部署到其物理服务器。 例如,在我们的两个项目中,我们使用了单独的服务器,该服务器已完全配置为记录应用程序的操作。 我们转到该URL,并将所有日志都放在那里。 如果应用程序中发生错误,则将其包装在try catch块中,并通过raven软件包方法发送到Sentry服务器。 一切都很简单方便。 如果您看到未注册的Sentry中晦涩的URL,或者看到嵌入或晦涩的邮件,则表示它们正在试图入侵您。 在我的实践中,这经常发生。 例如,一个项目-一种绕过广告拦截程序和防病毒软件的服务-一直在试图抵消和破解它。
为了进行监视,我还建议使用Grafana。 重要的是要考虑一个将由该系统监视的标准和指标系统。 我们在流量,广告返还,渲染广告的程度,Yandex发出的横幅数量等方面进行了调整。 (Rambler Group中的项目)。 我们需要了解Yandex如何处理我们的请求,因为它是第三方服务,这意味着需要对其进行监视,因为如果失败,则整个项目可能会完全崩溃。
如果您监视与第三方服务的所有通信,则将很快发现任何错误。 故事来自我的实践:从Yandex中我们看到,广告反应急剧停止。 原来,他们存在技术故障,整个广告网络都崩溃了。 并不是Yandex首先通知了我们,但我们打电话给他们并要求他们查看他们的服务正在发生什么。
监视的最佳方法是什么? 使用一些小的URL,编写GET参数,然后向该URL发送GET请求。 在服务器端,处理此URL,将日志写入数据库,然后对Grafana进行监视。 一切都很简单。
仅此而已。 将来,我将尝试继续撰写有关保护Web应用程序免受威胁的主题。 对于读完所有文章的所有人-希望您的项目安全)))
有关该主题的阅读资料清单:
www.owasp.org/index.php/Main_Page
tproger.ru/translations/webapp-security
S.老鹰队。 更快的单页应用程序:安全性
Seacord,RobertC。CERTC安全编码标准/ Robert C. Seacord。 -2008年
Chetan Karande。 保护节点应用程序-2017
史蒂文·帕尔默 Web应用程序漏洞检测,利用,预防-2011
罗伯特·西蒙斯基(Robert Shimonski),肖恩·菲利普·奥里亚诺(Sean-Philip Oriyano)。 客户端攻击和防御-2012
马库斯·平托(Marcus Pinto),达菲(Dafydd Stuttard)。 Web应用程序黑客手册:查找和利用安全漏洞,第二版-2011
卡尔·杜纳(Karl Duuna)。 保护您的Node.js Web应用程序-2015