问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
某OA系统的审计(新手学习)
漏洞分析
一次偶然机会,找人要了套源码,是Stuts2和spring框架混用的系统,比较简单适合入门学习
某OA系统的审计(新手学习) ============== 一次偶然机会,找人要了套源码,是Stuts2和spring框架混用的系统,比较简单适合入门学习 0x01 SQL注入 ---------- 该项目是基于mvc框架开发的,与数据库交互的代码在`DAO`目录下,在core/base/dao中存在IBaseDao类属于该项目的数据库操作的基类  根据其定义的函数名,都能看出是传入SQL语句进行查询,我们找的他的实现类  可以看到其方法实现也是传入SQL语句字符串直接它通过hibernateTemplate API直接进行查询。其实现SQL查询的方法也有很多。 同时我们发现该baseDao类有七百多个继承者  跟进去发现基本都继承了BaseDao的方法,并没有进行重载,于是我们全局搜索相关危险方法,这里以sqlFind方法为例  发现在构造SQL语句是用了?占位符,这样的语法是无法进行注入的,于是我们寻找直接拼接参数到SQL语句字符串中的方法  根据sqlFind方法的重装情况,当参数`param`为空则不会进行占位符参数绑定,于是我们可以缩小搜索范围 向下翻找就找到在`BaseDataService`类中`listBaseDataByFlowId`方法,存在直接拼接参数构造SQL语句的情况,  这里直接将`flowId`等参数拼接到语句中调用`sqlFind`方法进行数据库查询,我们向上找是哪个controller调用该危险方法 最终定位在`BaseDataController`中的`listBaseDataByFlowId`方法中  这里直接将请求中type和flowId传入service层进行查询,我们构造该接口的请求  提示我们没有登录,应该是spring进行了拦截处理 0x02 权限绕过 --------- 我们查看spring配置文件,找的拦截器的实现类  可以看到该项目有个全局拦截器`PermissionInterceptor`,我们跟进到里面,根据spring拦截器实现原理直接来到`prehandle`方法,主要处理逻辑如下  该拦截器定义了两个成员数组`UN_LOGIN_EXPOSE_CONTROLLERS`和`UN_LOGIN_EXPOSE_SERVLET_PATH`,当我们请求的控制器或者接口url在这两个数组中是会放行我们的请求,也就是定义了白名单请求,很遗憾我们的`listBaseDataByFlowId`方法的请求不在白名单中,会进入if判断。 首先判断session中是否有登录凭证(显然没有),如果没有会获取请求中jwt参数的值进行JSON Web Token的认证,检查token的有效性。 看到jwt 认证,很快就想到会不会硬编码jwt 密钥,因为在初期翻配置文件中没看到有jwt 密钥的定义 于是我们跟进到`jwtCheck`方法,果然验证了我们的猜想  于是我们根据密钥生成token  带着jwt token访问目标接口,发现不在提示未登录  根据配置文件该系统是属于了sql server数据库,于是构造语句 ```php flowId = 1'+(case when (1=1) then '' else char(1/0) end)+' ``` 当为正是,正常返回  为假是进行char(1/0)构造报错会返回500  证明存在SQL注入 0x03 总结 ------- 1、mvc框架中service层一般是负责sql语句的封装,dao层一般负责与数据库交互,所以我们可以在dao层中找直接执行sql语句的方法,在service层调用可疑查询方法处查看sql语句构造情况,找的可能存在sql注入的点,向上找的controller层的具体调用接口 2、主要还是看鉴权,通过配置文件找的鉴权类,如使用了request.getRequestUri等危险方法来获取请求url做判断时很容易就被bypass,或是看jwt等第三方鉴权组件硬编码的问题 0x04 另外发现 --------- ### 1、未授权文件上传 在鉴权文件中存在白名单controller类和接口数组`UN_LOGIN_EXPOSE_CONTROLLERS`和`UN_LOGIN_EXPOSE_SERVLET_PATH`,我们关注一下  翻找未授权类时在appCallController中,有文件操作的方法 ```java @RequestMapping({"uploadFile"}) @ResponseBody @Transactional( readOnly = false ) public String uploadFile(@RequestParam(value = "file",required = false) MultipartFile file) { try { String id = UUIDUtils.getuid(); String extension = StringUtils.getFilenameExtension(file.getOriginalFilename()); if (StringUtils.hasText(extension)) { extension = "." + extension; } String fileUrl = "../xxx_Ueditor_File/app/files/" + id + extension; String savePath = getCurRequest().getSession().getServletContext().getRealPath(fileUrl); File saveFile = new File(savePath); if (!saveFile.exists()) { saveFile.mkdirs(); } file.transferTo(saveFile); APPFiles af = new APPFiles(); af.setFileLength(file.getSize()); af.setId(id); af.setFilePath(saveFile.getAbsolutePath()); af.setFileName(file.getOriginalFilename()); af.setTime(new Date()); af.setFileType(file.getContentType()); af.setMsgId(""); af.setType(2); this.dao.save(af); return id; } catch (Exception var8) { var8.printStackTrace(); return ""; } } ``` 该方法是获取随机数id,然后取到表单上传中的文件名后缀名,然后将其保存在`/xxx_Ueditor_File/app/files/`目录中,最后讲随机数id返回给前端,因为未对文件后缀名做限制导致可以上传jsp文件 构造请求上传   成功上传文件 ### 2、未授权SQL注入 该项目除了用到spring框架外还用到了st2框架,在`struts.xml`查看配置信息,这里也定义了拦截器  具体实现逻辑在doIntercept()方法中  可以看到这里也是定义白名单方法名和类名 ```java private Set<String> UN_LOGIN_EXPOSE_METHODS = new HashSet<String>() { { this.add("saveStaffInfo"); this.add("updateStaffInfo"); this.add("listRegionTree"); this.add("CostCloudProject"); ... this.add("handle"); this.add("listProjAuditQGC"); this.add("getlistProjAuditDataQGC"); } }; private static List<Class<?>> TEMP_USER_EXPOSE_ACTIONS = new ArrayList<Class<?>>() { { this.add(IndexAction.class); ... } }; private static List<String> TEMP_USER_EXPOSE_METHODS = new ArrayList<String>() { { this.add("showPhoto"); this.add("download"); } }; ``` 看到白名单方法中有些get操作的函数,如`getlistProjAuditDataQGC`看名称是获取list数据,跟进其中  可以看到调用`findByBusinessByQueryQGC`方法进行查询,来到`findByBusinessByQueryQGC`方法实现,可以看到其是获取请求中的特定参数,并将其直接拼接在sql变量中  最后调用`sqlFindPage`拼接sql变量执行   此处也是存在SQL注入 
发表于 2023-09-26 09:00:02
阅读 ( 20457 )
分类:
漏洞分析
8 推荐
收藏
2 条评论
qrling
2023-09-27 09:49
佬,源码是开源的么,可以分享下吗
请先
登录
后评论
ybdt
2023-09-28 22:51
想知道是啥OA :)
请先
登录
后评论
请先
登录
后评论
中铁13层打工人
77 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!