0%

漏洞解析

Apache Shiro 1.2.4反序列化漏洞(CVE-2016-4437)
Apache Shiro是一个Java安全框架,执行身份验证、授权、密码和会话管理。只要rememberMe的AES加密秘钥泄露,无论shiro是什么版本都会导致反序列化漏洞。
Apache Shiro 1.2.4及以前版本中,加密的用户信息序列化后存储在名为remember-me的Cookie中。攻击者可以使用Shiro的默认密钥伪造用户Cookie,触发Java反序列化漏洞,进而在目标机器上执行任意命令。

漏洞环境

使用vulhub环境
执行如下命令启动一个使用了Apache Shiro 1.2.4的Web服务:

1
2
cd vulhub/shiro/CVE-2016-4437
docker-compose up -d
阅读全文 »

漏洞详解

反序列化:把字节序列恢复为对象的过程,即把可以存储或传输的数据转换为对象的过程。例如将二进制数据流或文件加载到内存中还原为对象。
序列化:把对象转换为字节序列的过程,即把对象转换为可以存储或传输的数据的过程。例如将内存中的对象转换为二进制数据流或文件,在网络传输过程中,可以是字节或是XML等格式。
简单来说,序列化就像是把数据加密,像json一样的格式,反序列化就是解密成原来的样子

漏洞可能出现的位置

  1. 解析认证token、session的位置
  2. 将序列化的对象存储到磁盘文件或存入数据库后反序列化时的位置,如读取json文件,xml文件等
  3. 将对象序列化后在网络中传输,如传输json数据,xml数据等
  4. 参数传递给程序
  5. 使用RMI协议,被广泛使用的RMI协议完全基于序列化
  6. 使用了不安全的框架或基础类库,如JMX 、Fastjson和Jackson等
  7. 定义协议用来接收与发送原始的java对象

PHP反序列化

阅读全文 »

文件包含解析

文件包含,是一个功能。在各种开发语言中都提供了内置的文件包含函数,其可以使开发人员在一个代码文件中直接包含(引入)另外一个代码文件。 比如 在PHP中,提供了:
include(),include_once()
require(),require_once()
这些文件包含函数,这些函数在代码设计中被经常使用到。
大多数情况下,文件包含函数中包含的代码文件是固定的,因此也不会出现安全问题。 但是,有些时候,文件包含的代码文件被写成了一个变量,且这个变量可以由前端用户传进来,这种情况下,如果没有做足够的安全考虑,则可能会引发文件包含漏洞。 攻击着会指定一个“意想不到”的文件让包含函数去执行,从而造成恶意操作。 根据不同的配置环境,文件包含漏洞分为如下两种情况:
1.本地文件包含漏洞:仅能够对服务器本地的文件进行包含,由于服务器上的文件并不是攻击者所能够控制的,因此该情况下,攻击着更多的会包含一些 固定的系统配置文件,从而读取系统敏感信息。很多时候本地文件包含漏洞会结合一些特殊的文件上传漏洞,从而形成更大的威力。
2.远程文件包含漏洞:能够通过url地址对远程的文件进行包含,这意味着攻击者可以传入任意的代码,这种情况没啥好说的,准备挂彩。
因此,在web应用系统的功能设计上尽量不要让前端用户直接传变量给包含函数,如果非要这么做,也一定要做严格的白名单策略进行过滤。

各种语言的文件包含

1
2
3
<!--#include file="1.asp" -->

<!--#include file="top.aspx" -->
阅读全文 »

awvs 的爬虫很好用,支持表单分析和单页应用的爬取,xray 的扫描能力比较强,速度也更快。awvs 和 xray 搭配使用则是如虎添翼。
xray官方手册

awvs安装

docker镜像地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#  pull 拉取下载镜像
docker pull secfa/docker-awvs

# 将Docker的3443端口映射到物理机的 13443端口
docker run -it -d -p 13443:3443 secfa/docker-awvs

# 容器的相关信息
username: admin@admin.com
password: Admin123
AWVS版本:14

#如何更改凭据

1.docker exec -u root -it $docker_names /bin/bash
2./home/acunetix/.acunetix/change_credentials.sh
3.输入您的新凭证

xray安装

阅读全文 »

less-01

  • 源码

    1
    2
    3
    4
    5
    <?php 
    ini_set("display_errors", 0);
    $str = $_GET["name"];
    echo "<h2 align=center>欢迎用户".$str."</h2>";
    ?>

    反射型xss,无过滤

  • payload
    对于XSS漏洞,在实战中未避免因关键字被发现,多采用h5标签进行试探。

    注入XSS

    1
    name=<script>alert('xss')</script>

less-02

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <?php 
    ini_set("display_errors", 0);
    $str = $_GET["keyword"];
    echo "<h2 align=center>没有找到和".htmlspecialchars($str)."相关的结果.</h2>".'<center>
    <form action=level2.php method=GET>
    <input name=keyword value="'.$str.'">
    <input type=submit name=submit value="搜索"/>
    </form>
    </center>';
    ?>

    反射型XSS,htmlspecialchars($str)过滤,把预定义的字符 “<” (小于)和 “>” (大于)转换为 HTML 实体

  • payload
    此处需要将突破点转向value,首先应该闭合标签(“>),在进行xss注入。

    1
    keyword="><script>alert(1)</script>

less-03

阅读全文 »

解析漏洞

Apache 换行解析漏洞(CVE-2017-15715)

上传抓包

在1.php后面插入一个\x0A(注意,不能是\x0D\x0A,只能是一个\x0A),不再拦截:

阅读全文 »

pass-01

  • 源码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    function checkFile() {
    var file = document.getElementsByName('upload_file')[0].value;
    if (file == null || file == "") {
    alert("请选择要上传的文件!");
    return false;
    }
    //定义允许上传的文件类型
    var allow_ext = ".jpg|.png|.gif";
    //提取上传文件的类型
    var ext_name = file.substring(file.lastIndexOf("."));
    //判断上传文件类型是否允许上传
    if (allow_ext.indexOf(ext_name + "|") == -1) {
    var errMsg = "该文件不允许上传,请上传" + allow_ext + "类型的文件,当前文件类型为:" + ext_name;
    alert(errMsg);
    return false;
    }
    }
  • 上传
    白名单,仅允许上传.jpg|.png|.gif,但是只有前端校验
    上传jpg抓包修改为php

  • 连接webshell
    复制图片地址,使用蚁剑连接

pass-02

源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {
if (file_exists(UPLOAD_PATH)) {
if (($_FILES['upload_file']['type'] == 'image/jpeg') || ($_FILES['upload_file']['type'] == 'image/png') || ($_FILES['upload_file']['type'] == 'image/gif')) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$img_path = UPLOAD_PATH . '/' . $_FILES['upload_file']['name']
if (move_uploaded_file($temp_file, $img_path)) {
$is_upload = true;
} else {
$msg = '上传出错!';
}
} else {
$msg = '文件类型不正确,请重新上传!';
}
} else {
$msg = UPLOAD_PATH.'文件夹不存在,请手工创建!';
}
}
阅读全文 »

爬取墨迹天气,土味情话,ONE每日图片定时发送邮件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178

import smtplib
import time
from email.mime.text import MIMEText
import requests
from lxml import etree
import datetime
from fake_useragent import UserAgent

sender_maile = '' # 发件人地址
sender_pass = '' # 邮件授权码
boy_name = '' # 发件人姓名
girl_name = '' # 收件人姓名
maile_obj = smtplib.SMTP_SSL('smtp.qq.com', 465) # 发送的服务器
receiver_mail = '' # 收件人邮箱
special_day = '' # 纪念日
province = '' # 省份 墨迹天气官网查看 示例province = 'guangxi'
city = '' # 城市 示例city = 'jiangnan-district'
title = 's' # 邮件主题
ua = UserAgent()
header = {
'Referer': 'https://tianqi.moji.com/weather/china/guangxi', # 根据城市修改
'User-Agent': ua.random
}

session = requests.session()


# 获取纪念日距今多少天
def get_day():
d1 = datetime.datetime.strptime(special_day, '%Y-%m-%d')
d2 = datetime.datetime.strptime(datetime.datetime.now().strftime('%Y-%m-%d'), '%Y-%m-%d')
delta = d2 - d1
return delta.days


# 获取每日土味情话
def get_chp():
url = "https://api.lovelive.tools/api/SweetNothings"
resp = requests.get(url=url)
return resp.text


# 获取提醒
def get_weathertip():
try:
url = f'https://tianqi.moji.com/weather/china/{province}/{city}'
resp = session.get(url=url, headers=header, verify=False)
html = etree.HTML(resp.text)
em = html.xpath('/html/body/div[4]/div[1]/div[4]/em/text()')[0]
return em
except:
return False


# 获取每日天气
def get_weather():
try:
url = f'https://tianqi.moji.com/weather/china/{province}/{city}'
resp = session.get(url=url, headers=header, verify=False)
html = ''
htmls = etree.HTML(resp.text)
ul = htmls.xpath('/html/body/div[5]/div[1]/div[1]/ul')
for lis in ul:
# 获取日期
day = lis.xpath('./li[1]/a/text()')[0]
# 获取天气图标
src = lis.xpath('./li[2]/span/img/@src')[0]
# 获取天气状况
weather = lis.xpath('./li[2]/span/img/@alt')[0]
# 获取温度
temperature = lis.xpath('./li[3]/text()')[0]
# 获取空气质量
air = lis.xpath('./li[5]/strong/text()')[0].strip()
# 获取空气质量对应的字体颜色
color = str(lis.xpath('./li[5]/strong/@class')[0])
# 判断字体颜色
if color == 'level_1':
color = '#8fc31f'
elif color == 'level_2':
color = '#d7af0e'
elif color == 'level_3':
color = '#f39800'
elif color == 'level_4':
color = '#e2361a'
elif color == 'level_5':
color = '#5f52a0'
elif color == 'level_6':
color = '#631541'
html += """<div style="display: flex;margin-top:5px;height: 30px;line-height: 30px;justify-content: space-around;align-items: center;">
<span style="width:15%%; text-align:center;">%s</span>
<div style="width:10%%; text-align:center;">
<img style="height:26px;vertical-align:middle;" src='%s' alt="">
</div>
<span style="width:25%%; text-align:center;">%s</span>
<div style="width:35%%; ">
<span style="display:inline-block;padding:0 8px;line-height:25px;color:%s; border-radius:15px; text-align:center;">%s</span>
</div>
</div>
""" % (day, src, temperature, color, air)
return html
except:
return False


# 获取图片
def get_image():
url = "http://wufazhuce.com/"
resp = requests.get(url=url)
html = etree.HTML(resp.text)
img_url = html.xpath('//*[@id="carousel-one"]/div/div[1]/a/img/@src')[0]
return img_url


# 获取当天日期
def get_today():
i = datetime.datetime.now()
date = "%s/%s/%s" % (i.year, i.month, i.day)
return date


mail_content = """<!DOCTYPE html>
<html>

<head>
<title>
</title>
<meta name="viewport" content="width=device-width,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
<meta charset="UTF-8">
</head>

<body style="margin:0;padding:0;">
<div style="width:100%; margin: 40px auto;font-size:20px; color:#5f5e5e;text-align:center">
<span>今天是我们在一起的第</span>
<span style="font-size:24px;color:rgb(221, 73, 73)" >{0}</span>
<span>天</span>
</div>
<div style="width:100%; margin: 0 auto;color:#5f5e5e;text-align:center">
<span style="display:block;color:#676767;font-size:20px">{2}</span>
<br>
<span style="display:block;color:#676767;font-size:20px">{1}</span>
<span style="display:block;margin-top:15px;color:#676767;font-size:15px">近期天气预报</span>
{3}
</div>
<div style="text-align:center;margin:35px 0;">
<span style="display:block;margin-top:55px;color:#676767;font-size:15px">{4} ❤️ {5}</span>
<span style="display:block;margin-top:25px;font-size:22px; color:#9d9d9d; ">{6}</span>
<img src='{7}' style="width:100%;margin-top:10px;" alt="">
</div>
</body>

</html>""".format(str(get_day()), get_weathertip(), get_chp(), get_weather(), boy_name, girl_name,
get_today(), get_image())


# 发送邮件
def send_mail():
try:
maile_obj.login(sender_maile, sender_pass)
# 三个参数分别是发件人邮箱账号,收件人账号,发送的邮件内容
msg = MIMEText(mail_content, _subtype='html', _charset='utf-8')
msg['Subject'] = title
msg['From'] = "发送人名称"
msg['To'] = "接收人名称"
maile_obj.sendmail(sender_maile, receiver_mail, msg.as_string())
maile_obj.quit()
return True
except smtplib.SMTPException as e:
return False


if __name__ == '__main__':
send_mail()
print('发送成功!')
theTime = datetime.datetime.now()
print(theTime)


效果

js源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
define("newweb/common/service", ["./utils", "./md5", "./jquery-1.7"], function(e, t) {
var n = e("./jquery-1.7");
e("./utils");
e("./md5");
var r = function (e) {
var t = n.md5(navigator.appVersion)
, r = "" + (new Date).getTime()
, i = r + parseInt(10 * Math.random(), 10);
return {
ts: r,
bv: t,
salt: i,
sign: n.md5("fanyideskweb" + e + i + "Ygy_4c=r#e#4EX^NUGUc5")
}
};
// e = 翻译的字符串, i = 字符串形式的js时间戳+一位整数

python实现代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

import time
import hashlib
import requests

def get_fanyi(word):
# 13位时间戳
lts = str(int(time.time() * 1000))
# 时间戳+一个随机整数
salt = str(int(time.time() * 10000))
# 写死的两个参数+翻译的字符+salt
sign = "fanyideskweb" + word + salt + "Y2FYu%TNSbMCxc3t2u^XT"
# md5 加密字符
sign = hashlib.md5(sign.encode()).hexdigest()

data = {"i": word,
"from": "AUTO",
"to": "AUTO",
"smartresult": "dict",
"client": "fanyideskweb",
# 时间戳14位
"salt": salt,
# 加密的数据
"sign": sign,
# 时间戳13位
"lts": lts,
"bv": 'd771cbe0c376715add7059261c9e06bd',
"doctype": "json",
"version": "2.1",
"keyfrom": "fanyi.web",
"action": "FY_BY_REALTlME"
}
url = 'https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule'
header = {
'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.60 Safari/537.36',
'Referer': 'https://fanyi.youdao.com/',
'cookie': 'OUTFOX_SEARCH_USER_ID=-1711366876@10.108.160.105; OUTFOX_SEARCH_USER_ID_NCOO=528854206.9578509; '
'fanyi-ad-closed=0; JSESSIONID=aaab35aMiB_2j8wyyH0-x; fanyi-ad-id=305426; '
'___rl__test__cookies=1649078361368 '
}
resp = requests.post(url=url, headers=header, data=data)
print(resp.json()['translateResult'][0][0]['tgt'])


if __name__ == '__main__':
get_fanyi('dog')