1.概述
SpringBoot+Mybatis的一个erp系统,项目结构如下:
2.SQL时间盲注
在MaterialMapperEx.xml
中,发现两个没有预编译的字段:
跟到service层的MaterialService.java
:
public int getListWithStockCount(List<Long> depotList, List<Long> idList, String position, String materialParam, Integer zeroStock) {
return materialMapperEx.getListWithStockCount(depotList, idList, position, materialParam, zeroStock);
}
再跟到controller层的MaterialController.java
,发现这两个参数经过了StringUtil.safeSqlParse()
的过滤:
跟过去StringUtil.java
,看到过滤了引号、注释符、分号和一些SQL关键字,但是没有过滤括号、sleep、case之类的,可以尝试时间盲注:
public static String safeSqlParse(String originStr){
return originStr.replaceAll("(?i)" + regex, "");
}
public final static String regex = "'|#|%|;|--| and | and|and | or | or|or | not | not|not " +
"| use | use|use | insert | insert|insert | delete | delete|delete | update | update|update " +
"| select | select|select | count | count|count | group | group|group | union | union|union " +
"| create | create|create | drop | drop|drop | truncate | truncate|truncate | alter | alter|alter " +
"| grant | grant|grant | execute | execute|execute | exec | exec|exec | xp_cmdshell | xp_cmdshell|xp_cmdshell " +
"| call | call|call | declare | declare|declare | source | source|source | sql | sql|sql ";
部署环境测试一下,果然可以时间盲注:
看看后端MySQL执行日志:
SQLMap跑一下:
3.存在限制的文件上传
全局搜upload,在SystemConfigController.java
找到文件上传的路由,这里没有对文件名进行过滤,fileUploadType
在配置文件里默认为1,所以走的是systemConfigService.uploadLocal()
:
跟踪uploadLocal()
函数到service层的SystemConfigService.java
,这里的bizPath是可控的且没有过滤,filepath在配置文件里默认为/opt/jshERP/upload
,文件名处理也没有过滤后缀名:
但有一点小问题,在于这段,bizPath拼接了一个根据token截取的租户id,这会导致最后上传的目录受到影响:
String token = request.getHeader("X-Access-Token");
Long tenantId = Tools.getTenantIdByToken(token);
bizPath = bizPath + File.separator + tenantId;
/**
* 根据token截取租户id
* @param token
* @return
*/
public static Long getTenantIdByToken(String token) {
Long tenantId = 0L;
if(StringUtil.isNotEmpty(token) && token.indexOf("_")>-1) {
String[] tokenArr = token.split("_");
if (tokenArr.length == 2) {
tenantId = Long.parseLong(tokenArr[1]);
}
}
return tenantId;
}
这个拼接大大影响了利用,但我暂时没找到绕过的办法,虽然getFileName()
没有过滤文件后缀名,但是过滤了斜杠,导致没办法从文件名这里跨目录,同时用户的token也是不可控的:
public static String getFileName(String fileName){
//判断是否带有盘符信息
// Check for Unix-style path
int unixSep = fileName.lastIndexOf('/');
// Check for Windows-style path
int winSep = fileName.lastIndexOf('\\');
// Cut off at latest possible point
int pos = (winSep > unixSep ? winSep : unixSep);
if (pos != -1) {
// Any sort of path separator found...
fileName = fileName.substring(pos + 1);
}
//替换上传文件名字的特殊字符
fileName = fileName.replace("=","").replace(",","").replace("&","");
return fileName;
}
部署测试:
4.Swagger未授权访问
系统集成了swagger,在Swagger2Config.java
配置了@EnableSwagger2
注解但没有启用@EnableSwaggerBootstrapUI
注解,所以有API接口但没有UI页面:
没有在application.properties给swagger接口配置认证,并且在FilterLogCostFilter.java
里把API加到了白名单,所以可以在不登录的情况下直接访问:
部署测试:
5.攻心为上的Fastjson
在pom.xml中看到fastjson的版本为1.2.83:
搜一下parseObject,serach可控,可以利用的路由很多,就不细说了:
1.2.83的fastjson暂时没有公开的利用方式,只能通过java.net.InetSocketAddress
来进行dnslog,没什么用,但可以在HW的时候折磨防守方。根据我的经验,你只需要在晚上8点40左右交班的前夕,挑两个关键资产打个dnslog让他们应急,可以有效延长白班兄弟的工作时间,搞他心态: