Keyi 的日常 


java代码审计思路


常见的审计思路
1.查看目录结构,查看配置文件,判断框架信息
2.查看使用的类库包是否安全
3.filter、controller
4.数据查询
5.危险函数审计
6.查看xml配置的数据库信息和文件信息
7.黑盒测试对应白盒测试功能点

spring mvc-ssh标准结构

spring-mvc框架
-w658

applicationContext.xml

正向审计是查看程序功能点与代码对应关系
反向审计是搜索函数去查找功能点

readObject()实例具体步骤

mvn结构详解

常见sping-mvc和spring-boot区别

1.下载源码解压以后查看是否有web.xml,有的化就是spring-mvc,没有的化就是注解模式-spring-boot

存在 web.xml 配置的 java web 项目,servlet3.0 的 java web 项目,springboot 内嵌容器的 java web 项目加载 servlet,filter,listener 的

ServletContainerInitializer 也是 Servlet 3.0 新增的一个接口,容器在启动时使用 JAR 服务 API(JAR Service API) 来发现 ServletContainerInitializer 的实现类,并且容器将 WEB-INF/lib 目录下 JAR 包中的类都交给该类的 onStartup() 方法处理,我们通常需要在该实现类上使用 @HandlesTypes 注解来指定希望被处理的类,过滤掉不希望给 onStartup() 处理的类。

一个典型的 servlet3.0+ 的 web 项目结构如下:
.
├── pom.xml
└── src
├── main
│ ├── java
│ │ └── moe
│ │ └── cnkirito
│ │ ├── CustomServletContainerInitializer.java
│ │ ├── filter
│ │ │ └── HelloWorldFilter.java
│ │ └── servlet
│ │ └── HelloWorldServlet.java
│ └── resources
│ └── META-INF
│ └── services
│ └── javax.servlet.ServletContainerInitializer
└── test
└── java

注册方式一:servlet3.0注解+@ServletComponentScan
springboot 依旧兼容 servlet3.0 一系列以 @Web* 开头的注解:@WebServlet,@WebFilter,@WebListener

@WebServlet("/hello")
public class HelloWorldServlet extends HttpServlet{}

注册方式二:RegistrationBean
@Bean
public ServletRegistrationBean helloWorldServlet() {
ServletRegistrationBean helloWorldServlet = new ServletRegistrationBean();
myServlet.addUrlMappings("/hello");
myServlet.setServlet(new HelloWorldServlet());
return helloWorldServlet;
}

@Bean
public FilterRegistrationBean helloWorldFilter() {
FilterRegistrationBean helloWorldFilter = new FilterRegistrationBean();
myFilter.addUrlPatterns("/hello/*");
myFilter.setFilter(new HelloWorldFilter());
return helloWorldFilter;
}

常见web-api框架

框架结构

webervice
-soap
-WSDL
-UDDI
-调用RPC与消息传递
-restful接口
-swagger
DWr
Hessian
GWT接口
-w1141

WEBSERVICE接口

漏洞点
1.默认的安全配置
2.未授权的访问
3.自身未修复漏洞

burp常见的样式,后缀是.wsdl
-w429
-w433

service,serivces,ws,webservice

swagger 接口

在pom.xml中添加Swagger依赖
创建Swagger配置类,与Application.java同级目录


常见的路径是
/swagger-ui.html

swagger测试网站
http://editor.swagger.io/
https://github.com/swagger-api/swagger-editor/releases

RESTful接口

RESTFUL是一种网络应用程序的设计风格和开发方式,基于HTTP,可以使用XML格式定义或JSON格式定义

在Restful
http://127.0.0.1/user/query/1 GET 根据用户id查询用户数据
http://127.0.0.1/user/save POST 新增用户
http://127.0.0.1/user/update POST 修改用户信息
http://127.0.0.1/user/delete/1 GET/POST 删除用户信息

RESTful用法:
http://127.0.0.1/user/1 GET 根据用户id查询用户数据
http://127.0.0.1/user POST 新增用户
http://127.0.0.1/user PUT 修改用户信息
http://127.0.0.1/user DELETE 删除用户信息

soap

使用工具是soapui
soap请求 (Simple Object Access Protocol,简单对象访问协议) 是HTTP POST的一个专用版本,遵循一种特殊的xml消息格式Content-type设置为: text/xml任何数据都可以xml化。

DWR接口

web.xml

debug
true


dwr-invoker
/dwr/*

dwr.xml

-w586

漏洞点
1.默认的安全配置项
2.未授权的访问
3.Debug状态下的问题

/dwr/index.html,/exec/index.html
HESSIAN接口
GWT接口

HESSIAN接口

HessianSpringInvokeService /*.hessian web.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">

<!-- hessian服务通过spring暴露出去 -->
<bean id ="EncryptService.hessian" class ="com.ufgov.admin.license.svc.EncryptServiceImpl">
</bean>

</beans>
看访问的文件格式默认是.hession 看content-type中:x-application/hession ![-w922](https://mwebkeyi.oss-cn-beijing.aliyuncs.com/2020/08/24/15793297519770.jpg) ![-w768](https://mwebkeyi.oss-cn-beijing.aliyuncs.com/2020/08/24/15793297646908.jpg) ![-w910](https://mwebkeyi.oss-cn-beijing.aliyuncs.com/2020/08/24/15793297829526.jpg)

-w910

1.未授权的访问
2.自带绕waf光环
3.自身未修复漏洞

GWT接口

漏洞
1.未授权访问
2.自带绕waf光环
3.接口枚举猜测

greetServlet com.google.gwt.sample.validation.server.GreetingServiceImpl greetServlet /gwtrpcservlet web.xml

-w605

idea快捷键

搜索文件名 shift 双击
Ctrl+N 按名字搜索类
在按照文本的内容查找 Control + Shift + F
Ctrl+Shift+N按文件名搜索文件
Ctrl+H 查看类的继承关系,例如HashMap的父类是AbstractMap
Ctrl+Alt+B查看子类方法实现 或者 Ctrl+Alt+鼠标左键
Ctrl+B可以查看父类或父方法定义,但是不如ctrl+鼠标左键方便
Alt+F7查找类或方法在哪被使用
显示便捷提示和快速修复 cmd + Enter
快速生成代码 Control + Enter
选中方法,查看参数信息 Cmd + P
弹出当前打开的文件列表 Cmd + E
根据0到9之间的数字,打开各个相应的工具窗口 Cmd+num 0-9
打开整个IDEA属性配置对话框 cmd + ,
查找当前文件 Cmd + F
快速定位到某一行某一列 Cmd + G
环绕选中代码块,生成注释 cmd + option + T
注释代码或者取消注释 Cmd + /
格式化代码 Cmd + option + L
优化导入,删除掉没用被使用的导入 Cmd + Option + O
缩进选中的行 tab
取消缩进选中的行 shift + tab
选中的单词或者代码,切换大小写 cmd + shift + u
返回或者前进最近编辑的地方 cmd + option + <- ->
打开变量声明处 cmd + B 或者 cmd + 鼠标左键
打开类型声明处 cmd + shift + B
插入注释模板 CMD + j

常见危险函数

java命令执行审计
ProcessBuilder.start()
Runtime.getRuntime().exec()
GroovyShell.evaluate()
exec、cmd、shell

如需用户输入参数,则对用户输入做严格校验,如&&、|、;等
避免命令用户可控

java反序列化审计
从上可得出结论,如果一个类需要序列化那么需要这个类或者父类实现 Serializable或者Externalizable接口。
对一个类进行序列化需要执行ObjectOutputStream.writeObject方法写入 对象
对一个类进行反序列化需要ObjectInputStream.readObject从输入流中读 取字节然后转换成对象
在反序列的过程中,被反序列化操作的类不会执行构造方法。
Serializable
Externalizabl
Externalizable
Transient
ObjectOutputStream.writeObject
readObject
writeObject
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

任意文件上传
ServletFileUpload
FileItemStream
MultipartFile
new FileInputStream()
new FileOutputStream()
new File()
new BufferedReader()
new ServletFileUpload()
new MultipartFile()
CommonsMultipartFile
printWrite
upload,write,fileName ,filePath
MultipartFile
createNewFile
FileInputStream

任意文件下载
download 、
fileName 、
filePath、
write、
getFile、
getWriter

任意文件删除
delete, deleteFile,fileName ,filePath

CSRF
审计方法:通过查看配置文件有没有配置 csrf 全局过滤器,如果没有则重点看每个操作前有 没有添加 token 的防护机制

输入方面进行总结
? request.getQueryString() ? request.getParameterMap() ? request.getParameterNames() ? request.getParameter() ? request.getHeader() ? request.getHeaders() ? request.getHeaderNames() ? req.getInputStream() ? ⋯⋯.

sql注入
? prepareStatement()
? createStatement()
? executeQuery()
? executeUpdate()
? execute()
$() #
Select、Dao 、from 、delete 、update、insert

  • append

缓冲区溢出
strcpy,strcat,scanf,memcpy,memmove,memeccpy Getc(),fgetc(),getchar;read,printf

ssrf
HttpURLConnection.getInputStream
URlConnection.getInputStream
Request.Get.execute
Request.Post.execute
URL.openStrem
ImagesIO.read
OkHttpClient.newCall.execute
HttpClients.execute
HttpClinet.execute
HttpClient.executeMethod
HttpURLConnection.connect
HttpURLConnection.getInputStream
URL.openStream

xxe
XMLReaderFactory.createXMLReader();
new SAXReader
new SAXBuilder
DocumentBuilderFactory
XPathExpression
DocumentBuilder
TransformerFactory
javax.xml.parsers.DocumentBuilder
javax.xml.stream.XMLStreamReader
org.jdom.input.SAXBuilder
org.jdom2.input.SAXBuilder
javax.xml.parsers.SAXParser
org.dom4j.io.SAXReader
org.xml.sax.XMLReader
javax.xml.transform.sax.SAXSource
javax.xml.transform.TransformerFactory
javax.xml.transform.sax.SAXTransformerFactory
javax.xml.validation.SchemaFactory
javax.xml.bind.Unmarshaller

DocumentBuilder、XMLStreamReader、SAXBuilder、SAXParser SAXReader 、XMLReader SAXSource 、TransformerFactory 、SAXTransformerFactory 、 SchemaFactory

硬编码
密码硬编码、密码明文存储
password 、pass、jdbc

xss
getParamter、<%=、param.

spel表达式注入
Spel是Spring框架el表达式的缩写,当使用SpelExpressionParser解析spel表达式,且表达式可被外部控制,则可能导致SPel表达式注入从而造成RCE,如CVE-2018-1260就是spring-security-oauth2的一个SPel注入导致的RCE 。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
ExpressionParser PARSER = new SpelExpressionParser();
Expression exp = PARSER.parseExpression(el)

@RequestMapping(path = "/elinjection")
public class SPelInjectionController {
@RequestMapping(value="/spel.html",method= RequestMethod.GET)
public String SPelInjection(ModelMap modelMap, HttpServletRequest request, HttpServletResponse response) throws IOException {
String el=request.getParameter("el");
//el="T(java.lang.Runtime).getRuntime().exec(\"open /Applications/Calculator.app\")";
ExpressionParser PARSER = new SpelExpressionParser();
Expression exp = PARSER.parseExpression(el);
return (String)exp.getValue();
}
}

Expression
SpelExpressionParser
getValue

文件上传
MultipartFile

Autobinding-自动绑定漏洞
这里使用了@ModelAttribute User user,实际上这里是从session中获取user对象。但存在问题是如果在请求中添加user对象的成员变量时则会更改user对象对应成员的值。
所以当我们给resetQuestionHandler发送GET请求的时候可以添加“answer=hehe”参数,这样就可以给session中的对象赋值,将原本密码找回的安全问题答案修改成“hehe”。这样在最后一步校验安全问题时即可验证成功并找回密码
@SessionAttributes
@ModelAttribute

压缩包文件上传
看上传的文件是否可以控制解压路径
是否有xxe

excel xxe
Poi-ooxml.jar的XXE漏洞

xlsx-streamer.jar
XSSFReader()和document()函数

URL重定向
sendRedirect
setHeader
forward

日志记录敏感信息
log log.info logger.info

不安全组件暴露
activity 、 Broadcast Receiver 、 Content Provider 、 Service 、 inter-filter

代码执行
eval、system、exec

越权
水平、垂直越权不需关注特定函数,只要在处理用户操作请求时查看是否有对当前登陆用户权限做校验从而确定是否存在漏洞

批量请求

1
2
3
4
5
6
7
8
9
10
@RequestMapping(value="/ifUserExit",method = RequestMethod.GET)
public String ifUserExit(Model model, HttpServletRequest request) throws IOException {
String phone = request.getParameter("phone");
if(! phone.isEmpty()){
boolean ifex=userModel.ifuserExitByPhone(phone);
if (!ifex)
return "用户不存在";
}
return "用户已被注册";
}

信息泄露
js中搜索
ip,密码,账号,测试账号,137,139,用户,ftp配置,192.168, 10. http, https

预编译
SELECT * From table_name WHERE name=‘XX’ and password=‘YY’ and corporate=‘ZZ’

添加 ' or 1=1 -
SELECT * From table_name WHERE name=’’ and password=’’ and corporate='' or 1=1-'
使用预编译后会吧后边当做一个整体

mybatis
Statement的几种实现
Statement 对象用于将SQL语句发送到数据库中。
Statement每次执行SQL语句,数据库都要执行SQL语句的编译,最好用于仅执行一次查询并返回结果的情形
1、执行静态SQL语句。通常通过Statement实例实现。
2、执行动态SQL语句。通常通过PreparedStatement实例实现。
3、执行数据库存储过程。通常通过CallableStatement实例实现。

’和‘$’的区别
sql 预编译指的是数据库驱动在发送 sql 语句和参数给 DBMS 之前对 sql 语句进行编译,这样 DBMS 执行 sql 时,就不需要重新编译。
‘#{ }’:解析为一个 JDBC 预编译语句(prepared statement)的参数标记符,一个‘ #{ }’ 被解析为一个参数占位符 ? 。
‘${ }’ 仅仅为一个纯粹的 string 替换,在动态 SQL 解析阶段将会进行变量替换。在预编译之前已经被变量替换了
‘${ }’变量的替换阶段是在动态 SQL 解析阶段,而’#{ }’变量的替换是在 DBMS 中。

PreparedStatement与Statement有什么区别
1.PreparedStatement能预编译,这条预编译的SQL查询语句能在将来的查询中重用,这样一来,它比Statement对象生成的查询速度更快。
2.PreparedStatement可以写动态参数化的查询
3.PreparedStatement可以防止SQL注入式攻击
4.PreparedStatement查询可读性更好,追加条件的语句很乱
5.PreparedStatement不允许一个占位符(?)有多个值

hibernate参数绑定

快速审计

1 查看jar包
2 标记为spring 然后查看路由
-w1597

查找路由
@RequestMapping({

jar包安全

fastjson <=1.2.48可以rce;<=1.2.58可以dos
Apache Shiro < 1.24 反序列漏洞
jackson <= 2.9.2 反序列化漏洞
Poi-ooxml.jar <=3.11 dos xxe
xlsx-streamer.jar <=2.0.0 xxe
Spring 5.0.x< 5.0.6 Spring 4.3.x< 4.3.7
Struts 2.0.4 - Struts 2.3.34 Struts 2.5.0 - Struts 2.5.16
XStream(XStream Core)< 1.4.11.1 ;1.4.10可以直接rce,1.4.11.1利用jdni注入

dubbo版本<2.7.5,http协议反序列化漏洞(CVE-2019-17564)
2.7.0 <= Apache Dubbo <= 2.7.4
2.6.0 <= Apache Dubbo <= 2.6.7
Apache Dubbo 2.5.x 的所有版本

危险利用链

commons-fileupload 1.3.1
commons-io 2.4
commons-collections 3.1
commons-logging 1.2
commons-beanutils 1.9.2
org.slf4j:slf4j-api 1.7.21
com.mchange:mchange-commons-java 0.2.11
org.apache.commons:commons-collections 4.0
com.mchange:c3p0 0.9.5.2
org.beanshell:bsh 2.0b5
org.codehaus.groovy:groovy 2.3.9
org.springframework:spring-aop 4.1.4.RELEASE

白盒检测

搜索以下函数:
ObjectInputStream.readObject
ObjectInputStream.readUnshared
XMLDecoder.readObject
Yaml.load
XStream.fromXML
ObjectMapper.readValue
JSON.parseObject

参考

https://cws6.github.io/2018/09/07/java%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E6%BC%8F%E6%B4%9E%E5%85%A5%E9%97%A8%E5%88%86%E6%9E%90/






© - 无尾熊 - 2019 - 2021 - Powered by hexo