一次渗透测试发现的安全问题
摘要:前段时间在Azure Cloud上线了一个Web项目,因为该项目对安全性要求比较高 ,所以客户那边申请了一个Azure Cloud的渗透测试,没想到测试报告出来后,报了10来个问题,然后客户在会议上把我和后端老哥公开处刑了一番 ,还说在测试环境能看到我的代码,直接社死。不说了,下面就来看看几个相关问题吧。1 Clickjacking问题
先看一下什么是Clickjacking
Clickjacking(点击劫持),也被称为UI-覆盖攻击。这个词首次出现在2008年,是由 互联网安全专家罗伯特·汉森和耶利米·格劳斯曼首创的。
它是通过覆盖不可见的框架误导受害者点击。
虽然受害者点击的是他所看到的网页,但其实他所点击的是被黑客精心构建的另一个置于原网页上面的透明页面。
这种攻击利用了HTML中iframe标签的透明属性。 简单来说就是别人可能通过iframe引入你的网站,然后将其设为透明,用户点击他的网站实际上是点击你的网站,从而触发一些操作。
解决方法呢就是禁止别人通过Iframe引入自己的网站, 我这边是通过添加响应标头 X-Frame-Options 的方式来解决X-Frame-Options有以下三个属性,可根据需求进行配置:
·SAMEORIGIN : 页面只能被本站页面嵌入到iframe或者frame中;
· DENY: 页面不能被嵌入到任何iframe或frame中;
· ALLOW-FROM:页面允许frame或frame加载。
Nginx
在 http、service或者 location层级通过add_header 添加X-Frame-Options就行了,但是add_header 有个坑, 子级的add_header 会把父级的给覆盖掉,如果需要添加两个header属性,需要再copy一遍
add_header X-Frame-Options SAMEORIGIN; IIS
图形化界面修改HTTP响应标头。
或者修改web.config文件。
<system.webServer>
…
<httpProtocol>
<customHeaders>
<add name=”X-Frame-Options” value=”SAMEORIGIN” />
</customHeaders>
</httpProtocol>
…
</system.webServer>Apache
Header always append X-Frame-Options SAMEORIGIN
配置完成需要重启相应服务后才能生效
2 禁用TSL1.0和1.1 使用1.2版本以上
SSL/TLS 的版本
协议发布时间状态SSL 1.0未公布未公布SSL 2.01995 年已于 2011 年弃用SSL 3.01996 年已于 2015 年弃用TLS 1.01999 年已于 2021 年弃用TLS 1.12006 年已于 2021 年弃用TLS 1.22008 年TLS 1.32018 年由于TLS1.0和TLS1.1 已被弃用。所以那边推荐禁用掉,使用1.2及以上的版本 ,下面是服务器端的一些配置方法。
Nginx
#正常nginx默认是 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_protocols TLSv1.2 TLSv1.3;
IIS
IIS需要通过 IISCrypto来配置,下载完成后打开配置,把需要禁用的选项取消勾选,Apply之后重启服务器就OK 了。
Apache
#正常Apache默认是 SSLProtocol -ALL +TLSv1 +TLSv1.1 +TLSv1.2
SSLProtocol -ALL +TLSv1.2 +TLSv1.3
配置完成需要重启相应服务后才能生效
校验
访问该网站输入域名,稍等几分钟即可看到服务器TSL使用情况。
SSL Server Test (Powered by Qualys SSL Labs)
3.Storage 敏感信息泄露
这个问题呢,主要是我把Vuex 里的数据做了下持久化,放在session storage里了,所以通过开发者模式的Application 能看到一些用户信息,解决方法呢自然就是对信息进行加密处理,取的时候再进行解密,本来是打算用RSA进行非对称加密的,后来想了想,公钥私钥都放在前端的话,非对称加密好像也没什么意义,而且jsencrypt对字符串长度有限制,还要做分段加解密处理,比较麻烦 , 最后还是采用了 CryptoJS 的AES进行加解密:
安装CryptoJS
npm install crypto-js -S
加解密方法
var CryptoJS = require("crypto-js");
var data = [{id: 1}, {id: 2}]
// Encrypt
var ciphertext = CryptoJS.AES.encrypt(JSON.stringify(data), 'secret key 123').toString();
// Decrypt
var bytes= CryptoJS.AES.decrypt(ciphertext, 'secret key 123');
var decryptedData = JSON.parse(bytes.toString(CryptoJS.enc.Utf8));
console.log(decryptedData); // [{id: 1}, {id: 2}]
Vuex 中使用
由于我使用的是vuex-persistedstate 做的持久化,所以简单封装了一下。
// security.js
import CryptoJS from "crypto-js";
const { AES, enc } = CryptoJS;
const securityKey = "NCAFUASFASDGMKLT";
export class SecurityStorage {
constructor(storage) {
this.storage = storage ?? sessionStorage;
}
getItem(key) {
try {
const value = this.storage.getItem(key);
return (value ?? "") === ""
? ""
: JSON.parse(
AES.decrypt(this.storage.getItem(key) ?? "", securityKey).toString(
enc.Utf8
)
);
} catch (err) {
//解密失败,storage信息被修改,清除storage
this.clear();
}
}
setItem(key, value) {
this.storage.setItem(
key,
AES.encrypt(JSON.stringify(value), securityKey).toString()
);
}
removeItem(key) {
this.storage.removeItem(key);
}
clear() {
this.storage.clear();
}
} 引入
// store/index.js
import { SecurityStorage } from "./security.js";
...
const securityStorage = new SecurityStorage(window.sessionStorage);
...
new Vuex.Store({
plugins: ,
state: {},
...
})
然后就能看到 Application 里面的内容已经成功加密了,刷新一下,store数据正常显示,说明加解密过程没有问题。
4.其他
测试环境看到源代码的问题,是因为我配置分环境打包时打包模式配置的是NODE_ENV=development,所以去除sourcemap的配置没有生效,这个确实不怪我,我也没想到,做个渗透测试还要对测试环境进行测试啊。
其他就是一些后端老哥的问题了:
·某些下载和预览接口没有加token校验
· 后端接口方面没有做权限处理 ,拿普通用户的token能调用管理员相关的一些接口
· 登录接口没有做次数限制或者验证码校验,然后他们那边写了个python脚本不断去试用户的密码,试出来很多12345678的密码
...
5.总结
经过这次经历,对Web 安全方面也多了一些了解 ,安全问题还真是蛮重要的,后面在开发和部署的时候要多上点心啊。
页:
[1]