[2024西湖论剑]only_sql

拿到题目后打开发现是一个mysql连接面板,初步猜测是在自己的远程数据库里写木马再写到靶机上 用vps开一个数据库,给root后连接,发现确实可以执行sql指令 但是没法写东西到靶机里(into outfile),搜索后发现是要开一个secure_file_priv的参数 并且我发现了这篇博客 可以用load data local infile语句在不受这个参数影响的情况下将文件内容读出来并写到我的远程数据库里。当然还可以使用搭建蜜罐的方式直接读文件,我后来选择使用后者 经过测试,蜜罐搭建后用面板连接,确实可以读取到文件 将query.php读出来就可以看到靶机运行的mysql的账号密码和库名,回到一开始的面板登录即可。登陆后,试了一圈也没发现flag文件,所以猜测是在环境变量。但是没找到读环境变量的方法,只能想办法rce 由于实在找不到什么除了sql外的rce手段,所以最后选择直接用udf提权 UDF(user defined function)用户自定义函数,是MySQL的一个扩展接口,称为用户自定义函数,是用来拓展MySQL的技术手段,用户通过自定义函数来实现在MySQL中无法实现的功能。文件后缀为.dll或.so,常用c语言编写。 先确定secure_file_priv是空值 show variables like '%secure%'; 之后确定一下mysql安装路径 show variables like '%basedir%'; 通过主机版本及架构确认mysql位数来选用udf文件 show variables like '%compile%'; 查看 plugin 目录 show variables like 'plugin%'; 还要再看一下有没有满足高位权限 select * from mysql.user where user = substring_index(user(), '@', 1) ; 最后看一下plugin的值 select host,user,plugin from mysql.user where user = substring_index(user(),'@',1); plugin值表示mysql用户的认证方式。当 plugin 的值为空时不可提权,为 mysql_native_password 时可通过账户连接提权。默认为mysql_native_password。另外,mysql用户还需对此plugin目录具有写权限。 上述条件满足且信息搜集完后,这里我选择用msf里自带的udf库文件,路径是/usr/share/metasploit-framework/data/exploits/mysql ...

January 30, 2024 · 1 min · Red

2024寒假训练赛3——Writeup

WEB TODO 题目给了两个端口,也就是起了两个web服务,一个是一个TODO应用,一个是。。。额。html测试器 应用一 应用二 作者直接给出了源码,页面里看不出啥,我们直接来看源码 在util/report.js发现了可疑的地方。 const LOGIN_URL = "http://127.0.0.1/login"; let browser = null const visit = async (url) => { const ctx = await browser.createIncognitoBrowserContext() const page = await ctx.newPage() await page.goto(LOGIN_URL, { waitUntil: 'networkidle2' }) await page.waitForSelector('form') await page.type('wired-input[name=username]', process.env.USERNAME) await page.type('wired-input[name=password]', process.env.PASSWORD) await page.click('wired-button') try { await page.goto(url, { waitUntil: 'networkidle2' }) } finally { await page.close() await ctx.close() } } const doReportHandler = async (req, res) => { ... await visit(url) ... } 在routes/index.js里可以看到router.post('/report', doReportHandler); ...

January 27, 2024 · 15 min · Red

2024寒假训练赛2——Writeup

WEB 窥视 一个简单的论坛系统 核心的api有 登录 POST /auth/login 注册 POST /auth/register 创建/回复帖子 POST /forum/post 审了一圈代码,唯一可操作的地方应该就是创建帖子(POST /forum/post)那一块了,这里有个文件图片上传 ValidationMiddleware("post", "/forum"), async function (req, res) { const { title, message, parentId, ...convertParams } = req.body; ... let attachedImage = null; if (req.files && req.files.image) { const fileName = randomBytes(16).toString("hex"); const filePath = path.join(__dirname, "..", "uploads", fileName); try { const processedImage = await convert({ ...convertParams, srcData: req.files.image.data, format: "AVIF", }); await fs.writeFile(filePath, processedImage); attachedImage = `/uploads/${fileName}`; } catch (error) { req.flashError("There was an issue processing your image, please try again."); console.error("Error occured while processing image:", error); return res.redirect("/forum"); } } ... } 随便进到一篇文章里po一张图片上去,结合POST表单和代码可以看出来,除了title, message, parentId三个参数外,其他参数都被写到convertParams里了, const processedImage = await convert负责用convertParams里的参数对图片进行一个转换。 ...

January 25, 2024 · 16 min · Red

2024寒假训练赛1——Writeup

WEB LoveTok 拿到附件后先看文件结构 还是比较简单的,老规矩,先从index入口开始 注意到这个对象,是个路由,路由方法在上面的函数。文件结构里找一下发现了同名的文件,进去看看 发现接收format参数后拿他去new了一个对象,同样跟进一下这个TimeModel文件 先看构造函数,可以看到会被addslashes过滤一遍。这里简单说一下这个函数的处理方法,如果被处理数据是输入到数据库中的,就会在例如单双引号、斜杠前面加上反斜杠进行转义。算是一种安全处理方式。不管要注意的就是,他只在数据输入进数据库时有效。 接下来就是一些显示的处理。看到下面的getTime方法,有个eval,应该就是利用这个家伙了 可以看到format有被放到eval中,但是不管输入什么都会被当成文本。怎么办呢?看提示 又是一个直接给payload的题了属于是 霓虹灯 一样,先看文件结构 发现不是常规语言,而是ruby 没事,同样先找index入口。 post提交了一个表单,没有明显的接口提示,那就直接看看controllers吧 没猜错,controllers控制着表单接收。如果经是验丰富的人看到这个正则匹配应该就知道肯定需要绕过了,但是我们还不清楚这个ERB对象是干嘛用的,再看看其他文件,也没发现有这个ERB类的定义,所以猜测应该是ruby自带的 搜了一下发现还真是,是个模板,而且还有个模板注入漏洞 发现ERB是Embedded RuBy的简称,意思是嵌入式的Ruby,是一种文本模板技术 网上提供了很多这个模板的注入方法,简单看了一下,读文件应该是长下面这样 <%= File.open('flag.txt').read %> 但是显然这应该不满足我们的正则匹配规则,怎么办呢?我看到了这篇文档 简单来说就是用^或者$,但是实测发现并不奏效,不过也当作是个知识点记录一下 怎么办呢?继续搜,发现了这个 是的,使用%0a或者\n换行就能绕过。拿我们前面的payload测试一下 1111%0a<%= File.open('/flag').read %> 这里有个坑要注意,如果上面这句payload直接在前端的输入框输入,就会被多次url编码,导致后端接收到的结果与预期不同,因此要将%,=等符号手动url编码后放置到数据包中进行发送 最终在数据包中的payload应该如下 neon=111%0a<%25%3d+File.open('/flag').read+%25> 有毒朋友 简单的文件包含与本地命令执行,下载附件后先看入口index.php 发现是读cookie,并且看到是被base64编码的,因此可以抓包下来看到serialize($page)的内容 在右侧已经被自动解码 继续看代码,跟进到PageModel 发现有一个文件包含的地方,并且可以通过控制刚刚cookie中的参数来达到访问不同的文件的效果。此时包含什么文件进来都会被当成php代码执行。而现在要找到能够查看并且可随着数据包而修改的文件内容的,第一个想起的就是服务器的日志文件。它会记录我们对服务器的访问请求。具体可以看我的这篇博客 所以可以通过修改User-Agent,从而达到让日志文件被写入php指令并执行的目的 这里要注意,得发送两次才能看到ls的结果,可以思考一下这是为什么 MISC 嘈杂 就像提示里说的那样,这里直接放exp import numpy as np from scipy.io.wavfile import read from scipy.fft import dst # 读取音频文件 final_waveform = read("encrypted.wav") # 对音频信号进行离散余弦变换(DST) result = dst(final_waveform[1]) # 从变换结果中选择幅度大于10^5的值 amplitudes = result[result > 10**5] amplitudes.sort() # 用于存储恢复的文本 recovered = "" # 遍历选定的幅度值 for a in amplitudes: # 找到幅度在变换结果中的位置 found = np.where(result == a)[0][0] # 判断位置是否为奇数 if found % 2 == 1: # 计算字符对应的ASCII码值 c = round(found / 20) # 将ASCII码值缩小,直到在可打印字符范围内 while c > 128: c //= 4 # 将字符添加到恢复的文本中 recovered += chr(c) # 打印恢复的flag print(recovered) 莫斯档案馆 每一层有一个pwd.png和一个压缩包,pwd.png是一个彩色条纹和圆点的非常小的图像,也就是摩斯密码,套了很多很多层,写脚本去识别摩斯密码,并递归解压。 ...

January 24, 2024 · 12 min · Red

[靶场笔记]第十一章

@在php curl中的作用 简单来说,就是当使用上面这个Curl方法时,使用@可以读取文件。因此在一些url参数中如果使用了这个方法(可以用是否是执行ping命令来判断),就可能存在LFI preg_match()函数漏洞 在这个函数中,可以存在三个参数 preg_replace($pattern, $replacement, $subject) 作用:搜索subject中匹配pattern的部分, 以replacement的内容进行替换。 $pattern: 要搜索的模式,可以是字符串或一个字符串数组。 $replacement: 用于替换的字符串或字符串数组。 $subject: 要搜索替换的目标字符串或字符串数组。 /e 可以修正符使该函数将replacement 参数当作 PHP 代码。例如 pat=/abc/e&rep=system("ls")&sub=abc 因为e在这里是作修饰符,因此abc必须用两个斜杠括起来(正则表达式)。 flask session伪造 flask session的构造方式是明文+SECRET_KEY+时间,因此伪造的关键在于获取SECRET_KEY。可以使用flask session manager工具进行伪造 /proc/self/… 这是一个特殊的目录,算是与linux内核的一个接口。如果是/proc/{pid}这样的目录,那么这个目录下的内容则是相应进程的运行信息。 有几个比较重要的文件,可以参考下图(原文) PHP session反序化漏洞 可以看这篇博客,其实就是在生产环境中如果对php session的读取和存储方式不一致,就会导致格式上的差异,从而导致触发反序化漏洞 但仔细一想,在真实渗透环境中应该很少有程序员会在php.ini设置好的基础上再添加其他php session处理器了吧,就当学习一下 题目的名字 有时候,题目的名字就隐藏了这道题的poc,不信可以试试这题😂 不过还是记录一下深信服的EDR RCE吧深信服 EDR终端检测响应平台RCE漏洞代码分析 一个巧妙的变量覆盖 preg_match()绕过 %0a没被禁用的情况下,是可以起到绕过的作用的。不然就是用大量字符导致preg_match()崩溃输出false。这种方法适合用在判断语句如下的情况 if(!preg_match(...)) ereg的00截断 很早之前记录过这个函数,不过不能识别数组的特性会让其返回false。今天再补充一个特性,就是当这个函数读到%00就会截止返回null,可以用来应付下面这种情况 if(ereg(...)!==FALSE) 科学计数法 php的判断是支持科学计数法的,例如1e8,会被判断成三个字符,但是这个数字可比9999999大多了

December 12, 2023 · 1 min · Red