概念
命令注入漏洞(Command Injection Vulnerability)是一种安全漏洞,攻击者可以通过将恶意命令注入到应用程序中,执行未授权的系统命令。以下是该漏洞的产生原因及其危害:
### 产生原因
1. **不当输入验证**:
- 应用程序没有对用户输入进行充分的验证和清洗,允许恶意输入。
2. **动态构建命令**:
- 程序在构建系统命令时直接使用用户输入,而没有使用安全的方式(如参数化)。
3. **信任用户输入**:
- 开发者过于信任来自用户的输入,未意识到这些输入可能包含恶意内容。
4. **错误配置**:
- Web服务器或应用程序的错误配置可能使命令注入攻击更容易发生。
### 危害
1. **远程执行命令**:
- 攻击者可以执行任意系统命令,获取系统权限。
2. **数据泄露**:
- 通过命令注入,攻击者可能访问敏感数据,如用户信息和系统配置。
3. **系统破坏**:
- 攻击者可以删除文件、修改数据或破坏系统,导致服务中断。
4. **后门安装**:
- 攻击者可在系统中植入后门,长期控制系统。
5. **影响声誉**:
- 安全事件可能导致用户信任下降,损害企业声誉。
### 总结
命令注入漏洞具有严重的危害,因此,开发者应采取适当的安全措施,如对用户输入进行严格验证和使用安全的命令构建方法,以防止此类攻击的发生。
Low
代码分析:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
提取Sumbit键值(即输入的ip),做空值校验,
REQUEST传递ip,赋值给$target,
利用php_uname(),返回PHP的系统名称,利用stristr()函数查询前面返回的系统名称中是否存在'Windows NT'字样。
如果存在,则ping
如果不存在,则 ping -c 4,
最后打印最终执行的命令。
shell_exec(‘[$cmd],[$value]’):直接执行命令$cmd。 可见对$value可能存在的非法字符的注入。
于是我们构造命令A:127.0.0.1&ipconfig
//执行ping 127.0.0.1 和 ipconfig
构造命令B:127.0.0.1&&ipconfig(执行结果通上方一致)
//只有前半段执行成功了才会执行ipconfig
构造命令C: 127.0.0.1 | ipconfig xxxx|ipconfig
//前半段后台执行,并且前半段执行失败不影响执行ipconfig
构造命令D:xxxx || ipconfig
//当且仅当前半段执行失败,才会执行后半段
构造命令E:127.0.0.1 || ipconfig
Medium
代码分析:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = $_REQUEST[ 'ip' ];
// Set blacklist
$substitutions = array(
'&&' => '',
';' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
提取Sumbit键值(即输入的ip),做空值校验,
REQUEST传递ip,赋值给$target,
非法字符数组,
利用php_uname(),返回PHP的系统名称,利用stristr()函数查询前面返回的系统名称中是否存在'Windows NT'字样。
如果存在,则ping
如果不存在,则 ping -c 4,
最后打印最终执行的命令。
这次代码对$target变量做了变量清洗。
str_replace() 函数,替换字符串中的一些字符并作大小写区分。
str_replace([查找的值],[替换前者的值],[目标字符串]),即如果出现&&和;做替换为空处理。
既然只对&&和;做处理,那我们就好办了,
开始构造命令F:127.0.0.1&whoami
构造命令G:127.0.0.1 | whoami
//前半段后台执行,仅回显whoami的执行结果
构造命令F: xxxx | ipconfig
多次尝试后,只有以上三种构造方式可以。
High
代码分析:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Get input
$target = trim($_REQUEST[ 'ip' ]);
// Set blacklist
$substitutions = array(
'&' => '',
';' => '',
'| ' => '',
'-' => '',
'$' => '',
'(' => '',
')' => '',
'`' => '',
'||' => '',
);
// Remove any of the charactars in the array (blacklist).
$target = str_replace( array_keys( $substitutions ), $substitutions, $target );
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
?>
说白了就是做了多种过滤,发现管道符后面莫名奇妙的过滤了空格,我们可以去掉空格试试:
Impossible
代码分析:
<?php
if( isset( $_POST[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$target = $_REQUEST[ 'ip' ];
$target = stripslashes( $target );
// Split the IP into 4 octects
$octet = explode( ".", $target );
// Check IF each octet is an integer
if( ( is_numeric( $octet[0] ) ) && ( is_numeric( $octet[1] ) ) && ( is_numeric( $octet[2] ) ) && ( is_numeric( $octet[3] ) ) && ( sizeof( $octet ) == 4 ) ) {
// If all 4 octets are int's put the IP back together.
$target = $octet[0] . '.' . $octet[1] . '.' . $octet[2] . '.' . $octet[3];
// Determine OS and execute the ping command.
if( stristr( php_uname( 's' ), 'Windows NT' ) ) {
// Windows
$cmd = shell_exec( 'ping ' . $target );
}
else {
// *nix
$cmd = shell_exec( 'ping -c 4 ' . $target );
}
// Feedback for the end user
echo "<pre>{$cmd}</pre>";
}
else {
// Ops. Let the user name theres a mistake
echo '<pre>ERROR: You have entered an invalid IP.</pre>';
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
做了token校验,并做了Sumbit输入格式的限制,不存在命令注入漏洞。
命令注入漏洞加固方法:
防止命令注入漏洞可以采取以下几种有效措施:
1. **输入验证**:
- 对所有用户输入进行严格验证,确保只接受合法字符和格式,使用白名单策略。
2. **使用参数化命令**:
- 在执行系统命令时,尽量使用参数化的API或库,如`exec`函数中的参数数组,而不是直接拼接字符串。
3. **避免使用系统命令**:
- 尽量避免在应用中调用系统命令,使用语言自带的功能或库来实现相同的功能。
4. **最小化权限**:
- 确保运行应用的用户权限最小化,仅允许其执行必要的操作,降低潜在风险。
5. **错误处理**:
- 实施适当的错误处理,避免泄露系统信息,防止攻击者通过错误消息获取有用的信息。
6. **定期审计和测试**:
- 进行安全审计和渗透测试,定期检查代码中是否存在潜在的命令注入漏洞。
通过这些措施,可以有效降低命令注入漏洞的风险,提升应用程序的安全性。