High severity8.8NVD Advisory· Published May 12, 2026· Updated May 13, 2026
CVE-2026-43937
CVE-2026-43937
Description
YetAnotherForum.NET (YAF.NET) is a C# ASP.NET forum. Prior to 4.0.5, Any admin OnPost… handler executes its side effects before the ResultFilterAttribute rewrites the response to a 302 to /Info/4. The most impactful abuse is /Admin/RunSql, whose OnPostRunQuery binds Editor from the POST body and passes it straight to IDbAccess.RunSql with no caller check, yielding arbitrary SQL execution for any low-privileged user. This vulnerability is fixed in 4.0.5.
Patches
127f7e671f936use IAsyncPageFilter instead of ResultFilterAttribute
4 files changed · +107 −143
.github/workflows/build.yml+1 −1 modified@@ -28,7 +28,7 @@ jobs: node-version: ${{ matrix.node-version }} - name: Install Node Packages working-directory: ./yafsrc/YetAnotherForum.NET - run: npm install + run: npm ci - name: Build working-directory: ./ run: dotnet build ./yafsrc/YAF.NET-SqlServer.slnx
yafsrc/YAFNET.Core/BasePages/ForumPage.cs+105 −1 modified@@ -22,20 +22,25 @@ * under the License. */ +using YAF.Core.Model; + namespace YAF.Core.BasePages; +using System.Threading.Tasks; + using Microsoft.AspNetCore.Mvc.RazorPages; using Microsoft.AspNetCore.Mvc.Rendering; using YAF.Core.Filters; using YAF.Core.Handlers; using YAF.Types.Attributes; +using YAF.Types.Models; /// <summary> /// The class that all YAF forum pages are derived from. /// </summary> [EnableRateLimiting("fixed")] -[PageSecurityCheck] +//[PageSecurityCheck] [UserSuspendCheck] public abstract class ForumPage : PageModel, IHaveServiceLocator, @@ -47,6 +52,105 @@ public abstract class ForumPage : PageModel, /// </summary> private readonly UnicodeEncoder unicodeEncoder; + /// <summary> + /// Called asynchronously before the handler method is invoked, after model binding is complete. + /// </summary> + /// <param name="context">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutingContext" />.</param> + /// <param name="next">The <see cref="T:Microsoft.AspNetCore.Mvc.Filters.PageHandlerExecutionDelegate" />. Invoked to execute the next page filter or the handler method itself.</param> + public async override Task OnPageHandlerExecutionAsync(PageHandlerExecutingContext context, PageHandlerExecutionDelegate next) + { + // no security features for login/logout pages + if (BoardContext.Current.CurrentForumPage.IsAccountPage) + { + await next.Invoke(); + } + + // check if login is required + if (BoardContext.Current.BoardSettings.RequireLogin && BoardContext.Current.IsGuest && + BoardContext.Current.CurrentForumPage.IsProtected) + { + // redirect to login page if login is required + var result = this.Get<IPermissions>().HandleRequest(ViewPermissions.RegisteredUsers); + + if (result != null) + { + context.Result = result; + return; + } + } + + // check if it's a "registered user only page" and check permissions. + if (BoardContext.Current.CurrentForumPage.IsRegisteredPage && + BoardContext.Current.CurrentForumPage.AspNetUser == null) + { + var result = this.Get<IPermissions>().HandleRequest(ViewPermissions.RegisteredUsers); + + if (result != null) + { + context.Result = result; + + return; + } + } + + // Handle admin pages + if (BoardContext.Current.CurrentForumPage.IsAdminPage) + { + if (!BoardContext.Current.IsAdmin) + { + context.Result = this.Get<ILinkBuilder>().AccessDenied(); + return; + } + + // Load the page access list. + var hasAccess = this.GetRepository<AdminPageUserAccess>().HasAccess( + BoardContext.Current.PageUserID, + BoardContext.Current.CurrentForumPage.PageName.ToString()); + + // Check access rights to the page. + if (!BoardContext.Current.PageUser.UserFlags.IsHostAdmin && + (!BoardContext.Current.CurrentForumPage.PageName.ToString().IsSet() || !hasAccess)) + { + context.Result = this.Get<ILinkBuilder>() + .RedirectInfoPage(InfoMessage.HostAdminPermissionsAreRequired); + + return; + } + } + + // handle security features... + if (BoardContext.Current.CurrentForumPage.PageName == ForumPages.Account_Register && + BoardContext.Current.BoardSettings.DisableRegistrations) + { + context.Result = this.Get<ILinkBuilder>().AccessDenied(); + + return; + } + + // check access permissions for specific pages... + var resultPermission = BoardContext.Current.CurrentForumPage.PageName switch + { + ForumPages.ActiveUsers => this.Get<IPermissions>() + .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.ActiveUsersViewPermissions), + ForumPages.Members => this.Get<IPermissions>() + .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.MembersListViewPermissions), + ForumPages.UserProfile or ForumPages.Albums or ForumPages.Album => this.Get<IPermissions>() + .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.ProfileViewPermissions), + ForumPages.Search => this.Get<IPermissions>() + .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.SearchPermissions), + _ => null + }; + + if (resultPermission != null) + { + context.Result = resultPermission; + + return; + } + + await next.Invoke(); + } + /// <summary> /// Initializes a new instance of the <see cref="ForumPage"/> class. /// </summary>
yafsrc/YAFNET.Core/Filters/PageSecurityCheckAttribute.cs+0 −140 removed@@ -1,140 +0,0 @@ -/* Yet Another Forum.NET - * Copyright (C) 2003-2005 Bj�rnar Henden - * Copyright (C) 2006-2013 Jaben Cargman - * Copyright (C) 2014-2026 Ingo Herbote - * https://www.yetanotherforum.net/ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - - * https://www.apache.org/licenses/LICENSE-2.0 - - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -namespace YAF.Core.Filters; - -using System; -using System.Threading.Tasks; - -using YAF.Core.Model; -using YAF.Types.Models; - -/// <summary> -/// Page Security Check -/// Implements the <see cref="ResultFilterAttribute" /> -/// Implements the <see cref="IHaveServiceLocator" /> -/// </summary> -/// <seealso cref="ResultFilterAttribute" /> -/// <seealso cref="IHaveServiceLocator" /> -[AttributeUsage(AttributeTargets.Class)] -public class PageSecurityCheckAttribute : ResultFilterAttribute, IHaveServiceLocator -{ - /// <summary> - /// Gets or sets ServiceLocator. - /// </summary> - public IServiceLocator ServiceLocator => BoardContext.Current.ServiceLocator; - - /// <summary> - /// On result execution as an asynchronous operation. - /// </summary> - /// <param name="context">The context.</param> - /// <param name="next">The next.</param> - /// <returns>A Task representing the asynchronous operation.</returns> - /// <inheritdoc /> - public override Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next) - { - // no security features for login/logout pages - if (BoardContext.Current.CurrentForumPage.IsAccountPage) - { - return next.Invoke(); - } - - // check if login is required - if (BoardContext.Current.BoardSettings.RequireLogin && BoardContext.Current.IsGuest && - BoardContext.Current.CurrentForumPage.IsProtected) - { - // redirect to login page if login is required - var result = this.Get<IPermissions>().HandleRequest(ViewPermissions.RegisteredUsers); - - if (result != null) - { - context.Result = result; - } - } - - // check if it's a "registered user only page" and check permissions. - if (BoardContext.Current.CurrentForumPage.IsRegisteredPage && - BoardContext.Current.CurrentForumPage.AspNetUser == null) - { - var result = this.Get<IPermissions>().HandleRequest(ViewPermissions.RegisteredUsers); - - if (result != null) - { - context.Result = result; - } - } - - // Handle admin pages - if (BoardContext.Current.CurrentForumPage.IsAdminPage) - { - if (!BoardContext.Current.IsAdmin) - { - context.Result = this.Get<ILinkBuilder>().AccessDenied(); - } - else - { - // Load the page access list. - var hasAccess = this.GetRepository<AdminPageUserAccess>().HasAccess( - BoardContext.Current.PageUserID, - BoardContext.Current.CurrentForumPage.PageName.ToString()); - - // Check access rights to the page. - if (!BoardContext.Current.PageUser.UserFlags.IsHostAdmin && - (!BoardContext.Current.CurrentForumPage.PageName.ToString().IsSet() || !hasAccess)) - { - context.Result = this.Get<ILinkBuilder>() - .RedirectInfoPage(InfoMessage.HostAdminPermissionsAreRequired); - } - } - } - - // handle security features... - if (BoardContext.Current.CurrentForumPage.PageName == ForumPages.Account_Register && - BoardContext.Current.BoardSettings.DisableRegistrations) - { - context.Result = this.Get<ILinkBuilder>().AccessDenied(); - } - - // check access permissions for specific pages... - var resultPermission = BoardContext.Current.CurrentForumPage.PageName switch - { - ForumPages.ActiveUsers => this.Get<IPermissions>() - .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.ActiveUsersViewPermissions), - ForumPages.Members => this.Get<IPermissions>() - .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.MembersListViewPermissions), - ForumPages.UserProfile or ForumPages.Albums or ForumPages.Album => this.Get<IPermissions>() - .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.ProfileViewPermissions), - ForumPages.Search => this.Get<IPermissions>() - .HandleRequest((ViewPermissions)BoardContext.Current.BoardSettings.SearchPermissions), - _ => null - }; - - if (resultPermission != null) - { - context.Result = resultPermission; - } - - return next.Invoke(); - } -} \ No newline at end of file
yafsrc/YAFNET.Core/Services/BoardInfo.cs+1 −1 modified@@ -57,7 +57,7 @@ public class BoardInfo(IServiceLocator serviceLocator) : IHaveServiceLocator /// <summary> /// Gets the Current YAF Build Date /// </summary> - public DateTime AppVersionDate { get; set; } = new (2026, 04, 01, 08, 17, 00, DateTimeKind.Utc); + public DateTime AppVersionDate { get; set; } = new (2026, 04, 23, 06, 11, 00, DateTimeKind.Utc); /// <summary> /// Creates a string that is the YAF Application Version from a long value
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5News mentions
0No linked articles in our index yet.