背景
有一个在用的confluence应用,被多次通报有使用弱密码。经查发现,登录时居然是明文传输账号密码。。。
解决问题
网上查了下文档,也翻了下登录页面的代码,没有发现有设置加密的地方。
官方没有,那尝试自己来改。
思路
前端提交数据前,拦截修改提交数据,将数据加密后传递。
后端收到数据后,先解密再执行原逻辑。
首先我反编译了后端代码,梳理了页面登录的流程。
然后去网上查了相关加密算法,决定使用rsa加密。
最后查询了js和java的rsa实现方法。
修改后结果如下:
大致步骤
前端修改内容
前端rsa的实现参考借鉴了,https://tool.ip138.com/rsa/
- 引入js
修改 com.atlassian.confluence_confluence-8.3.1.jar中的plugins/web-resources.xml文件,引入新的实现加密的js.
当然也可以不修改这个文件把相关方法直接写入原来的login.js文件中
<web-resource key="login" name="Confluence Login" i18n-name-key="admin.web.resources.plugin.login.name">
<transformation extension="js">
<transformer key="jsI18n"/>
</transformation>
<resource type="download" name="login.js" location="/includes/js/login.js">
<param name="source" value="webContextStatic"/>
</resource>
<resource type="download" name="rsa.js" location="/includes/js/jsencrypt.js">
<param name="source" value="webContextStatic"/>
</resource>
<dependency>confluence.web.resources:ajs</dependency>
<dependency>com.atlassian.auiplugin:template</dependency>
</web-resource>
- 修改登录页面js
在登录前的校验逻辑后,添加了加密处理逻辑。
我是修改了传递的id值。当然你也可以直接对原值中的账号密码进行加密。
$loginForm.submit(function(e) {
$loginButton.attr('enabled', 'false');
var formIsValid = validate();
if (!formIsValid) {
$loginButton.attr('enabled', 'true');
}
formIsValid || e.preventDefault();
//以下是新加的rsa非对称加密逻辑
if('function' == typeof(JSEncrypt)){
let crypt = new JSEncrypt();
crypt.setPublicKey("这里填公钥");
$('#os_password')[0].name="data";
$('#os_username').removeAttr("name");
$('#os_password').val( crypt.encrypt("{\"os_username\":\""+$('#os_username').val()+"\",\"os_password\":\""+$('#os_password').val()+"\"}") || '')
}
});
后端修改内容
后端java解密rsa的逻辑,参考借鉴了这篇博文 https://blog.csdn.net/wanzijy/article/details/126092414
confluence登录时传递的信息是在com.atlassian.seraph_atlassian-seraph-4.1.0.jar包里的LoginFilter类中的PasswordBasedLoginFilter.UserPasswordPair方法中实现。
于是反编译代码,添加解密方法,再编译后替换原文件。
添加的代码如下:
protected PasswordBasedLoginFilter.UserPasswordPair extractUserPasswordPair(HttpServletRequest request) {
String data = request.getParameter("data");
String username = request.getParameter("os_username");
String password = request.getParameter("os_password");
//下面是新增的代码,解密并替换
if(StringUtils.isNotEmpty(data)){
data = decrypt(data);
JSONObject jsonObject = new JSONObject(data) ;
if(jsonObject.has("os_username")){
username=jsonObject.get("os_username").toString();
}
if(jsonObject.has("os_password")){
password=jsonObject.get("os_password").toString();
}
}
...