小子比较菜,初学java审计 记录一下下,大佬勿喷
因酷教育网校平台SQL注入
https://gitee.com/ms_git/demo_inxedu_open
gitee下载
下载之后导入IDEA
配置SDK版本
配置maven ,不然很多库加载不出来
配置tomcat
数据库已经配置导入了
然后启动
这个页面有点点问题但是不影响 。
找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 文件都要看
这里可以发现使用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
这里创建了 deleteImages方法 传入了 imageIds
1 2 3 4
| public void deleteImages(String imageIds) { websiteImagesDao.deleteImages(imageIds); EHCacheUtil.remove(CacheConstans.BANNER_IMAGES); }
|
按住Ctrl + 鼠标左键 定位上一个调用的
会来到这里
现在我们找到了接口 传参的可控点
但是这里是一个后台的功能 哈哈
http://127.0.0.1:8080/admin/website/imagesPage
我们点击删除抓包
接口 可控点都是正确的 。一开始发包过去看的时候 是302 跳转
在实战中,如果是我的话可能不会想到这里存在sql注入 哈哈比较菜
简单点sqlmap直接跑
这里可以证明是存在sql注入的了
第二个点 sql注入的点
1
| DELETE FROM EDU_ARTICLE_CONTENT WHERE EDU_ARTICLE_CONTENT.ARTICLE_ID IN (${value})
|
依旧使用IN字句查询
继续找
继续往下跟
来到了这里
如果传入的articleIds 不为空就会进入循环 赋给 ids
然后会根据传入的articleIds值进行调用deleteArticleByIds(ids) 然后进行删除
继续跟 deleteArticleByIds
然后就来到了这里
继续跟deleteArticle 方法 这是一个删除的
然后来到了这里
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
细心会发现 getParameterValues 函数
和前面一个sql注入调用的是一个
接口 传参 漏洞点知道了 验证一下
sqlmap 验证
这个系统还有很多处sql注入
这个系统是 MyBatis 框架的 #{是可以防止sql注入的
可以发现里面有些地方使用了#{}进行预防 ,但是很多地方还是使用${去使用 ,然而造成了漏洞。
因酷教育网校平台任意文件上传
文件上传常见函数 或者参数
1 2 3 4 5 6 7 8 9 10
| DiskFileItemFactory @MultipartConfig MultipartFile File upload InputStream OutputStream write fileName filePath
|
先来搜索一下 upload
这里出现一个视频上传的接口
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){
|
这是他的一个接口 参数
主路径在开头
1
| POST /video/uploadvideo?param=&fileType
|
在后台找半天没有找到上传视频这个点
接口参数有了 我们直接上传一个文件获取数据包
把这个数据包的 请求替换为自己找的这个
原本是长这样 替换接口
他这里的fileType 类型可控,原本是只有那几种图片类型。
由于这里可控filetype 造成任意文件上传
分析一下 代码
这段代码由于filetype是可以用户自己设定,造成文件上传漏洞,这里可以写一个白名单
1
| List<String> allowedFileTypes = Arrays.asList("jpg", "jpeg", "png", "gif", "mp4", "avi");
|
只运行上传这几个类型后缀
第二个漏洞点,他这里做了一个简单的校验
就是一开始找图片上传的地方
数据包
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?¶m=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: 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,*
|
接口
/image/gok4
他这个接口是自己重写的,在lib目录下
可以发现这里存在这么一段代码
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就上传失败
但是我们知道可以使用几种方式绕过
既然不能写jsp 这里可以写jspx
也可以使用
.jsp::$DATA: 绕过
上传一个木马尝试
这样就成功上传了 链接一下
成功上传
这两个漏洞都是比较简单,而且都是未授权上传 不需要cookie ,只是功能点在后台
删除cookie 依旧可以成功上传。
JFinalCMS 任意文件读取/下载
网上存在这个漏洞
可以发现接口是 /common/down/file
来分析一下
搜索/down/file 可以看出是一个下载的功能
点击第一个
这里的file 也是一个路径
file 定义了一个处理文件下载请求的方法。
参数是fileKey
1
| renderFile(new File(PathKit.getWebRootPath() + fileKey))
|
使用PathKit.getWebRootPath()获取web根目录路径,并拼接fileKey参数值生成文件路径,然后调用renderFile方法返回该文件。
比如路径是 xx.cn/common/down/file?fileKey=xx.html
可以通过../../../去获取路径下的文件 来调试一下
看idea
看步入之后会显示路径
这是他的路径 我 前面输入的xx.html是有问题可以看见 他直接连在跟目录上了
就会报错
我们重新来
我们读取上一级目录下的test文件
步入
这样就会跳转到webapps下的test.txt文件了
burp更加清晰
可以成功的读取到 。
这里就是直接用PathKit.getWebRootPath()获取web根目录路径 然后就直接拼接了fileKey的参数导致的文件读取/目录遍历。