前段时间爆出一个U8cloud
的SQL注入,路径为/u8cloud/api/file/upload/base64
,在此之前也做过U8cloud
的代码审计,没有发现和这个路径类似的路径,正好这次有时间,来复现分析一下这个漏洞到底是怎么回事。
按照网上给出的POC
,利用结果如下图,注入点在请求头的system
字段。
但是神奇的是,如果吧路径中的file/upload/base64
随便替换为其他东西,会发现居然也能成功注入,这就很耐人寻味了,这个漏洞和file/upload/base64
居然没有半毛钱关系。
接下来掏出朋友给的一份编译后的源码,全局搜索u8cloud/api
,很快就在webapps/u8c_web/WEB-INF/web.xml
中找到了这个路径,对应的servlet
是ExtSystemInvokerServlet
,除了他以外,/u8cloud/openapi/*
、/u8cloud/yls/*
、/u8cloud/extsystem/dst/*
三个路径也都对应到了ExtSystemInvokerServlet
。
而这个ExtSystemInvokerServlet
的位置在fw.jar!\nc\bs\framework\server\extsys\ExtSystemInvokerServlet
。
找到这个类,来看他的doAction()
方法。重点关注一下ExtSystemServerEnum
和serviceName
ExtSystemServerEnum
是一个枚举类,包含/u8cloud/yls
、/u8cloud/extsystem/dst
、/u8cloud/api/
、/u8cloud/openapi/
四个常量。
回到上面的doAction()
方法,我们要保证我们的request.getRequestURI()
必须是以上述四个常量之一开头才可以,否则会抛出异常,也就是说不能按照一般的/servlet/*
路径根据模块名和包名去调用,否则就会报错。
此时,如果我们访问的路径是/u8cloud/api/file/upload/base64
,就会匹配到/u8cloud/api/
,然后serviceName
就被赋值为u8cloud_api
。
接着一路向下,进入getServiceObject()
。
根据serviceName
也就是u8cloud_api
去找对应的类。这里具体逻辑感兴趣的可以自行去分析,偷了个懒。
根据这项目的惯性,一般就是在各种配置文件中进行的配置。全局搜索一下u8cloud_api
,在/modules/uap/META-INF/P_API.upm
中找到如下所示的配置,找到u8c.server.APIServletForJSON
这么一个类。
继续跟进,在doAction()
方法中,会先判断request.getPathInfo()
,显然不是以file.
开头,进入APIController.forWard(request)
。
在APIController.forWard()
中,会发现存在checkUser()
进行校验,跟进看一下。
在这个地方,看到了本次分析的主角system
,通过inputData.getSystem()
获取,然后传入APIOutSysUtil.getOutSysVOByCode()
中。
继续跟进一下,明晃晃的字符串拼接就出现了,就造成了SQL
注入。
还在校验身份甚至没有到校验授权的时候就完成了注入,这也就是我们请求/u8cloud/api/f
都可以成功注入的原因了。
自此,关于这个漏洞的一些情况就分析完毕了,但是也还是遗留了一些问题,比如/u8cloud/api/
后的服务模块具体是怎么调用的,感兴趣的师傅们就自行去研究了。
1 篇文章
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!