命令执行漏洞

命令执行漏洞是指用户能够控制函数输入,存在可以执行代码的危险函数

一般都是因为程序员调用了几个可以执行系统命令的函数,具体利用方法和sql注入有点像

危险函数

  • system() 成功则返回命令输出的最后一行,失败则返回false
  • exec() 命令执行结果的最后一行内容
  • shell_exec() 命令执行的输出,如果执行过程中发生错误或者过程不产生输出,则返回NULL
  • passthru() 执行外部程序并且显示原始输出
  • eval() 将输入的字符串参数当作PHP代码来执行
  • assert() 将输入字符串参数当作php代码来执行

eval():该函数对于在数据库文本字段中供日后计算而进行的代码存储很有用。(在生产中也建议少用)
注意:1.eval()里必须是字符串;

       2.eval()里的引号必须是双引号,因为单引号不能解析字符串里的变量$str;

eval定义和用法:
(1)eval() 函数把字符串按照 PHP 代码来计算(计算=执行)。
(2)该字符串必须是合法的 PHP 代码,且必须以分号结尾。
(3)如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false

assert的用法却更详细一点。
assert_option()可以用来对assert()进行一些约束和控制;
默认值
ASSERT_ACTIVE=1 //Assert函数的开关
ASSERT_WARNING =1 //当表达式为false时,是否要输出警告性的错误提示,issue a PHP warning for each failed assertion
ASSERT_BAIL= 0 //是否要中止运行;terminate execution on failed assertions
ASSERT_QUIET_EVAL= 0 //是否关闭错误提示,在执行表达式时;disable error_reporting during assertion expression evaluation
ASSERT_CALLBACK= (NULL) // 是否启动回调函数 user function to call on failed assertions

php的官方文档里头是建议将assert用来进行debug,我们可以发现还有一个开关ASSERT_ACTIVE可以用来控制是否开启debug。
现在问题就产生了,如果程序员在开发的时候在代码中留下了很多assert(),然后在程序发布的时候关闭执行,设置assert_options(ASSERT_ACTIVE,0);这样做是否可行?有没有安全问题?

既然assert主要作用是debug,就不要在程序发布的时候还留着它。在程序中用assert来对表达进行判断是不明智的,原因上文说了, 一个是在生产环境中assert可能被disabled,所以assert不能被完全信任;二是assert()可以被继续执行;而如果在生产环境让 ASSERT_ACTIVE=1,那这个表达式字符串可以被执行本身就存在安全隐患。assert引起的代码注射
例如

注意:assert把整个字符串参数当php代码执行,eval把合法的php代码执行。
assert做一句话木马在php7后已经失败了

命令执行的一些骚操作

命令执行的是系统命令,所以我们这里分成windows下和linux下

windows下

一些不影响运行的符号

“和^还有成对的圆括号()符号并不会影响命令的执行,而且windows还1不区分大小写,例如以下的命令都可以正常执行

whoami

w”h”o”a”m”i

wH^o”ami

(w^Hoami)

可以随便加”但是不能同时连续加两个^符号,因为^是cmd中的转义符,跟在他后面的符号是会被转义的

set命令和windows变量

set可以用来设置一个变量

set a=1

echo a //输出a

echo %a% //输出1

用两个%括起来的变量,会引用其变量内的值(类似php的$)

同时还可以拼接

set a=who

set b=ami

%a%%b% //执行whoami

cmd /c “echo 1” 会输出1

cmd /c 会执行字符串内的命令

切割字符串

cmd命令也有一个切割字符串的用法,可以继续用刚刚的whoami举例

set a=whoami

%a:~0% //输出a的值中所有字符

%a:~0,1% //输出a从第0个位置开始,1个数值

%a:~-1% //输出最后一个字符串

%a:~-3,-2% //从倒数第3个数开始 输出到倒4个字符串

因此可以用本地的变量来构造一个shell

逻辑运算符的作用

|在cmd中,可以连接命令,且只会执行后面那条命令

whoami|ping www.xxx.com 这里只会执行ping

||情况下,只有前面的命令失败,才会执行后面的语句

whoa|ping www.xxx.com //执行ping

whoami|ping www.xxx.com //只执行whoami

&情况下,无论前面的命令成功或者失败,后面的命令都会执行

whoami&ping www.xxx.com //都执行

whoam&ping www.xxx.com //只执行ping

&&情况下,要求两条命令都为真才能执行

whoami&&ping www.xxx.com //都执行

whoa&&ping www.xxx.com //都不执行

For循环拼接命令

for循环经常被用来混淆处理cmd命令,使得cmd命令看起来复杂,最常用的for循环参数又/L,/F参数

FOR 参数 %变量名% IN (相关文件或命令) DO 执行的命令

linux

linux下的变量和逻辑运算符

linux下面终于不用两个%了,直接赋值就可以了

a=who

b=ami

$a$b

linux下用分号表示命令结束后执行后面的命令,无论前面的命令是否成功

ping www.xxx.com;whoami //都执行

|、||、&、&&都和windows一样

一些通配符

/us?/sb*/if?onfig

wh\oami

wh$1oami

反括号可以把括起来的字符当作命令执行

who`111`ami //执行whoami

利用环境变量去构造想要的命令

echo $PATH //查看环境变量 看看有没有我们要的字符

输出/root/anaconda3/bin

echo $