温馨提示
- 这关涉及的知识点较多, 写的很长, 中间留了很多错误引导(本人在实验时遇到的问题, 或许你们也会遇到), 在后文才逐步解释
源码分析
- 跟前几关一样, 更改了 WAF 的过滤字段
- 这个关卡, 只有
0
,1
,'
(单引号),$
,<
,\
,(
,)
可以用
解题分析(实验这些命令, 可以先在自己本地的Bash
试试)
- 上一关使用 八进制, 而这一关只有
0
和1
, 难道使用二进制?- 没错
- 在
bash
终端中, 支持使用$((2#binary))
来通过二进制表示十进制数- 比如
$((2#10011010)) -> 154
- 比如
- 虽说知道了
$((2#binary))
可以把二进制转为十进制, 但是还是把它拆分开来分析一下- 首先是
$((...))
- 在
bash
中$((...))
是 算术扩展(Arithmetic Expansion) 的语法 - 比如
echo $((3 + 5)) # 输出 8 echo $((10 / 2)) # 输出 5a=10 b=5 echo $((a + b)) # 输出 15
- 在
- 而
2#binary
是 进制表示法(Base Notation), 表示把后面的二进制串, 转化为十进制- 同理
#
前面的2
也可以是8
,16
,36
, 如下
echo $((8#72)) # 输出 58 echo $((16#1A)) # 输出 26 echo $((36#Z)) # 输出 35
- 同理
- 首先是
- 熟知
$((2#binary))
的原理, 是否会发现, 这里不是有个2
吗, 怎么绕过 WAF 呢- 其实只要在嵌套一层
$((...))
就可以 - 可以只使用
1
和<
通过左移运算得到2
- 如
$((1<<1))
- 如
- 所以
$((2#binary))
可以写为$(($((1<<1))#binaryStr))
- 其实只要在嵌套一层
- 然后把
$(($((1<<1))#binaryStr))
套入到八进制转义中, 这里拿ls
举例- 注意的是, 这里的
$((2#binary))
不是直接转为八进制数, 而是转为十进制的数, 而这个十进制数当做八进制使用, 转换步骤详细如下ls 转为八进制 -> \154\163 使用八进制转义 -> $'\154\163' 使用二进制替换 154 和 163, 这两个数现在当做十进制154 -> $((2#10011010)) -> $(($((1<<1))#10011010))163 -> $((2#10100011)) -> $(($((1<<1))#10100011)) 于是 $'\154\163' -> $'\$(($((1<<1))#10011010))\$(($((1<<1))#10100011))'
- 注意的是, 这里的
- 但是使用
$'\$(($((1<<1))#10011010))\$(($((1<<1))#10100