ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

Java SQL Inject/XSS/SSRF

2022-01-26 16:33:54  阅读:228  来源: 互联网

标签:username XSS Java url resp req Inject SQL new


Java SQL Inject

JDBC SQL Inject

JDBC 原生查询如果没有经过预编译,而是直接进行 SQL 语句的拼接,这时过滤不严格则会产生 SQL 注入问题,比如下面代码就是一个带有 SQL 注入漏洞的 Demo

Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/security?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "123456");
String sql = "select * from users where id = '"+id+"'";
resp.getWriter().write("The SQL statement:" + sql + "\n");
Statement statement = conn.createStatement();
ResultSet resultSet = statement.executeQuery(sql);

预编译修复

Class.forName("com.mysql.cj.jdbc.Driver");
Connection conn = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/security?characterEncoding=utf8&useSSL=false&serverTimezone=UTC", "root", "123456");
String sql = "select * from users where id = ?";
PreparedStatement preparedStatement = conn.prepareStatement(sql);
preparedStatement.setString(1,id);
ResultSet resultSet = preparedStatement.executeQuery();

Mybatis SQL Inject

Mybatis 执行SQL语句也有预编译和直接拼接两种方法,如果直接拼接SQL语句且过滤不严格则会产生SQL注入问题,比如下面一个查询语句,使用了 ${} 直接拼接值

<select id="selectUserByName" resultType="com.mybatis.pojo.User">
    SELECT * FROM Users WHERE username = '${username}'
</select>

使用 #{} 进行预编译则可以有效防御 SQL 注入问题

<select id="selectUserByName" resultType="com.mybatis.pojo.User">
    SELECT * FROM Users WHERE username = '#{username}'
</select>

LIKE Query

对于 Like 查询,直接预编译则程序会抛出异常

<select id="selectUserByLikeName" resultType="com.mybatis.pojo.User">
    SELECT * FROM Users WHERE username like '%#{username}#'
</select>

如果开发人员为了防止报错而改为直接取值且没有足够过滤则产生SQL注入问题

<select id="selectUserByLikeName" resultType="com.mybatis.pojo.User">
    SELECT * FROM Users WHERE username like '%${username}%'
</select>

直接预编译会报错,那么就使用 concat 连接预编译,既不会抛出异常也防御了SQL注入

<select id="selectUserByLikeNameRepair" resultType="com.mybatis.pojo.User">
    SELECT * FROM Users WHERE username like concat('%',#{username},'%')
</select>

IN/ORDER BY Query

同理,IN/ORDER BY 查询直接预编译也会使得程序抛出异常,如果开发人员改为直接拼接的方式构造SQL语句且没有足够过滤则会产生SQL注入

JavaWeb Inject Demo :https://github.com/ky0103/JavaSecurityDemo/tree/main/SQLInject

需要把 Myabtis/JDBC 依赖加入到 WEB-INF/lib 目录下

image-20220125182000471

Java XSS

在 Java 中 XSS 的产生一般是在 Servlet 中获取到参数值,然后设置到 request 属性中,在 jsp 文件中就可以直接引用 request 中的值了,而如果没有对参数值进行过滤,那么就可能产生 XXS 问题。如下代码就没有进行过滤就设置属性值了

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String username = req.getParameter("username");
    req.setAttribute("username",username);
    req.getRequestDispatcher("/index.jsp").forward(req,resp);
}

XSS 防御可以利用 ESAPI

ESAPI(Enterprise Security API)是一个免费开源的Web应用程序API,目的帮助开发者开发出更加安全的代码,并且它本身就很方便调用。

依赖

<dependency>
    <groupId>org.owasp.esapi</groupId>
    <artifactId>esapi</artifactId>
    <version>2.2.1.1</version>
</dependency>

在存储值到 request 中前用 ESAPI 进行过滤操作

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String username = req.getParameter("username");
    ESAPI.encoder().encodeForJavaScript(username);
    req.setAttribute("username",username);
    req.getRequestDispatcher("/index.jsp").forward(req,resp);
}

JavaWeb Inject Demo :https://github.com/ky0103/JavaSecurityDemo/tree/main/XSS

需要把 ESAPI 依赖加入到 WEB-INF/lib 目录下

image-20220125192550194

Java SSRF

HttpURLConnection 类的 SSRF 只支持 HTTP/HTTPS 协议,不支持 file 等协议

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String url = req.getParameter("url");
    if (url != null){
        URL url1 = new URL(url);
        String htmlContent;
        URLConnection urlConnection = url1.openConnection();
        HttpURLConnection httpURLConnection = (HttpURLConnection)urlConnection;
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(httpURLConnection.getInputStream()));
        StringBuffer html = new StringBuffer();
        while ((htmlContent = bufferedReader.readLine()) != null){
            html.append(htmlContent);
        }
        bufferedReader.close();
        resp.getWriter().println(html);
    }else {
        resp.getWriter().write("?url");
    }
}

URLConnection 支持 HTTP/HTTPS/file 等协议

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String url = req.getParameter("url");
    if (url != null){
        URL url1 = new URL(url);
        String htmlContent;
        URLConnection urlConnection = url1.openConnection();
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
        StringBuffer html = new StringBuffer();
        while ((htmlContent = bufferedReader.readLine()) != null){
            html.append(htmlContent);
        }
        bufferedReader.close();
        resp.getWriter().println(html);
    }else {
        resp.getWriter().write("?url");
    }
}

SSRF 下的文件下载,其实就是把响应头修改一下而已

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String fileName = "secret.txt";
    resp.setHeader("content-disposition","attachment;fileName="+fileName);
    String url = req.getParameter("url");
    int length;
    URL u = new URL(url);
    InputStream inputStream = u.openStream();
    byte[] bytes = new byte[1024];
    while ((length = (inputStream.read(bytes))) > 0){
        resp.getOutputStream().write(bytes,0,length);
    }
}

SSRF 下对文件的读取,无法读取非图片类文件,但是可以探测文件是否存在

@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String url = req.getParameter("url");
    URL u = new URL(url);
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    InputStream inputStream1 = u.openStream();
    ImageInputStream imageInputStream = ImageIO.createImageInputStream(inputStream1);
    BufferedImage read = ImageIO.read(imageInputStream);
    ImageIO.write(read,"png",byteArrayOutputStream);
    InputStream inputStream = new ByteArrayInputStream(byteArrayOutputStream.toByteArray());
    int length;
    byte[] bytes = new byte[1024];
    while ((length = (inputStream.read(bytes))) > 0){
        resp.getOutputStream().write(bytes,0,length);
    }
}

JavaWeb SSRF Demo :https://github.com/ky0103/JavaSecurityDemo/tree/main/XSS

标签:username,XSS,Java,url,resp,req,Inject,SQL,new
来源: https://blog.csdn.net/qq_53264525/article/details/122704356

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有