DVWA-对Command Injection(命令注入)的简单演示与分析
- 前言
上一篇文章中,对命令注入进行了简单的分析,有兴趣的可以去看一看,文章地址 https://www.cnblogs.com/lxfweb/p/12828754.html,今天这篇文章以DVWA的Command Injection(命令注入)模块为例进行演示与分析,本地搭建DVWA程序可以看这篇文章 https://www.cnblogs.com/lxfweb/p/12678463.html,通过对DVWA不同等级的代码分析,看看它是如何做的防御。
漏洞利用与分析
low级别(低级别)
首先查看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>";
}
?>
可以发现上面的代码,用了stristr(),php_uname(),函数,这是用来判断当前的系统是否是Windows,因为Windows和Linux下的ping命令执行参数是不同的。接下来是用shell_exec函数来执行ping命令,并将结果输出。我们发现low级别的代码,对用户的输入没有做任何的过滤。存在很大的安全隐患。例如使用管道符“|”查看当前端口,输入下列内容
127.0.0.1|netstat -ano
结果如下图
这里不止可以使用“|”,在DOS下允许同时执行多条命令的符号主要有以下几个
- & 连接符 执行完第一个命令,执行第二个命令
- && 只有上一个执行成功,才执行下一个命令
- | 管道符 让前一命令的输出当做后一命令的输入,就是说前面命令的结果当做一个参数传递给后面命令处理
- || 只有上一个执行失败,才执行下一个命令
可以用连接符直接接net user zhangsan 123/add 创建用户 接着连接提权命令 net localgroup administrators zhangsan /add 拿下整个服务器
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>";
}
?>
我们发现,中级的代码,对参数做了一点过滤,把&&和;删除,相当于黑名单的形式,在Linux中;也可以起连接作用,依次执行多个命令。我们可以尝试| || & &;& ,这里以||举例,||前面报错,后面执行咱们构造的命令,结果如下图
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(无漏洞)
查看核心代码
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();
?>
通过查看Impossible级别的代码加入了Anti-CSRF token,并且采用白名单的方式,对参数ip进行了严格的限制,只接受X.X.X.X(X只能为数字),因此不存在命令执行漏洞。
- ES6 Features系列:Template Strings & Tagged Template Strings
- 基于Tcp协议的简单Socket通信实例(JAVA)
- spring集成kafka
- Java常用类(二)String类详解
- 用树莓派玩转蓝牙
- CSS魔法堂:你真的理解z-index吗?
- HashSet
- 树莓派的GPIO编程
- Java集合源码分析(三)Vevtor和Stack
- JS魔法堂:再识instanceof
- Web开发之CSS
- Linux重启命令与如何重启网络?
- spring boot + embed tomcat + standalone jar的内存泄露问题
- 树莓派:设置与软件安装
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 程序员该造轮子吗,造轮子能升职加薪吗?
- 1.基本标签
- 细品mysql之Join 语句的执行过程
- A Java Fork/Join Framework(Doug Lea 关于java Fork/Join框架的论文翻译)
- Mysql 的安装
- Spring系列之数据源的配置 数据库 数据源 连接池的区别
- STM32F4 SPI DMA
- 快速学习-XXL-JOB总体设计
- Android中Input事件初始化、接收以及分发
- 快速学习-XXL-JOB操作指南
- 快速学习-XXL-JOB任务详解
- PyQt5 技术篇-scrollArea不显示滚动条解决方法。Qt Designer不显示滚动条。滚动条的显示和隐藏。
- Python 爬虫篇-利用BeautifulSoup库爬取墨迹天气网的天气信息实例演示,调用墨迹天气api接口获取空气质量
- Redis的各种数据类型实践-ZSet
- Python 技术篇-将python项目打包成exe独立运行程序,pyinstaller库打包python代码