第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1


所需环境

  1. Java基础环境

  2. maven ,配置镜像源

  3. MySQL

  4. tomcat


这里引用一下网图

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

Java EE分层模型

Domain Object(领域对象)层:此层由系列的POJO(Plain Old Java Object,普通的、传统的java对象)组成,这些对象是该系统的Domain Object,往往包含了各自所需要实现的业务逻辑方法。

DAO(Data Access Object,数据访问对象)层:此层由系统的DAO组建组成,这些DAO实现了对数据库的创建、查询、更新和删除(CRUD)等原子操作。

Service(业务逻辑层):此层由系列的业务逻辑对象组成,这些业务逻辑对象实现了系统所需要的业务逻辑方法。这些业务逻辑方法可以仅仅用于暴露Domain Object对象所实现的业务逻辑方法,也可能是依赖DAO组件实现的业务逻辑方法。

Controller( 控制器层):此层由系列控制器组成,这些控制器用于拦截用户请求,并调用业务逻辑组件的业务逻辑方法,处理用户请求,并根据处理结果转发到不同的表现层组件。

View(表现层):此层由系列的JSP页面、Velocity页面、PDF文档视图组件组成,负责收集用户请求,并将显示处理结果。

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

MVC模式

模型(Model):模型是应用程序中用于封装数据以及与数据相关的业务逻辑的部分。它直接管理应用程序的数据、逻辑和规则,对外提供接口使得数据可以被视图或控制器访问和修改。模型并不关心数据如何展示给用户,它的重点在于维护数据的完整性和一致性。

视图(View):视图负责数据的展示,即用户界面。它是应用程序中用户可见的部分,用来显示从模型中获取的数据。视图可以根据模型数据的变化自动更新,但本身不包含业务逻辑,仅专注于如何呈现数据。

控制器(Controller):控制器作为模型和视图之间的协调者,负责接收用户的输入,对用户的请求进行处理,并根据需要调用模型中的业务逻辑方法。处理完成后,控制器可能会更新模型的状态,或者指示视图进行相应的更新以反映模型的变化。

+---------+       +----------------+       +------------------+|         |       |                |       |                  ||  用户   +------>+   控制器(C)   +------>+    模型(M)      ||         ||                |   处理|                  ||         |  户   +----------------+       +------------------+|         |       |                |       |                  ||         +<------+    视图(V)     +<------+    业务逻辑      ||         |       |                |       |                  |+---------+       +----------------+       +------------------+

    在对一个项目进行审计的时候,本质上就是 三部分的组合:污点(Taint),源(Source),数据流向 , 这个也是一些静态代码审计工具的原理。首先污点是存在漏洞的代码,如:new File(Stirng fileName) , 污点就是fileName , 源就是这个fileName哪里传进来的。我们需要从Controller层找源,因为那个是直接获取前端数据的层,如果Controller层的源和污点的数据流向是通的,那就说明这个漏洞可能存在。只有我们知道了分层结构,去审计代码的时候才能更快的找到数据流向是否连通。

JavaWeb三大核心技术

Servlet


什么是 Servlet 容器?

    正如我们看到的,用户/客户端只能从服务器请求静态网页。如果用户希望根据自己的输入阅读网页,那么这还不够好。Servlet 容器的基本思想是使用 Java 动态生成服务器端的网页。所以 Servlet 容器本质上是与 Servlet 交互的 Web 服务器的一部分。

“    Servlet 容器”是一个装载一堆 Servlet 对象的“器具”(容器),并且具备管理这些对象的功能。


第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

配置方式:

基于web.xml配置文件

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1


第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

基于注解的方式:

| 注解                | 参数                      | 含义                                                                                      ||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@WebServlet`       | `name`                    | Servlet 的名称。||                     | `urlPatterns` / `value`   | 映射到 Servlet 的 URL 模式。||                     | `initParams`              | 初始化参数,类型为 `WebInitParam[]`。||                     | `loadOnStartup`           | 指定 Servlet 的加载顺序。||                     | `asyncSupported`          | 指定 Servlet 是否支持异步处理。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@WebFilter`        | `filterName`              | 过滤器的名称。||                     | `urlPatterns` / `value`   | 映射到过滤器的 URL 模式。||                     | `servletNames`            | 映射到过滤器的 Servlet 名称。||                     | `dispatcherTypes`         | 过滤器的分发类型,类型为 `DispatcherType[]`。||                     | `initParams`              | 初始化参数,类型为 `WebInitParam[]`。||                     | `asyncSupported`          | 指定过滤器是否支持异步处理。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@WebListener`      | 无                        | 用于定义监听器。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@MultipartConfig`  | `location`                | 用于存储上传文件的目录。||                     | `fileSizeThreshold`       | 文件大小超过该值时,文件内容将被写入磁盘。||                     | `maxFileSize`             | 单个上传文件的最大大小。||                     | `maxRequestSize`          | 总的上传文件的最大大小。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@ServletSecurity`  | `value`                   | 安全性约束,类型为 `HttpConstraint`。||                     | `httpMethodConstraints`   | 为特定 HTTP 方法定义安全约束,类型为 `HttpMethodConstraint[]`。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@WebInitParam`     | `name`                    | 初始化参数的名称。||                     | `value`                   | 初始化参数的值。||                     | `description`             | 初始化参数的描述。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@HandlesTypes`     | `value`                   | 指定 Servlet 容器在启动时应该扫描和处理的类型。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@ServletComponentScan` | `basePackageClasses`  | 基础包类。||                     | `basePackages`            | 基础包名称。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@HttpConstraint`   | `value`                   | 安全性约束,类型为 `ServletSecurity.EmptyRoleSemantic`。||                     | `rolesAllowed`            | 允许访问的角色。||                     | `transportGuarantee`      | 传输保证,类型为 `ServletSecurity.TransportGuarantee`。||---------------------|---------------------------|-------------------------------------------------------------------------------------------|| `@HttpMethodConstraint` | `value`              | HTTP 方法名称。||                     | `rolesAllowed`            | 允许访问的角色。||                     | `transportGuarantee`      | 传输保证,类型为 `ServletSecurity.TransportGuarantee`。||                     | `emptyRoleSemantic`       | 空角色语义,类型为 `ServletSecurity.EmptyRoleSemantic`。|
 
import javax.servlet.annotation.WebServlet;import javax.servlet.annotation.WebInitParam;import javax.servlet.http.HttpServlet;
@WebServlet( name = "MyServlet", urlPatterns = {"/myServlet"}, initParams = { @WebInitParam(name = "param1", value = "value1", description = "Parameter 1 description"), @WebInitParam(name = "param2", value = "value2", description = "Parameter 2 description") }, loadOnStartup = 1, asyncSupported = true)public class MyServlet extends HttpServlet { // Servlet implementation}import javax.servlet.annotation.WebFilter;import javax.servlet.annotation.WebInitParam;import javax.servlet.*;
@WebFilter( filterName = "MyFilter", urlPatterns = {"/myServlet"}, servletNames = {"MyServlet"}, dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD}, initParams = { @WebInitParam(name = "filterParam1", value = "value1", description = "Filter Parameter 1") }, asyncSupported = true)public class MyFilter implements Filter { public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { // Filter implementation chain.doFilter(request, response); }}

访问流程:

1、在浏览器输入对应的网址,如:http://ip:port/test

2、HTTP请求达到Servlet容器,通过我们注册的Servlet ,找到对应的Class文件路径

3、将结果返回到浏览器

但是在第2步,有分为几个步骤,这就是servlet的生命周期相关的东西

生命周期:

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

init()

    方法在 Servlet 生命周期的初始化阶段调用。它被传递一个实现 javax.servlet.ServletConfig 接口的对象,该接口允许 Servlet 从 Web 应用程序访问初始化参数。

service() 

    方法在初始化后对每个请求进行调用。每个请求都在自己的独立线程中提供服务。Web容器为每个请求调用 Servlet 的 service() 方法。service() 方法确认请求的类型,并将其分派给适当的方法来处理该请求。

destroy() 

方法在销毁 Servlet 对象时调用,用来释放所持有的资源。

从 Servlet 对象的生命周期中,我们可以看到 Servlet 类是由类加载器动态加载到容器中的。每个请求都在自己的线程中,Servlet 对象可以同时服务多个线程(线程不安全的)。当它不再被使用时,会被 JVM 垃圾收集。

像任何Java程序一样,Servlet 在 JVM 中运行。为了处理复杂的 HTTP 请求,Servlet 容器出现了。Servlet 容器负责 Servlet 的创建、执行和销毁。

Servlet 容器和 Web 服务器如何处理一个请求的

  1. Web 服务器接收 HTTP 请求。

  2. Web 服务器将请求转发到 Servlet 容器。

  3. 如果对应的 Servlet 不在容器中,那么将被动态检索并加载到容器的地址空间中。

  4. 容器调用 init() 方法进行初始化(仅在第一次加载 Servlet 时调用一次)。

  5. 容器调用 Servlet 的 service() 方法来处理 HTTP 请求,即读取请求中的数据并构建响应。Servlet 将暂时保留在容器的地址空间中,可以继续处理其它 HTTP 请求。

  6. Web 服务器将动态生成的结果返回到浏览器/客户端。

Filter

配置方式:

import javax.servlet.annotation.WebFilter;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import java.io.IOException;
@WebFilter(urlPatterns = "/path/*")public class MyFilter implements Filter {// Filter 的逻辑代码}

基于配置的方式

参数名称

含义

filter-name

过滤器的名称

filter-class

过滤器类的完全限定名

init-param

过滤器的初始化参数

url-pattern

过滤器映射到的 URL 模式

servlet-name

过滤器映射到的 Servlet 名称

dispatcher

过滤器的分发类型

async-supported

指定过滤器是否支持异步处理

基于注解的方式:

| 注解参数              | 含义                                  ||----------------------|---------------------------------------|| `@WebFilter`         |                                       || `filterName`         | 过滤器的名称                          || `urlPatterns` / `value` | 过滤器映射到的 URL 模式            || `servletNames`       | 过滤器映射到的 Servlet 名称           || `dispatcherTypes`    | 过滤器的分发类型,类型为 `DispatcherType[]` || `initParams`         | 初始化参数,类型为 `WebInitParam[]`  || `asyncSupported`     | 指定过滤器是否支持异步处理            |

访问流程:

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1 第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1 第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

生命周期:

 

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

1、初始化(Initialization):

    在过滤器实例化后,容器会调用过滤器的 init 方法,用于初始化过滤器的资源和配置。这个方法在过滤器的生命周期中只会被调用一次。在 init 方法中,你可以进行一些初始化工作,如读取配置文件等。

public void init(FilterConfig filterConfig) throws ServletException {     // 初始化操作,读取配置等}

2、运行中(Request Processing):

    一旦过滤器初始化完成,它会开始拦截请求。当请求匹配过滤器所配置的拦截路径时,容器会调用过滤器的 doFilter 方法来处理请求。在这个阶段,你可以对请求进行修改、记录日志、验证身份等操作。

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)        throws IOException, ServletException {    // 请求处理前的操作    chain.doFilter(request, response); // 继续请求处理    // 请求处理后的操作}

3、销毁(Destruction)

     当 Web 应用关闭或过滤器被从应用中移除时,容器会调用过滤器的 destroy 方法,用于释放资源、关闭连接等清理工作。和 init 方法一样,destroy 方法也只会被调用一次。

public void destroy() { 2 // 清理资源,关闭连接等 3 }

Listener

https://blog.csdn.net/sinat_41655101/article/details/79555313

JSP

jsp 中的三种脚本

声明脚本

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1
<%!    private Integer id;    private String name;    private static Map map = new HashMap<>();%><%!    //声明 static 静态代码块    static {        map.put("key1",1);        map.put("key2",2);        map.put("key3",3);        map.put("key4",4);    }%>

表达式脚本

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1



<%=12 %><%=12.12 %><%="我是字符串" %><%=map %><%=request.getParameter("username") %>

代码脚本


<%    int i =12;    if (i == 12){        System.out.println("好厉害" );    }else {        System.out.println("家的啊");    }%><%    for (int i1 = 0; i1 < 10; i1++) {        System.out.println(i1);    }%><%    String username = request.getParameter("username");    System.out.println(username);%>

jsp 九大内置对象


request 对象 请求对象,可以获取请求信息

response 对象 响应对象。可以设置响应信息

pageContext 对象 当前页面上下文对象。可以在当前上下文保存属性信息

session 对象 会话对象。可以获取会话信息。

exception 对象 异常对象只有在 jsp 页面的

page 指令中设置 isErrorPage=”true” 的时候才会存在 application 对象

ServletContext 对象实例,可以获取整个工程的一些信息。

config 对象 ServletConfig 对象实例,可以获取 Servlet 的配置信息 out 对象 输出流。

page 对象 表示当前 Servlet 对象实例(无用,用它不如使用 this)


九大内置对象,都是我们可以在【代码脚本】中或【表达式脚本】中直接使用的对 象。

jsp 四大域对象

 四大域对象经常用来保存数据信息。


pageContext 可以保存数据在同一个 jsp 页面中使用

request 可以保存数据在同一个 request 对象中使用。经常用于在转发的时候传递数据

session 可以保存在一个会话中使用

application(ServletContext) 就是 ServletContext 对象,工程创建时创建,工程关闭时销毁。(可以)

它们从小到大的顺序分别是:pageContext 、Request、Session 、application

使用的优先顺序是从小到大:pageContext 、Request、Session 、application


jsp 的常用标签

1)静态包含–很常用

<%@ include file=”” %>

静态包含是把包含的页面内容原封装不动的输出到包含的位置。

2)动态包含–很少用

< /jsp:include>

动态包含会把包含的 jsp 页面单独翻译成 servlet 文件,然后在执行到时候再调用翻译的 servlet 程序。并把 计算的结果返回。动态包含是在执行的时候,才会加载。所以叫动态包含。

3)页面转发–常用

< /jsp:forward>

< jsp:forward> 转发功能相当于

request.getRequestDispatcher(“/xxxx.jsp”).forward(request, response);

EL表达式和JSTL 标签库

EL表达式

EL 表达式的全称是:Expression Language。是表达式语言。EL 表达式的什么作用:EL 表达式主要是代替 jsp 页面中的表达式脚本在 jsp 页面中进行数据的输出。因为 EL 表达式在输出数据的时候,要比 jsp 的表达式脚本要简洁很多

<%    request.setAttribute("key","key1");%>表达式脚本输出: <%=request.getAttribute("key1")%>EL表达式输出: ${key1}

EL 表达式输出 Bean 的普通属性,数组属性。List 集 合属性,map 集合属性

<%    Person person = new Person();    person.setName("tom");    person.setPhones(new String[]{"186515151","156295654","123521888"});    ArrayList cities = new ArrayList<>();    cities.add("北京");    cities.add("南京");    cities.add("上海");    cities.add("深圳");    person.setCities(cities);    Map map = new HashMap<>();    map.put("key1","values1");    map.put("key2","values2");    map.put("key3","values3");    map.put("key4","values4");    map.put("key5","values5");    person.setMap(map);    pageContext.setAttribute("person",person);%>
输出person的属性:${person}输出person的name属性: ${person.name}输出person的phones1数组属性: ${person.phones[0]}输出person的phones2数组属性: ${person.phones[1]}输出person的phones3数组属性: ${person.phones[2]}输出person的cities集合1的属性: ${person.cities[0]}输出person的cities集合2的属性: ${person.cities[1]}输出person的map集合的属性: ${person.map}输出person的map集合1的属性: ${person.map.key2}

EL表达式之所以能够输出Bean中的属性,是因为它调用了get方法,当Bean中没有get方法的时候,就没办法获取Bean中的属性了

EL 表达式的 11 个隐含对象

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

EL 获取四个特定域中的属性

pageScope ====== pageContext 域requestScope ====== Request 域sessionScope ====== Session 域applicationScope ====== ServletContext 域<%--    ${pageContext}--%>    <%=request.getScheme()%>     1.协议:${pageContext.request.scheme}     2.服务器ip: ${pageContext.request.serverName}    3.服务器端口号 : ${pageContext.request.serverPort}    4.获取工程路径:${pageContext.request.contextPath}    5.获取请求的方法: ${pageContext.request.method}    6.获取客户端IP: ${pageContext.request.remoteHost}    7.获取会话的id: ${pageContext.session.id}

JSTL 标签库

https://blog.csdn.net/w_linux/article/details/79885939

案例:

doGet 请求的中文乱码解决

// 获取请求参数String username = req.getParameter("username");//1 先以 iso8859-1 进行编码//2 再以 utf-8 进行解码username = new String(username.getBytes("iso-8859-1"), "UTF-8");

POST 请求的中文乱码解决

@Overrideprotected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException{    // 设置请求体的字符集为 UTF-8,从而解决 post 请求的中文乱码问题    req.setCharacterEncoding("UTF-8");    System.out.println("-------------doPost------------");        //要在获取参数设置字符编码        // 获取请求参数    String username = req.getParameter("username");    String password = req.getParameter("password");    String[] hobby = req.getParameterValues("hobby");    System.out.println("用户名:" + username);    System.out.println("密码:" + password);    System.out.println("兴趣爱好:" + Arrays.asList(hobby));}

请求的转发

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1
/**************************Servlet1代码***************************/public class Servlet1 extends HttpServlet {    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException,            IOException {// 获取请求的参数(办事的材料)查看        String username = req.getParameter("username");        System.out.println("在 Servlet1(柜台 1)中查看参数(材料):" + username);// 给材料 盖一个章,并传递到 Servlet2(柜台 2)去查看        req.setAttribute("key1","柜台 1 的章");// 问路:Servlet2(柜台 2)怎么走/** * 请求转发必须要以斜杠打头,/ 斜杠表示地址为:http://ip:port/工程名/ , 映射到 IDEA 代码的 web 目录 <br/> * */        RequestDispatcher requestDispatcher = req.getRequestDispatcher("/servlet2");// RequestDispatcher requestDispatcher = req.getRequestDispatcher("http://www.baidu.com");// 走向 Sevlet2(柜台 2)        requestDispatcher.forward(req,resp);}}
//为了方面也写成:req.getRequestDispatcher("/servlet2").forward(req,resp);
/***********************Servlet2 代码***********************/ public class Servlet2 extends HttpServlet { @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {// 获取请求的参数(办事的材料)查看 String username = req.getParameter("username"); System.out.println("在 Servlet2(柜台 2)中查看参数(材料):" + username);// 查看 柜台 1 是否有盖章 Object key1 = req.getAttribute("key1"); System.out.println("柜台 1 是否有章:" + key1);// 处理自己的业务 System.out.println("Servlet2 处理自己的业务 "); }}

重定向

可能会出现URL跳转

第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1
/*请求重定向的第一种方案:*/        // 设置响应状态码 302 ,表示重定向,(已搬迁)        resp.setStatus(302);// 设置响应头,说明 新的地址在哪里        resp.setHeader("Location", "http://localhost:8080");
/*-----------------------------------------------------*/
//请求重定向的第二种方案(推荐使用):resp.sendRedirect("http://localhost:8080");

响应的乱码解决

/*解决响应中文乱码方案一(不推荐使用):*/        // 设置服务器字符集为 UTF-8        resp.setCharacterEncoding("UTF-8");// 通过响应头,设置浏览器也使用 UTF-8 字符集        resp.setHeader("Content-Type", "text/html; charset=UTF-8");
/*-----------------------------------------------------------------------------*/
/*解决响应中文乱码方案二(推荐):*/ // 它会同时设置服务器和客户端都使用 UTF-8 字符集,还设置了响应头// 此方法一定要在获取流对象之前调用才有效 resp.setContentType("text/html; charset=UTF-8");

现有需求如下:

1、身份:包含管理员和普通用户

2、登陆成功后都跳转到首页,管理员有两个按钮:查看个人信息和查看所有人员信息 。普通用户只能查看个人信息。

3、保证权限校验的正确,不能存在垂直越权。

4、前端页面使用jsp

5、先不使用用数据库,使用本地模拟的方式提供数据。后面讲到sql注入的时候在说数据库。


未完持续…..



原文始发于微信公众号(安全随心录):第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1

版权声明:admin 发表于 2024年7月5日 下午9:40。
转载请注明:第二节:Java代码审计零点五基础系统学习之JavaWeb快速入门-1 | CTF导航

相关文章