处理casdoor明文传输高危漏洞遇到的问题整理

问题背景:

公司最近对各个系统做了安全漏洞扫描,发现诸多系统均存在不同级别,不同数量的漏洞,我则负责统一认证中心密码明文传输的漏洞。统一认证中心我们使用的是开源项目casdoor,该项目专注于单点登陆,功能强大。

过程及问题:

Go环境的问题:

casdoor服务端采用go语言开发,我在本地验证功能,需要先配置go环境。go环境配置网上教程较成熟,按照GOPATH规范放源码位置。go运行还需要下载一系列go的依赖包,国内网络环境下载十有八九是不成功的,这时我们需要将go的网络代理配置成环境变量,还需要配置一个开关

重试,依赖工具可成功下载。

前端版本问题: 

casdoor的前端使用react+js语言开发,依赖node环境运行,一开始我按照网上教程下载按照了最新版本的node环境(本地casdoor测试代码也是最新版),运行casdoor前端正常。于是我把casdoor版本切换到公司测试环境对应的版本,然后发现前端总是启动失败,最终定位发现是node环境和js版本不匹配导致的,于是我打算降低本地node环境,网上搜教程发现了一个非常强大的node版本控制工具--nvm,强烈建议前端node环境使用nvm安装,具体安装使用教程自行百度。nvm可以自由切换不同的node版本,只需要简单的命令执行。

于是我成功安装了nvm工具,同时降低了我的node版本,此后,casdoor前端成功启动。

加密解密问题:

环境问题都ok,项目也可以成功启动,接下来就是处理密码明文传输的问题了,我们团队采用的思路是采用rsa非对称加密算法,前端在发送请求之前将密码使用公钥加密,然后传给后端,后端收到密文之后再通过秘钥解密,得到明文密码处理后续业务逻辑。

密钥对可以在线获取(不安全),也可以go代码在本地生成,秘钥长度越长,加密后的密文就越长,越安全,但是传输和处理代码也越大,可根据实际情况选择适当的秘钥长度。

// 生成密钥对并保存到文件
func GenerateRSAKey() error {
	// 1、RSA生成私钥文件的核心步骤:
	// 1) 生成RSA密钥对
	var bits int
	flag.IntVar(&bits, "key flag", 4096, "密钥长度,默认值为1024位")
	privateKer, err := rsa.GenerateKey(rand.Reader, bits)
	if err != nil {
		return err
	}
	// 2) 将私钥对象转换成DER编码形式
	derPrivateKer := x509.MarshalPKCS1PrivateKey(privateKer)
	// 3) 创建私钥pem文件
	file, err := os.Create("./private.pem")
	if err != nil {
		return err
	}
	// 4) 对密钥信息进行编码,写入到私钥文件中
	block := &pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: derPrivateKer,
	}
	err = pem.Encode(file, block)
	if err != nil {
		return err
	}

生成秘钥对后,在前端用公钥对密码进行加密,

import JSEncrypt from "jsencrypt";
  
encrypt(txt) {
    const publicKey = "自己生成的公钥";
    const encryptor = new JSEncrypt();
    encryptor.setPublicKey(publicKey); // 设置公钥
    return encryptor.encrypt(txt); // 对需要加密的数据进行加密
  }

此处需要注意,公钥需和生成的格式保持一致,不能写到一行!

前端加密后,后端开始解密,一开始我在网上找了很多go语言rsa解密教程,大多数都已失败告终,建议大家使用go原生的rsa解密方法进行解密,不要使用个人封装的git库。后端也需要将秘钥按照生成的格式配置,不能放在一行。秘钥是解密密文的关键,不可以泄露。(如果有私钥加密,公钥解密的场景,公钥也不可以泄露)

在解密过程中有一个非常重要的坑,几乎网上所有的帖子都没有提到,那就是,前端加密后的密文是经过base64转换的,后端要解密之前,须先将密文进行base64反转,然后才能解密成功,后端解密核心代码如下:

import (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/base64"
	"encoding/pem"
	"fmt"
)

func DecryptByPrivateKey(ciphertext string) string {
	fmt.Println("开始解密")
	if ciphertext == "" {
		fmt.Println("解密密文为空!")
		return ciphertext
	}
    //必须先将密文base反转换
	decoded, err := base64.StdEncoding.DecodeString(ciphertext)
	if err != nil {
		fmt.Println("base64反解析前端传入的密文出错:" + err.Error())
		return ""
	}
	block, _ := pem.Decode([]byte(Pirvatekey))
	privateKey, err := x509.ParsePKCS1PrivateKey(block.Bytes)
	if err != nil {
		fmt.Println("将秘钥转换为*rsa.PrivateKey格式出错:" + err.Error())
		return ""
	}

	decrypted, err := rsa.DecryptPKCS1v15(rand.Reader, privateKey, decoded)
	if err != nil {
		fmt.Println("解密密码失败" + err.Error())
		return ""
	}
	fmt.Println("解密完成")
	return string(decrypted)
}

经验证,前端传输的密码为密文传输,后端也可以正常解密,业务正常运行。

总结: 

1、go环境须配置国内代理才能在国内网络环境正常下载go依赖;

2、casdoor前端须以来正确的node版本才能正常运行,建议使用nvm工具切换node版本;

3、前端配置公钥和后端配置的私钥都须按照秘钥生成的格式配置(换行),不可以放在一行;

4、前端使用JSEncrypt加密的密文,后端须先进行base64反转才可进行rsa解密。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值