CTF中的命令执行及Bypass

温馨提示:点击页面下方以展开或折叠目录~

CTF中的命令执行及Bypass

  • 做题时发现bash的命令执行特性都不懂…白在win下的cmd试了那么久,于是乎决定总结一下
  • 准确来说应该是利用Linux下bash的特性,进行一下过滤绕过

参考1:https://mp.weixin.qq.com/s/Hm6TiLHiAygrJr-MGRq9Mw

参考2(和参考1一样):https://blog.zeddyu.info/2019/01/17/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C/

各种符号及其作用

分号

分号;隔开命令,从左到右依次执行,不管成功或者失败,所有命令都会执行

image-20211130093615925

管道符

管道符|上一条命令的输出作为下一条命令的参数

image-20211130190609517

逻辑或

||左边为真则右边不执行,||左边为假则继续执行右边

image-20211130211059978

逻辑与

&&先执行左边,左边为真则继续执行右边,否则不执行右边

image-20211130213745546

后台进程

&放在启动参数里表示设置此进程为后台进程(也即不会占用shell)

若连接两条命令则表示先执行右边再执行左边(先执行右再执行左不等于执行完右再执行左!

image-20211130220841182

1
2
3
4
5
6
[1] 26925
next
26926
before
26925
[1] + done python3 before.py

第一行为将左边的命令放后台执行,第2~3行为执行右边命令的效果,第4~5行为执行左边命令的效果,第6行表示执行左边命令(后台进程结束)完成

但是我如果让右边的命令sleep个5秒

image-20211130221512623

会发现本应先执行的next.py居然在before后才执行,我们再继续测试一下:

  • 在before里调用命令行执行了next,并给了一个命令行参数3
  • 在next里,如果有命令行参数则sleep 3秒(before给的);否则sleep5秒

image-20211130224919452

可以发现next确实是先执行了,但是next在sleep 5秒的期间,before也在执行,并且由于运行时间比next短,before先执行完毕

再测试一下是不是真的后面的指令先执行:

image-20211130230312558

可以看到next的time确实要比before早

因此大概可以推测:&的本质作用是将前一条命令放在后台,接着开始执行后面的命令,但是不会等后面的命令执行完才执行前面的命令,而是在后一条指令执行的同时也在执行前一条指令

{}和()

():

  1. 格式:(cmd1;cmd2;cmd3…)
  2. 重新开一个子shell执行

{}:

  1. 格式:{ cmd1;cmd2;….cmdn;}

    cmd1与左边花括号要有空格,最后一条命令要分号(我不知道这是不是真的,反正kali不用….kali的花括号和括号格式一样就行了)

  2. 在当前shell执行

  • 区别

    image-20211201103925442

    • 当使用()时,可以看到他们的ppid都为28045,而pid=28045的进程zsh是pid=26745的进程zsh的子进程,也就是说,在当前shell(pid=26745)下开了一个子shell(pid=28045),再由子shell去执行命令
    • 当使用{}时,可以看到他们的ppid都是26745,即父进程都是pid=26745的zsh本身,没有开一个子shell

反引

  • 命令替代,将某一指令的输出作为另一指令的输入

image-20211202205052773

各种读取文件的关键字

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat flag				// 正序输出所有内容
tac flag // 从最后一行开始倒序输出所有内容
php flag // php读取
head flag // 读文件前若干行(需要加参数 -n)
tail flag // 读文件后若干行(需要加参数 -n)
more flag // 按页读文件
less flag // 好像和more差不多
nl flag // 读文件顺便显示行号
od flag // 一般用od -c flag
file -f flag // 利用file报错出flag
sort flag // 按首列ascii排序后输出
uniq flag // 删除重复出现的行列
paste flag // 合并文件的行列并输出
diff flag file // 对比flag和file的不同
bzmore flag // 将bzip压缩过的文件解压后输出
bzless flag // bzmore增强版
curl file:///flag // file协议读
sed -n '1,2p' flag // 1,2表示显示1~2行,可以不要

可以把这些关键字存为一个字典,当遇到正则过滤时就fuzz一下看看有没有哪个没被过滤可以用的

文件名过滤绕过

  • 用于在正则过滤例如flag文件名时的绕过

通配符绕过

字符 解释
* 匹配任意长度任意字符
? 匹配任意单个字符
[list] 匹配指定范围内(list)任意单个字符,也可以是单个字符组成的集合
list 匹配指定范围外的任意单个字符或字符集合
[!list] [^list]
{str1,str2,…} 匹配 srt1 或者 srt2 或者更多字符串,也可以是集合
IFS 由 < space > 或 < tab > 或 < enter > 三者之一组成
CR 由 < enter > 产生
! 执行 history 中的命令

通配符*绕过

image-20211202102952846

通配符?绕过

image-20211202103223618

[]绕过

[]为文件名通配符,用来匹配指定范围内的任意单个字符

image-20211202103433300

{}绕过

{}为集合,匹配集合内的字符串

image-20211202103720217

专用字符集绕过

字符 意义
[:alnum:] 任意数字或者字母
[:alpha:] 任意字母
[:space:] 空格
[:lower:] 小写字母
[:digit:] 任意数字
[:upper:] 任意大写字母
[:cntrl:] 控制符
[:graph:] 图形
[:print:] 可打印字符
[:punct:] 标点符号
[:xdigit:] 十六进制数
[:blank:] 空白字符

image-20211202210142892

关键字绕过

  • 用于正则过滤例如cat关键字的绕过

命令提示符$绕过

  • $*$@$x(x=1~9)、${x}(x>9)
  • 在没有传参时,这些值都为空($0表示shell本身的文件名,不可用)

image-20211202104609939

可以插入在任意位置(关键字、文件名均可以)

反斜杠绕过

image-20211202160707368

单引连接符绕过

image-20211202160648306

空格绕过

<或者<>

image-20211202202720648

$IFS

$IFS在bash下为分隔符,不知道为什么kali中试不出效果(好像是zsh和bash的差异之一)

image-20211202204008762

后来发现可能不同的shell对IFS的默认值设定不一样,bash的话默认是空格,所以可以用

{}绕过

image-20211202204741101

又是zsh和bash的差异,{cat,flag}可以把逗号当作空格

编码绕过

base64编码

image-20211202162222954

16进制编码绕过

  • xxd -r -p将纯16进制转储读入

    image-20211202162425388

  • $()执行括号中语句的执行结果

    image-20211202162940683

命令执行

利用编码+shell

  • 16进制:echo hexString|xxd -r -p|bash
  • base64:echo base64String|base64 -d|bash

image-20211202192742665

变量拼接

有一个要注意的,如果是a=l;cat f$aag的话,他会把$aag当作一个变量,而我们没有定义这个变量从而读不到flag

image-20211202193401208

内联执行

反引号``(汗了md里怎么在行内代码打出反引….)和$():将其中命令的输出作为输入执行(新生赛就有一道题用了这个trick然而我不懂…在win下呆呆试了半天没绕过去)

image-20211202194207974

长度限制的getshell

  • 这个看了一下相关博客,当场直呼牛b内行,放在这里讲有点糟蹋了,打算另起一篇总结一下