php审计初探:dvwa之命令注入

在这里插入图片描述

Low

代码:

<?phpif( 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>";
}?> 

涉及函数:

isset()

stristr()

php_uname()

shell_exec()

代码分析:

  1. 是否点击submit提交按钮。
  2. 服务器通过GPC方式获取了一个IP地址,赋值给变量$target。
  3. 使用php_name(‘s’)获取到主机名,并通过stristr函数判断是windows系统还是*nix系统
  4. 根据不同的主机名拼接不同的ping命令(linux系统需要限制ping的次数,否则会一直ping)。
  5. 由shell_exec() 运行拼接后的命令。
  6. 当web用户点击submit时,服务器执行了1条命令。
  7. 一个字符串是否可以执行多条命令呢?

GPC(Get/Post/Cookie)通常指的是一种获取网页表单数据的方法,是 PHP 中一种非常常用的编程技巧。GPC 方法包括 GET、POST 和 COOKIE,它们各自有不同的用途和特点。

  1. GET:GET 方法通过 URL 将数据传送到服务器,在URL地址栏中可以看到这些参数及其值。由于GET 方法只能传输少量数据(大约 2KB 左右),且数据不安全,所以不适合传递敏感信息。
  2. POST:POST 方法将数据封装在 HTTP 请求体中,因此不会出现在 URL 地址栏中,而且传输的数据量较大(理论上不受限制),适合传输大量数据和敏感信息。
  3. COOKIE:COOKIE 是存储在客户端的一小段数据,可以在多个页面间共享数据。它可以保存用户的个人信息和偏好设置,还可以用于实现身份验证等功能。 在实际编程中,可以综合运用这三种方法,根据需求和安全性要求灵活使用。

漏洞利用:

127.0.0.1&whoami127.0.0.1&&whoami127.0.0.1|whoami127.0.0.1.1||whoami

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>";
    }
?> 

涉及函数:

isset()

str_replace()

array_keys()

stristr()

php_uname()

shell_exec()

代码分析:

  1. 是否点击submit提交按钮。
  2. 服务器通过GPC方式获取了一个IP地址,赋值给变量$target。
  3. 定义了一个数组$substitutions,存储了黑名单&&;
  4. 使用函数array_keys获取数组 s u b s t i t u t i o n s 的键值,然后使用函数 s t r r e p l a c e 将其替换成空,并最后重新赋值给 substitutions的键值,然后使用函数str_replace将其替换成空,并最后重新赋值给 substitutions的键值,然后使用函数strreplace将其替换成空,并最后重新赋值给target。
  5. 使用php_name(‘s’)获取到主机名,并通过stristr函数判断是windows系统还是*nix系统
  6. 根据不同的主机名拼接不同的ping命令(linux系统需要限制ping的次数,否则会一直ping)。
  7. 由shell_exec() 运行拼接后的命令。
  8. 当web用户点击submit时,无法使用&&;拼接的多条命令语句
  9. 寻找其他可以执行多条命令的语句

漏洞利用:

127.0.0.1&whoami127.0.0.1|whoami127.0.0.1.1||whoami

High

代码:

<?phpif( 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>";
}?>

涉及函数:

isset()

trim()

str_replace()

array_keys()

stristr()

shell_exec()

php_uname()

代码分析:

  1. 设置了黑名单,&;|+空格 -()$||反引号
  2. 漏掉了关键字符 |

漏洞利用:

127.0.0.1|whoami

Impossible

代码:


<?phpif( 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();?>

涉及函数:

isset()

stristr()

php_uname()

array_keys()

str_replace()

trim()

checkToken()

stripslashes()

explode()

is_numeric()

代码分析:

  1. 是否点击submit提交按钮。
  2. 服务器通过GPC方式获取了一个Token值校验token是否有效。
  3. 服务器通过GPC方式获取了一个ip并存储到变量$target中。
  4. 使用函数stripslashes过滤了下字符串中的反斜杠。
  5. 使用函数explode以字符’.'切割了字符串并组成一个数组赋值给变量 $octet
  6. 判断如果 o c t e t [ 0 ] 、 octet[0]、 octet[0]octet[1]、 o c t e t [ 2 ] 、 octet[2]、 octet[2]octet[3]都为数字并且, o c t e t 数组长度等于 4 时,拼接字符串赋值为 octet数组长度等于4时,拼接字符串赋值为 octet数组长度等于4时,拼接字符串赋值为target,否则输出“ERROR:
    You have entered an invalid IP.”。
  7. 使用php_name(‘s’)获取到主机名,并通过stristr函数判断是windows系统还是*nix系统
  8. 根据不同的主机名拼接不同的ping命令(linux系统需要限制ping的次数,否则会一直ping)。
  9. 由shell_exec() 运行拼接后的命令。
  10. 当web用户点击submit时,无法使用&&;拼接的多条命令语句
  11. 寻找其他可以执行多条命令的语句

漏洞利用:

相关函数的作用及示例:

isset()

isset函数用于检测变量是否已经设置且不为空

<?php
$myVar = "Hello World";
if(isset($myVar)){
	echo "$myVar is set.";
}else{
	echo "$myVar is not set.";
}
//输出:Hello World is set.
?>

stristr()

注意:stristr函数是strstr函数的忽略大小写版本

<?php
    $text = "Hello World";
    $find = "World";
    $result = stristr($text,$find);
    echo $result;//输出:"World"
?>

php_uname()

php_uname()函数用于获取操作系统的信息,包括操作系统的名称、版本号、发布日期等。

例如:以下代码会输出服务器的主机名:

<?php
echo php_uname('n');//输入:WIN-37QPUN7NO81 
?>

而以下代码则会输出更全面的系统信息:

<?php
print_r(php_uname());//输入:Windows NT WIN-37QPUN7NO81 6.2 build 9200 (Windows Server 2012 Standard Edition) i586 
?>

php_uname 相关的其他参数

‘a’: 包含 ‘s’, ‘n’, ‘r’, ‘v’, ‘m’ 所有的模式.

‘s’: 操作系统名称。

‘n’: 主机名。

‘r’: 内核版本。

‘v’: 系统版本。

‘m’: 硬件平台。

‘p’: 进程器类型。

‘i’: 设备节点名。

‘c’: CPU 架构。

‘x’: 不同于 ‘i’ 的设备节点名。

‘O’: 发行版名称和版本号。

‘L’: Linux 标识符。

‘S’: 安全标识符。

‘M’: MAC 地址。

‘B’: BIOS 版本。

‘H’: Hardware 平台。

‘U’: 内部 Unicos 计划 ID ‘t’: 时间支持。

‘C’: 软件计数器。

‘D’: 定义域。

‘Z’: 额外的 z/OS 信息。

‘W’: Windows 注册表的 PHP 部分。

‘V’: php cgi-fcgi 版本信息

str_replace()

str_replace() 函数用于在字符串中替换指定的字符或字符串。

例如,假设有以下的 PHP 代码:

<?php
$str = "Hello World!";
$new_str = str_replace("World", "Universe", $str);
echo $new_str;
?>

上述代码将输出:

Hello Universe!

在这个例子中,str_replace() 函数将字符串 $str中的"World"替换为"Universe",并将替换后的结果存储在new_str 中。这对于在字符串中进行简单的替换操作非常有用。

array_keys

array_keys() 函数用于返回数组中所有的键名

例如,假设有以下的 PHP 代码:

<?php
$age = array("Peter"=>"35", "Ben"=>"37", "Joe"=>"43");
print_r(array_keys($age));
?>

上述代码将输出:

Array
(
    [0] => Peter
    [1] => Ben
    [2] => Joe
)

shell_exec()

用于执行外部命令并返回输出。

<?php
$output = shell_exec('whoami');
echo "<pre>$output</pre>";//输出结果:win-37qpun7no81\administrator
?>

trim()

trim函数的作用是去除字符串两端的空格或其他指定字符。

例如:

$str = "  hello world  ";
echo trim($str); // 输出 "hello world"$str2 = "###hello world###";
echo trim($str2, "#"); // 输出 "hello world"

在第一个例子中,trim函数去除了字符串两端的空格,使得输出的字符串只包含"hello world"。

在第二个例子中,trim函数去除了字符串两端的"#“字符,使得输出的字符串只包含"hello world”。

checkToken()

用于检测用户的访问令牌是否有效。

<?php
// 定义checkToken()函数
function checkToken($token) {
    // 假设$validToken是一个有效的访问令牌
    $validToken = "abc123";
 
    // 验证传入的令牌是否与有效令牌匹配
    if ($token === $validToken) {
        return true; // 令牌有效
    } else {
        return false; // 令牌无效
    }
}
 
// 获取用户提交的访问令牌
$userToken = $_POST['token'];
 
// 调用checkToken()函数验证用户的访问令牌
if (checkToken($userToken)) {
    echo "he access token is valid and allows the user to access the page";
} else {
    echo "The access token is invalid and access is denied";
}
?>

token校验不通过:

在这里插入图片描述

token校验通过:

在这里插入图片描述

stripslashes()

stripslashes() 函数用于删除由 addslashes() 函数添加的反斜杠。

在某些情况下,需要对字符串进行转义,比如在将数据插入数据库之前。但是在从数据库中取出数据后,可能需要去除这些转义字符,这时就可以使用 stripslashes() 函数。

<?php
$str = "This is some text with a \"quoted\" word";
echo $str;
echo "<br>";// 添加转义字符
$str = addslashes($str);
echo $str;
echo "<br>";// 删除转义字符
$str = stripslashes($str);
echo $str;
?>

在这里插入图片描述

explode()

我们想要将这个字符串按照逗号分隔成一个数组,可以使用explode()函数来实现

<?php
$str = "apple,banana,orange";
$arr = explode(",", $str);
print_r($arr);
//输出结果:Array ( [0] => apple [1] => banana [2] => orange ) 
?>

is_numeric()

is_numeric()函数用于检查变量是否是一个数字或数字字符串。

以下是一个示例:

<?php
$num1 = 123;
$num2 = "456";
$str1 = "456abc";
$str2 = "abc";var_dump(is_numeric($num1)); // 输出: bool(true)
var_dump(is_numeric($num2)); // 输出: bool(true)
var_dump(is_numeric($str1)); // 输出: bool(false)
var_dump(is_numeric($str2)); // 输出: bool(false)
?>

我们想要将这个字符串按照逗号分隔成一个数组,可以使用explode()函数来实现

<?php
$str = "apple,banana,orange";
$arr = explode(",", $str);
print_r($arr);
//输出结果:Array ( [0] => apple [1] => banana [2] => orange ) 
?>

is_numeric()

is_numeric()函数用于检查变量是否是一个数字或数字字符串。

以下是一个示例:

<?php
$num1 = 123;
$num2 = "456";
$str1 = "456abc";
$str2 = "abc";var_dump(is_numeric($num1)); // 输出: bool(true)
var_dump(is_numeric($num2)); // 输出: bool(true)
var_dump(is_numeric($str1)); // 输出: bool(false)
var_dump(is_numeric($str2)); // 输出: bool(false)
?>

点赞(18) 打赏

评论列表 共有 0 条评论

暂无评论

微信小程序

微信扫一扫体验

立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部