禁用ssl重协商以达到解决DOS漏洞

第三方工具检测8883端口(mosquitto mqtt服务器)和443(python下使用aiohttp库web生成的server)有DOS漏洞,需要禁用相关端口的ssl的重协商功能。或者直接在openssl源码中禁用重协商功能也可以。请问要怎么做才能禁用重协商?8883下的mosquitto使用的是库,只有配置文件可以修改。443端口的python版本是3.8。只要能解决掉该DOS漏洞的方法都可以。

mosquitto.conf 配置中加上ssl_options reused_session false

openssl.cnf文件中你可以设置一些用来禁用

[system_default_sect]
Options = !SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS

[ssl_client]
Options = !SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS

[ssl_server]
Options = !SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS

#conf文件中禁用重协商
listener 8883
tls_version tlsv1.2
tls_ciphers HIGH:!aNULL:!MD5:!RC4:!DSS
tls_no_ticket true
tls_options no_renegotiation

1、首先,你需要找到OpenSSL 的配置文件:
在Linux系统中,一般在 /etc/ssl/openssl.cnf 或 /usr/local/ssl/openssl.cnf 目录下;
在Windows系统中,一般在 OpenSSL 安装目录下的 bin\openssl.cfg 文件中。

2、其次,找到 [system_default_sect] 或 [default] 段,添加以下内容来禁用重协商功能:

[system_default_sect]
Options = -SessionTicket -renegotiate

3、最后保存并退出配置文件。

关于 8883 端口的 Mosquitto 使用库的情况,你可以在 Mosquitto 的配置文件 mosquitto.conf 中加入以下行禁用客户端与代理的重协商功能:

# 在mosquitto.conf配置文件中的内容
listener 8883
tls_version tlsv1.2
ciphers <your_cipher_string>
reneg_limit 0

对于 443 端口的 Python 下使用 aiohttp 库 web 生成的 server,您需要在创建 TLS 上下文时将 options 参数设置为 ssl.OP_NO_RENEGOTIATION,如下所示:

import ssl
import aiohttp

context = ssl.SSLContext(protocol=ssl.PROTOCOL_TLS)
context.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_RENEGOTIATION

# 创建 app 时,将 context 对象传递给 ssl 参数
app = web.Application()
web.run_app(app, host='127.0.0.1', port=443, ssl_context=context)

tls 禁用重协商_SSL/TLS高危不安全重新协商漏洞
可以参考下
https://blog.csdn.net/weixin_29999895/article/details/111955780


1、关闭renegotiation协议或限制SSL重协商数,以防止TLS DOS攻击:在Apache 2.2.15以上版本中,可以通过在配置文件httpd.conf中,添加如下字串:SSLInsecureRenegotiation Off;如使用的Apache版本低于2.2.15,则可以通过限制SSL重协商的次数防止DOS攻击。

2、使用WEB应用防火墙防止中间人攻击:通过WEB应用防火墙,对HTTP Header请求头进行过滤和监控,舍弃嵌入式的Http请求行,以防止中间人攻击。

3、禁止使用SSLv3协议

可先使用openssl客户端检测是否支持SSLv3:

openssl s_client -ssl3 -connect [host]:443

如果服务器不支持SSLv3会返回类似下面的信息:

SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure:/xx/src/ssl/s3_pkt.c:1125:SSL alert number 40
SSL routines:SSL3_WRITE_BYTES:ssl handshake failure:/xx/src/ssl/s3_pkt.c:546:

【Nginx、Apache、IIS禁用SSLv3方法】:

Apache

SSLProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCipherSuite ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:!aNULL:!MD5:!DSS

Nginx
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:RC4-SHA:!aNULL:!eNULL:!EXPORT:!DES:!3DES:!MD5:!DSS:!PKS;
ssl_session_timeout 5m;
ssl_session_cache builtin:1000 shared:SSL:10m;


IIS

请参考:http://support2.microsoft.com/kb/187498/en-us
  或:http://support2.microsoft.com/kb/187498/zh-cn
进行手工修复,或者使用fix it向导进行修复。

把433端口禁用调吧,然后你再把python下使用aiohttp库web生成的server的端口换成其它端口。或者在服务器禁用客户端重新协商功能看看是否可行

在 Python 中,可以使用 ssl 模块设置 SSL OP_NO_RENEGOTIATION 选项来禁用 SSL 重协商

试试这个办法是否可行:

import ssl
from aiohttp import web

app = web.Application()

ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.options |= ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | ssl.OP_NO_RENEGOTIATION

web.run_app(app, ssl_context=ssl_context)



对于 mosquitto mqtt 服务器(使用的是库):
mosquitto 是一个轻量级的 MQTT 消息代理服务软件,如果您使用的是 Linux 系统,具体的配置文件位置可以在命令行执行 mosquitto -h 查看。进入配置文件后,需要加入两个配置项:


#禁止 SSL/TLS 重协商
ssl_options renegotiation_limit=-1

#禁止 SSLv2 和 SSLv3 协议
listener 8883
protocol mqtt
cafile /etc/ssl/certs/broker.crt
keyfile /etc/mosquitto/certs/broker.key
require_certificate true
tls_version tlsv1.2
ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384

其中,ssl_options renegotiation_limit=-1 表示禁止 SSL/TLS 重协商;tls_version tlsv1.2 表示只接受 TLS 1.2 版本的协议,同时也禁止了 SSLv2 和 SSLv3 协议;ciphers 指定了 SSL/TLS 支持的密码套件。

对于使用 aiohttp 库生成的 web server:
在 Python 3.8 版本中,可以通过设置 SSLContext 的 renegotiation_cb 属性来禁用重协商:


python
import ssl
from aiohttp import web

ssl_ctx = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
ssl_ctx.options |= ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3
ssl_ctx.set_ciphers('ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384')
ssl_ctx.renegotiation_cb = ssl.disable_renegotiation

app = web.Application()
app.add_routes([...])
web.run_app(app, ssl_context=ssl_ctx, port=443)


其中,ssl.disable_renegotiation 是一个自定义的回调函数,用来禁用 SSL/TLS 重协商功能。

如果想直接修改 OpenSSL 源代码来禁止重协商功能,需要对源码进行修改并重新编译安装。具体操作可以参考 OpenSSL 的官方文档。

禁用 SSL 重协商功能可以通过修改 OpenSSL 库配置文件来实现

openssl_conf = openssl_init

[openssl_init]
ssl_conf = ssl_sect

[ssl_sect]
options = DONT_INSERT_EMPTY_FRAGMENTS

去这个 openssl/s3_lib.c 文件中,找到这行代码

if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS)
改一下

if (s->s3->flags & SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS || s->s3->flags & SSL3_FLAGS_CCS_OK)

然后再重新编译和安装OpenSSL库
完美且暴力 , 爱不爱

借助chatgpt:
修改mosquitto和aiohttp的配置文件。
mosquitto:


listener 0.0.0.0 8883

protocols mqtt 51843

ssl-default-bind-ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES256-SHA384:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK

ssl_prefer_server_ciphers on;

ssl_ciphers "EECDH+aRSA+RC4+3DES+EDH+AESGCM+AES256+EECDH+aRSA+RC4+3DES+EDH";


aiohttp:


import asyncio

from aiohttp import web



async def hello(request):

    return web.Response(text="Hello, world")



app = web.Application()

app.router.add_get('/', hello)



# 禁用SSL重协商功能

if hasattr(asyncio, 'start_tls') and hasattr(asyncio, 'create_server'):

    asyncio.set_event_loop(asyncio.new_event_loop())

    loop = asyncio.get_event_loop()

    server = loop.create_server(app.make_handler(), 'localhost', 443)

    server.serve_forever()

else:

    app.run_forever()



最后调试一下看看,应该没有问题。


import logging

logging.basicConfig(level=logging.DEBUG)