Java代码审计初探

小子比较菜,初学java审计 记录一下下,大佬勿喷

因酷教育网校平台SQL注入

https://gitee.com/ms_git/demo_inxedu_open
gitee下载
image.png
下载之后导入IDEA
配置SDK版本
image.png
配置maven ,不然很多库加载不出来
image.png
配置tomcat
image.png
数据库已经配置导入了
然后启动
image.png
这个页面有点点问题但是不影响 。
找sql注入了 一般是搜索一些关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
${
select
insert
update
delete
order by


java.sql.Connection: 表示与数据库的连接。
getConnection(): 用于建立数据库连接的方法。
Statement: 执行 SQL 语句的接口。
execute(): 执行任何类型的 SQL 语句的方法。
executeQuery(): 专门用于执行返回 ResultSet 的 SQL 查询(SELECT 语句)的方法。
PreparedStatement:用于执行预编译的 SQL 查询的接口。
jdbcTemplate:Spring 框架中用于简化 JDBC 操作的类。
queryForInt、queryForObject 和 queryForMap:jdbcTemplate 类中用于执行 SQL 查询并返回不同类型结果的方法。

#{ 这样也算是预编译了 和 用PreparedStatement ? 预编译差不多

总所周知预编译可以防止sql注入
了解一下预编译代码

1
2
String sql = "SELECT * FROM users WHERE username = ? AND password = ?";
preparedStatement = connection.prepareStatement(sql);

先来全局搜一下 ${
文件可能是java 和 xml 文件都要看
image.png
这里可以发现使用delete 来删除广告图片 使用的是 IN子句的SQL查询 然后 value是用 ${value}包裹的
跟进去看看

1
2
3
4
5
<!-- 删除广告图片 -->
<delete id="deleteImages" parameterType="java.lang.String">
DELETE FROM EDU_WEBSITE_IMAGES WHERE IMAGE_ID IN(${value})
</delete>

继续往上找可控点 搜索deleteImages
image.png
这里创建了 deleteImages方法 传入了 imageIds

1
2
3
4
public void deleteImages(String imageIds) {
websiteImagesDao.deleteImages(imageIds);
EHCacheUtil.remove(CacheConstans.BANNER_IMAGES);
}

image.png
按住Ctrl + 鼠标左键 定位上一个调用的
image.png
会来到这里
现在我们找到了接口 传参的可控点
但是这里是一个后台的功能 哈哈
http://127.0.0.1:8080/admin/website/imagesPage
image.png
我们点击删除抓包
image.png
接口 可控点都是正确的 。一开始发包过去看的时候 是302 跳转
在实战中,如果是我的话可能不会想到这里存在sql注入 哈哈比较菜
简单点sqlmap直接跑
image.png
image.png
image.png
这里可以证明是存在sql注入的了

第二个点 sql注入的点
image.png

1
DELETE FROM EDU_ARTICLE_CONTENT WHERE EDU_ARTICLE_CONTENT.ARTICLE_ID IN (${value})

依旧使用IN字句查询
继续找
image.png
继续往下跟
image.png
来到了这里
如果传入的articleIds 不为空就会进入循环 赋给 ids
然后会根据传入的articleIds值进行调用deleteArticleByIds(ids) 然后进行删除
继续跟 deleteArticleByIds
image.png
然后就来到了这里
继续跟deleteArticle 方法 这是一个删除的
image.png
然后来到了这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@RequestMapping("/delete")
public ModelAndView delete(HttpServletRequest request) {
ModelAndView model = new ModelAndView();
try {
model.setViewName(this.getRequestUri(request));
String[] aridArr = request.getParameterValues("articelId");
if (aridArr != null && aridArr.length > 0) {
this.deleteArticle(aridArr);
}
} catch (Exception e) {
model.setViewName(this.setExceptionRequest(request, e));
logger.error("AdminArticleController.delete()--error", e);
}
return model;
}

主要的代码

1
String[] aridArr = request.getParameterValues("articelId");

传入了articelId 接口 delete 完整接口/admin/article/ delete
image.png
细心会发现 getParameterValues 函数
和前面一个sql注入调用的是一个
image.png
接口 传参 漏洞点知道了 验证一下
image.png
image.png
sqlmap 验证
image.png
image.png
这个系统还有很多处sql注入
这个系统是 MyBatis 框架的 #{是可以防止sql注入的
image.png
可以发现里面有些地方使用了#{}进行预防 ,但是很多地方还是使用${去使用 ,然而造成了漏洞。

因酷教育网校平台任意文件上传

文件上传常见函数 或者参数

1
2
3
4
5
6
7
8
9
10
DiskFileItemFactory
@MultipartConfig
MultipartFile
File
upload
InputStream
OutputStream
write
fileName
filePath

先来搜索一下 upload
image.png
这里出现一个视频上传的接口

1
2
3
4
@RequestMapping(value="/uploadvideo",method={RequestMethod.POST})
public String gok4(HttpServletRequest request,HttpServletResponse response,@RequestParam(value="uploadfile" ,required=true) MultipartFile uploadfile,
@RequestParam(value="param",required=false) String param,
@RequestParam(value="fileType",required=true) String fileType){

这是他的一个接口 参数
主路径在开头
image.png

1
POST /video/uploadvideo?param=&fileType

在后台找半天没有找到上传视频这个点
接口参数有了 我们直接上传一个文件获取数据包
image.png
把这个数据包的 请求替换为自己找的这个
image.png
原本是长这样 替换接口
image.png
他这里的fileType 类型可控,原本是只有那几种图片类型。
由于这里可控filetype 造成任意文件上传
分析一下 代码
image.png
这段代码由于filetype是可以用户自己设定,造成文件上传漏洞,这里可以写一个白名单

1
List<String> allowedFileTypes = Arrays.asList("jpg", "jpeg", "png", "gif", "mp4", "avi");

只运行上传这几个类型后缀

第二个漏洞点,他这里做了一个简单的校验
就是一开始找图片上传的地方
image.png
数据包

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
POST /image/gok4?&param=online&fileType=jpg,gif,png,jpeg&pressText=undefined HTTP/1.1
Host: 127.0.0.1:8080
Content-Length: 8740
Cache-Control: max-age=0
sec-ch-ua:
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: ""
Upgrade-Insecure-Requests: 1
Origin: http://127.0.0.1:8080
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary8u8KcA4F9WoK4tkH
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.5845.111 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: iframe
Referer: http://127.0.0.1:8080/admin/websiteProfile/online?tabPageId=jerichotabiframe_8
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: remember-me=YWRtaW46MTcxODk3MDQ3MDU0NzowZWFlOWEwZmQzY2QzYWVlM2MwZjNjMWVkOWVjNDk3MA; inxedulogin_sys_user_=inxedulogin_sys_user_1; JSESSIONID=4DB22884B104B1636BD64E45638ECB69
Connection: close

------WebKitFormBoundary8u8KcA4F9WoK4tkH
Content-Disposition: form-data; name="uploadfile"; filename="downloadApp.png"
Content-Type: image/png


接口
/image/gok4
他这个接口是自己重写的,在lib目录下
image.png
可以发现这里存在这么一段代码

1
2
3
4
5
6
f (fileType.contains(ext) && !"jsp".equals(ext)) {
String filePath = this.getPath(request, ext, param);
File file = new File(this.getProjectRootDirPath(request) + filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}

这里做了一个防止上传jsp的操作 ,如果上传类型为jsp就上传失败
image.png
但是我们知道可以使用几种方式绕过
既然不能写jsp 这里可以写jspx
image.png
也可以使用
.jsp::$DATA: 绕过
上传一个木马尝试
image.png
这样就成功上传了 链接一下
image.png
image.png
成功上传
这两个漏洞都是比较简单,而且都是未授权上传 不需要cookie ,只是功能点在后台
image.png
删除cookie 依旧可以成功上传。

JFinalCMS 任意文件读取/下载

网上存在这个漏洞
image.png

可以发现接口是 /common/down/file
来分析一下
image.png
搜索/down/file 可以看出是一个下载的功能
点击第一个
image.png
这里的file 也是一个路径
file 定义了一个处理文件下载请求的方法。
参数是fileKey

1
renderFile(new File(PathKit.getWebRootPath() + fileKey))

使用PathKit.getWebRootPath()获取web根目录路径,并拼接fileKey参数值生成文件路径,然后调用renderFile方法返回该文件。
比如路径是 xx.cn/common/down/file?fileKey=xx.html
可以通过../../../去获取路径下的文件 来调试一下
image.png

看idea
image.png
看步入之后会显示路径
image.png
这是他的路径 我 前面输入的xx.html是有问题可以看见 他直接连在跟目录上了
image.png
就会报错
image.png
我们重新来
我们读取上一级目录下的test文件
image.png
image.png步入
image.png
这样就会跳转到webapps下的test.txt文件了
burp更加清晰
image.png
可以成功的读取到 。
这里就是直接用PathKit.getWebRootPath()获取web根目录路径 然后就直接拼接了fileKey的参数导致的文件读取/目录遍历。