审计 DVWA 命令执行漏洞的代码【练习】

Command Injection

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

?>

image-20231121172739944

trim()

trim() 用于去除字符串两端的空白字符(包括空格、制表符、换行符等)。

trim($str, $charlist = " \t\n\r\0\x08")

参数 $str 是要进行处理的字符串。

参数 $charlist 是一个可选的字符串参数,用于指定要删除的字符列表。默认包含空格、制表符、换行符、回车符、空字符和垂直制表符。

trim() 函数会从字符串的开头和姐夫删除指定的字符列表中出现的字符,并返回处理后的字符串。

示例:

$str = "   Hello, World!   ";
$trimStr = trim($str);
echo $trimStr;	// 输出:hello,world
str_replace()

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

str_replace($search, $replace, $subject, $count = null)

参数 $search 是要查找的字符或子字符串。它可以是一个字符串或一个字符串数组。

参数 $replace 是要替换为的字符或子字符串。它可以是一个字符串或一个字符串数组,与 $search 参数对应。

参数 $subject 是要进行替换操作的原始字符串。

参数 $count 是一个可选的引用参数,用于存储替换操作的次数。

str_replace() 函数会在 $subject 字符串中查找 $search 参数指定的字符或子字符串,并将其替换为 $replace 参数指定的字符或子字符串。如果 $search$replace 都是数组,那么将会对应替换数组中的元素。

str_replace() 函数返回替换后的字符串,如果没有进行任何替换,则返回原始的 $subject 字符串。

需要注意的是,str_replace() 函数是区分大小写的。如果需要进行大小写不敏感的替换操作,可以使用 str_ireplace() 函数。

示例:

$str = "Hello, World!";
$newStr = str_replace("World", "PHP", $str);
echo $newStr;  // 输出:Hello, PHP!
array_keys()

array_keys() 是一个 PHP 函数,用于获取数组中所有的键(即数组的索引)。它的语法如下:

array_keys(array $array, mixed $search_value = null, bool $strict = false): array|false

参数 $array 是要获取键的数组。

参数 $search_value 是一个可选的参数,用于指定要搜索的值。如果提供了该参数,则 array_keys() 函数将返回数组中所有与该值匹配的键。

参数 $strict 是一个可选的布尔值参数,用于指定是否进行严格的比较。默认情况下,它为 false,表示使用宽松的比较。如果设置为 true,则进行严格的比较,即要求键的类型和值都匹配。

array_keys() 函数返回一个包含数组中所有键的新数组。如果没有找到匹配的键,则返回空数组。如果出现错误,则返回 false

以下是一个示例,演示如何使用 array_keys() 函数:

$fruits = array("apple", "banana", "orange", "apple");
$keys = array_keys($fruits);
print_r($keys);

在上面的示例中,有一个包含多个水果的数组 $fruits。使用 array_keys() 函数,获取了数组中所有的键,并将结果赋值给 $keys 变量。最后,使用 print_r() 函数输出键的数组。

输出结果如下:

Array
(
    [0] => 0
    [1] => 1
    [2] => 2
    [3] => 3
)

在上述示例中,由于数组中有重复的值 “apple”,因此在结果中会有多个相应的键。

需要注意的是,array_keys() 函数对于关联数组(即具有字符串键的数组)也适用,它会返回所有的键,而不仅仅是数字索引。

stristr()

stristr() 用于在字符串中查找指定的子字符串,并返回该子字符串及其后面的所有字符。它的语法如下:

stristr($haystack, $needle, $before_needle = false)

参数 $haystack 是要进行搜索的原始字符串。

参数 $needle 是要查找的子字符串。

参数 $before_needle 是一个可选的布尔值参数,用于指定是否返回 $needle 之前的部分字符串。默认情况下,它为 false,表示返回 $needle 及其后面的部分字符串。如果设置为 true,则返回 $needle 之前的部分字符串。

stristr() 函数会在 $haystack 字符串中查找 $needle 参数指定的子字符串,并返回该子字符串及其后面的所有字符。如果找到匹配的子字符串,则返回结果字符串。如果没有找到匹配的子字符串,则返回 false

示例:

$email = "john.doe@example.com";
$domain = stristr($email, "@");
echo $domain;  // 输出:@example.com

在上面的示例中,stristr() 函数将字符串 $email 中的 “@” 符号作为子字符串进行查找,并返回该子字符串及其后面的所有字符。最后,使用 echo 输出结果字符串。

需要注意的是,stristr() 函数是不区分大小写的。如果需要进行大小写敏感的查找操作,可以使用 strstr() 函数。

php_uname()

php_uname() 用于获取当前服务器的操作系统信息。它返回一个包含有关操作系统的字符串。

php_uname() 函数没有任何参数,调用它将返回一个包含操作系统信息的字符串。这个字符串通常包括操作系统的名称、主机名、内核版本和发布日期等信息。

示例:

$osInfo = php_uname();
echo $osInfo;

输出可能类似于:

Linux myserver 4.15.0-54-generic #58-Ubuntu SMP Mon Jun 24 10:55:24 UTC 2019 x86_64

请注意,php_uname() 函数的返回值取决于服务器上 PHP 运行的操作系统。因此,不同的服务器可能会返回不同的结果。

  • 's':获取操作系统名称(例如:Linux、Windows、Darwin 等)。
  • 'n':获取主机名(即服务器的名称)。
  • 'r':获取内核版本号。
  • 'v':获取操作系统版本号。
  • 'm':获取机器类型(例如:x86_64、i686 等)。

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

?>
checkToken()

checkToken() 函数是用于验证防跨站请求伪造(Anti-CSRF)令牌的自定义函数。

示例:

function checkToken($userToken, $sessionToken, $redirectUrl) {
    // 检查用户提交的令牌是否与会话中的令牌匹配
    if ($userToken !== $sessionToken) {
        // 令牌不匹配,可能是 CSRF 攻击
        // 可以根据需要执行其他操作,例如记录日志、重定向到错误页面等
        echo "CSRF 检测失败!";
        // 重定向到指定的 URL
        header("Location: $redirectUrl");
        exit;
    }
}

checkToken() 函数接受三个参数:

  1. $userToken:用户提交的令牌,通常是从表单中获取的。
  2. $sessionToken:存储在服务器会话中的令牌,通常是在生成表单时生成并存储在会话中的。
  3. $redirectUrl:如果令牌验证失败,将重定向用户到的 URL。

函数的工作原理如下:

  1. 首先,函数比较用户提交的令牌 $userToken 和会话中的令牌 $sessionToken 是否匹配。
  2. 如果令牌匹配,表示请求是合法的,函数不执行任何操作,继续执行后续代码。
  3. 如果令牌不匹配,表示可能发生了跨站请求伪造攻击(CSRF)。函数会输出一条错误消息,并使用 header() 函数将用户重定向到指定的 URL $redirectUrl。重定向后,用户可以被导航到一个错误页面或其他适当的处理页面。
explode()

explode() 用于将字符串按指定的分隔符拆分成数组。

示例:

array explode(string $delimiter, string $string, int $limit = PHP_INT_MAX)

参数说明:

  • $delimiter:指定的分隔符,用于将字符串拆分成数组元素。
  • $string:要拆分的字符串。
  • $limit(可选):指定返回的数组元素的最大数量。默认为 PHP_INT_MAX,即没有限制。

返回值:

  • 返回一个数组,其中包含拆分后的字符串片段作为数组元素。

示例用法:

$string = "Hello,World,How,Are,You";
$delimiter = ",";
$pieces = explode($delimiter, $string);

print_r($pieces);

输出:

Array
(
    [0] => Hello
    [1] => World
    [2] => How
    [3] => Are
    [4] => You
)

在上面的示例中,我们将字符串 $string 使用逗号 , 作为分隔符进行拆分,得到一个包含拆分后的片段的数组 $pieces。每个逗号分隔的部分成为数组的一个元素。

is_numeric()

is_numeric() 是一个 PHP 函数,用于检查给定的值是否为数字或数字字符串。它的作用是判断一个值是否可以被解释为数字。

is_numeric() 函数的使用方法如下:

$value = "123";
if (is_numeric($value)) {
    echo "The value is numeric.";
} else {
    echo "The value is not numeric.";
}

在上面的示例中,我们将变量 $value 设置为字符串 "123",然后使用 is_numeric() 函数检查该值是否为数字。如果 $value 是数字或可以解释为数字的字符串,那么条件 is_numeric($value) 将返回 true,并输出 “The value is numeric.”;否则,条件将返回 false,并输出 “The value is not numeric.”。

需要注意的是,is_numeric() 函数在判断一个值是否为数字时非常宽松。它可以接受整数、浮点数以及以数字开头的字符串(例如 "123""3.14""0xFF" 等),但它也会将一些非数字的值(例如空字符串、布尔值、数组等)视为数字。因此,在使用 is_numeric() 函数时,应该注意对输入值进行适当的验证和过滤,以确保得到预期的结果。

sizeof()

sizeof() 用于获取数组或对象的元素数量(即长度)。它可以用于计算数组中的元素个数或对象中的属性数量。

sizeof() 函数的语法如下:

sizeof(array|object $var, int $mode = COUNT_NORMAL): int

参数 $var 是要计算长度的数组或对象。可选参数 $mode 用于指定计数模式,默认为 COUNT_NORMAL

以下是示例代码,演示如何使用 sizeof() 函数:

$array = [1, 2, 3, 4, 5];
$size = sizeof($array);
echo "Array size: $size"; // 输出:Array size: 5

$object = new stdClass();
$object->name = "John";
$object->age = 25;
$size = sizeof($object);
echo "Object size: $size"; // 输出:Object size: 2

在上面的示例中,我们首先创建了一个数组 $array,并使用 sizeof() 函数计算了数组的长度。然后,我们创建了一个对象 $object,并使用 sizeof() 函数计算了对象的属性数量。最后,我们将计算结果输出到屏幕上。

3, 4, 5];
s i z e = s i z e o f ( size = sizeof( size=sizeof(array);
echo “Array size: $size”; // 输出:Array size: 5

$object = new stdClass();
$object->name = “John”;
$object->age = 25;
s i z e = s i z e o f ( size = sizeof( size=sizeof(object);
echo “Object size: $size”; // 输出:Object size: 2

在上面的示例中,我们首先创建了一个数组 `$array`,并使用 `sizeof()` 函数计算了数组的长度。然后,我们创建了一个对象 `$object`,并使用 `sizeof()` 函数计算了对象的属性数量。最后,我们将计算结果输出到屏幕上。

需要注意的是,`sizeof()` 函数在计算数组长度时,也可以使用 `count()` 函数来实现相同的功能。它们的用法是相似的,可以根据个人喜好选择使用哪个函数。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值