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 参数可以批量执行命令

String btype = request.getParameter("inputparam");
String cmds[] = {"cmd.exe","/K","\"C: &&del C:\\r2.txt”+btype+” &&del C:\\r1.txt \""};
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 参数,输入参数直接作为命令执行

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

/bin/bash test.sh;rm *

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

String btype = request.getParameter("inputparam");
String cmds[] = {"/bin/bash ","-c","sh script.sh"+btype};
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里是没有保护)


  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Java网站中,预防SQL注入攻击是非常重要的安全措施。下面是一些常见的检查和防护方法: 1. 使用参数化查询:使用预编译的SQL语句和参数绑定来执行数据库操作,而不是直接将用户输入的数据拼接到SQL语句中。这可以防止恶意用户在输入中插入恶意的SQL代码。 2. 输入验证和过滤:对用户输入的数据进行验证和过滤,确保只接受有效的输入。可以使用正则表达式、白名单过滤或黑名单过滤等方式。 3. 使用ORM框架:使用对象关系映射(ORM)框架,如Hibernate或MyBatis,可以将数据库操作抽象化,减少手动编写SQL语句的机会,从而降低SQL注入的风险。 4. 最小权限原则:为数据库用户授予最小权限,限制其对数据库的访问范围。不要使用具有高权限的特权账户执行普通操作。 5. 安全编码实践:编写安全的代码是防止SQL注入攻击的基础。避免使用动态拼接SQL语句,避免使用不可信任的输入直接执行数据库操作。 6. 日志记录和监控:实施日志记录和监控机制,及时发现异常的数据库操作行为,并采取相应的应对措施。 7. 定期更新和维护:及时更新数据库和应用程序的补丁,确保系统中使用的软件版本是最新的,以减少已知的漏洞和安全风险。 请注意,以上只是一些常见的方法,SQL注入攻击的防范需要综合考虑系统架构、安全需求和开发团队的实际情况。建议在开发过程中结合安全专家的建议来确保系统的安全性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值