Java命令注入之防护

1 Java中的命令注入

在Java中的Runtime.getRuntime本质就是使用ProcessBuilder,以ProcessBuilder里用ProcessImpl,start 的一个子进程执行命令,

Java的native调用

a. Windows是CreateProcessW 创建子进程执行命令

b. Unix中以enecve 来创建子进程执行命令

Java并没有使用system函数进行创建子进程执行命令,通常我们也知道system的函数非常容易发生注入风险,比如system(“ls “+”test;rm *”); 后面部分是用户输入的,用户输入通过注入符号;和后续指令rm *,被系统执行。

 execve, CreateProcessW 函数通过执行命令和参数分别传递的方式,这种方式杜绝了system的拼接命令的方式,有一定的安全性,但也未必是安全的。

1.1      参数直接用于命令执行

如果传入的参数对原执行命令来说是用于执行的情况下,enecve, createprocessW无法防护

1.        Windows下的

cmd.exe /K 参数可以批量执行命令


 
 
  1. String btype = request.getParameter( "inputparam");
  2. String cmds[] = { "cmd.exe", "/K", "\"C: &&del C:\\r2.txt”+btype+” &&del C:\\r1.txt \""};
  3. System.Runtime.getRuntime().exec(cmds);

虽然此时传入的参数是用于cmd.exe的,但因为cmd.exe 使用了/K参数,将后续传入的参数用于命令执行,如果传入&&del *,最后变成

cmd.exe /K “del C:\\test1.txt && del *&&del C:\\test2.txt”

 

2.        Unix 下的

  • /bin/bash 参数,输入参数直接作为命令执行


 
 
  1. String btype = request.getParameter( "test");
  2. String cmds[] = { "/bin/bash ", "test.sh"+btype};
  3. System.Runtime.getRuntime().exec(cmds);
传入的参数作为bash直接执行的,此时如果作为参数传入;rm *,最后等效于

/bin/bash test.sh;rm *

  • /bin/bash –c 参数,后续输入参数为执行命令


 
 
  1. String btype = request.getParameter("inputparam");
  2. String cmds[] = {"/bin/bash ","-c","sh script.sh"+btype};
  3. System.Runtime.getRuntime().exec(cmds);

此时传入的参数是用于bash执行脚本文件的,但因为使用了-c参数,使后续传入的参数用于命令执行,如果传入;rm *,最后等效于

/bin/bash –c “sh script.sh; rm *”

上述的例子提示只要在实际应用过程中,传入的参数(例如上例的sh script.sh;)是用于运行程序内部(例如sh -c,cmd.exe/k)执行命令的,execve,CreateProcessW函数就无法防护,此时用法等效于system(“sh script.sh;rm *”)函数


1.2       参数编码

对用于常见的用于shell执行的符号进行转码,避免命令注入的风险

字符

功能描述

Unix

Windows

|

管道:连接上个指令的标准输出,作为下个指令的标准输入

\|

^|

;

连续指令服务

\;

^;

&

后台运行

\&

^&

$

变量替换

\$

^$

重定向输入

\>

^>

目标文件内容发送到命令中

\<

^<

`

返回当前执行结果

\`

^`

\

作为连接符号用,或者转义用

\\

^\

!

执行上一条shell命令

\!

^!

例如:Unix 中

可以通过编码方式,避免命令的注入

/bin/bash script.sh\;rm *

/bin/bash –c “sh script.sh\; rm *” 

  • 多字符需要转义每个字符

比如:  >> 需要转义成\>\>

  •   编码方式的注意点:

编码是指在调用函数之前需要对参数进行编码,不需要多次编码。

比如说在某个script.sh test.sh\;rm *里面继续还有命令调用,而这个命令是用参数传入

sh $1

上述的解决方案并不是对test.sh;rm * 做两次编码,对script.sh来说传入参数test.sh;rm *只需要做一次编码,而在script.sh里需要对输入的参数$1在进行一次编码,遵循谁调用谁编码的原则。

1.3       参数过滤

  • 白名单保护

如果命令的参数是有特征性的建议使用白名单对输入的参数进行保护

比如允许[a-z][A-Z][0-9] _- 等有限的字符

 

  •  黑名单保护

a.      |;&$><`\! 可以将这些字符直接作为黑名单过滤

b.      \t\n\r\f \u0000 这些字符需要作为黑名单过滤,特别是空字符截断 \u0000 (这个在JVM6里是没有保护)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
XML实体执行命令漏洞(XML External Entity,简称XXE),是指在XML文档的解析过程中,利用实体注入技术来执行恶意命令的一种攻击方式。对于该问题,以下是一个用300字中文回答: XML实体执行命令java xxe是一种漏洞攻击方式。当解析XML时,攻击者通过在XML文档中注入带有恶意代码的实体,可以导致服务器执行恶意命令或读取敏感数据。 在Java中,XXE漏洞可以通过DocumentBuilderFactory解析XML时使用的解析器特性(如“<!DOCTYPE”、“DOCTYPE”和“<ENTITY>”等)来注入实体。攻击者可以构造恶意的XML文档,通过实体注入技术注入包含恶意代码的外部资源引用。当XML文档被解析时,解析器会尝试从外部资源加载实体,如果攻击者在外部资源中包含了一些系统命令,那么这些命令就会被执行。 为防止XXE漏洞,应对输入进行合理过滤和安全处理。可采取以下几种防护措施:1.禁止或限制解析器使用外部实体和外部DTD文件。2.使用安全的解析器,如Woodstox、SAX、SAXON等,它们可以禁用外部实体和DTD。3.对输入进行严格的验证和过滤,确保只接受合法的XML数据。4.采用白名单机制,限制允许的XML元素、属性和实体。 总之,通过对输入进行严格验证和过滤,禁用或限制外部实体和DTD,选择安全的解析器等措施,可以有效防范XML实体执行命令java xxe漏洞带来的危害。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值