近日手头上有一份蛋疼的渗透测试报告,洋洋洒洒列了几十条,本菇凉连月加班才勉勉强强,从对这些漏洞的无知,到为web打补丁、防攻击,真是心力交瘁,内忧外患。
今天遇到的漏洞,学名为:会话cookie通过URL传递
按照字面理解呢,就是JESSIONID放在url中,直接列在浏览器上,安全公司认为这是敏感信息,不宜大张旗鼓的展示。
好吧,我改。55555555555...........
先给大家展示一下什么是cookie通过URL传递:
https://localhost:8443/admin/login;JSESSIONID=eefe2007-a31b-492e-a56f-4d1fa8bd61c6
很显然,当我在登陆页面的时候,浏览器的url里面有个JESSIONID,而且大家注意,在/login路径后面,跟着的并不是?和参数,而是冒号和JESSIONID。
这就很奇怪了?这个JESSIONID是怎么加上去的呢?肯定不是我web后端加上去的,我也没精力自己写个SessionManager管理器。
那就是后端框架自动生成的,无疑。
我们项目的就是基于tomcat容器和SpringBoot、shiro权限与安全框架进行部署的,那么我最先的思路就是查找tomcat容器为何会重写URL,自动加上JESSIONID,我的做法是这样的:
1、百度一下,我就知道
2、百度一下,我就知道
3、百度一下,我就知道
搜索了N久之后,我来总结一下网络搜索的结果:
1、修改application.properties中的tomcat配置
server.servlet.session.cookie.http-only=true
server.servlet.session.tracking-modes=cookie
2、disableURLRewriting属性
3、修改启动类
忘了,不想搜索贴图了.........
有没有效果呢?我们的框架是SpringBoot,用的是内嵌tomcat,网络搜索的结果都是针对独立tomcat的设置,我并不能确定修改了以上这些就一定有效。我修改了以上这些,一启动服务,一打开首页,心跳加速,duang!特么的JESSIONID还在。
是否因为是内嵌tomcat的缘故,所以以上设置无效?我一开始的猜测是这样的,来看下maven引入的内嵌tomcat的jar包
是否因为embed包与独立tomcat不同?
这可怎么解决?每次发出一个登陆请求,tomcat容器就会自动生成一个JESSIONID,交给sessionManager管理,并且重写URL,在浏览器里直接显示,若是因为包不一样,那我如何判断哪里需要修改呢?好吧,请叫我百度程序员,google都很少用,百度啊百度啊,什么办法都没有,只有一个很绝望的方法:修改tomcat源代码,把ManagerBase的createSession等方法都返回null,自然无法创建sessionId。
把sessionId返回空了,怎么管理session呢?放心,我们springboot+shiro+..的项目,shiro已经掌握了管理Session的大权。禁用掉tomcat sessionManager,不仅不会影响系统正常运行,还会节约空间,加速请求/响应速度。
源代码,呵呵,我好像从来没读过,更别说去改。
但是咋办呢?这个任务一定要完成.....天将降大任于斯人也,必先让其熬夜,饿其体肤,损其脑细胞......
我们需要修改的源代码:(怎么改自己搜去)
这是本菇凉第二次改框架源代码,上一次改的前端UI插件的源代码,大不了就是显示不出来,可是改tomcat,万一崩溃了,咋办?本菇凉手都要发抖了。
一万个草泥马飞过.......
好吧,硬着头皮也要上。。。。
一个小时过去了................
又一个小时过去了..............
三个小时过去了..............
好吧,我放弃了.....我可以成功改掉源代码,但是我不会重新编译.......哎......心累
气到脑袋发晕,于是我一气之下熬了一锅粥喝。。。。。
边喝粥边想,为什么我设置tomcat属性禁用掉重写URL就无效呢?就是无效呢?就是无效呢!!!!!!
光想有什么用?调试!我去调试tomcat源代码,我就不信我还找不到是怎么重写URL的
Tomcat的Response类实现了重写URL:
来把这个代码贴出来分析下:
protected String toEncoded(String url, String sessionId) {
if ((url == null) || (sessionId == null)) {
return (url);
}
String path = url;
String query = "";
String anchor = "";
int question = url.indexOf('?');
if (question >= 0) {
path = url.substring(0, question);
query = url.substring(question);
}
int pound = path.indexOf('#');
if (pound >= 0) {
anchor = path.substring(pound);
path = path.substring(0, pound);
}
StringBuilder sb = new StringBuilder(path);
if( sb.length() > 0 ) { // jsessionid can't be first.
sb.append(";");
sb.append(SessionConfig.getSessionUriParamName(
request.getContext()));
sb.append("=");
sb.append(sessionId);
}
sb.append(anchor);
sb.append(query);
return (sb.toString());
}
看出来了吧!此方法在URL中加上了冒号和sessionId,我们的URL就变了!哼!
虽然找到了方法根源处,但是还是找不出为什么Tomcat设置了禁用,URL仍然被重写!很绝望啊有木有!
好吧,我开始打断点,我就不信我一步步调试还进不去。。。
真正令人激动的时刻到来了,我在各个地方都断了点,就等他入瓮......
好的,打开,调试,F6,竟然进入了ShiroHttpServeletResponse,而且翻阅该类的源代码,竟然去tomcat源代码几乎一样!!
这也就是为什么,我设置了tomcat禁用URL重写,它为什么还会出来,因为shiro框架"参考"了tomcat部分源代码!!shiro框架中还存在着URL重写!!!
之后,我很自然地把设置shiro禁用URL重写
@Bean(name = "sessionManager")
public DefaultWebSessionManager getDefaultWebSessionManager() {
DefaultWebSessionManager defaultWebSessionManager = new DefaultWebSessionManager();
defaultWebSessionManager.setGlobalSessionTimeout(60 * 30 * 1000);
defaultWebSessionManager.setDeleteInvalidSessions(true);
defaultWebSessionManager.setSessionValidationSchedulerEnabled(true);
defaultWebSessionManager.setSessionValidationScheduler(getExecutorServiceSessionValidationScheduler());
defaultWebSessionManager.setSessionDAO(getEnterpriseCacheSessionDAO());
defaultWebSessionManager.setSessionIdCookieEnabled(true);
defaultWebSessionManager.setSessionIdCookie(getSessionIdSimpleCookie());
// tomcat的JESSIONID自动生成模块,shiro直接抄的tomcat的,唉!误导我一直在看tomcat源码
defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);
List listeners = new ArrayList<>();
listeners.add(getUserSessionListener());
defaultWebSessionManager.setSessionListeners(listeners);
return defaultWebSessionManager;
}
这下应该可以了吧!可是defaultWebSessionManager.setSessionIdUrlRewritingEnabled(false);竟然报红——没有该方法
这一刻,我疯了。
静若处子,动若脱兔............
为什么!为什么!
后来去网上漫天遍地的找原因...终于找到了..
官网解释:.1.3.2一下版本的shiro有bug,1.3.2以后的修复了这个URL重写却不可禁用的BUG
MMP,我要骂人了...低版本的还有大bug.....
改好了版本,开测!
这个时候我内心都已经放弃了,最后一次,JESSIONID再去不掉,我就睡觉去,不管了....
好,打开浏览器,输入首页,回车.....
JSESSIONID...它不见了...........
!!!!!!!!!!!!!!!!!!!!!
我又花了半小时写这篇记录
抬头一看外面,天都亮了........