skip to Main Content

In our Global.asax file we have:

protected void Application_Error()
{
    Errors.Functions.HandleException(HttpContext.Current);
}

On a 404 error, the following code is executed:

context.Server.Transfer("~/pages/errors/404.aspx");
context.ClearError();
context.ApplicationInstance.CompleteRequest();

This works absolutely fine for every 404 exception. However, we’re seeing odd requests in our logs to paths that don’t exist such as:

https://www.example.com/en/meta.json

Visiting this page serves a normal 404 response page as above, and doesn’t throw any exceptions.

However, these requests (I’m guessing from some vulnerability scanner or crawler) throw this exception on a daily basis:

TYPE: HttpException
BASE TYPE: ExternalException
MESSAGE: Error executing child request for /pages/errors/404.aspx.

SOURCE:
System.Web

STACK TRACE:
   at System.Web.HttpServerUtility.ExecuteInternal(IHttpHandler handler, TextWriter writer, Boolean preserveForm, Boolean setPreviousPage, VirtualPath path, VirtualPath filePath, String physPath, Exception error, String queryStringOverride)
   at System.Web.HttpServerUtility.Execute(String path, TextWriter writer, Boolean preserveForm)
   at System.Web.HttpServerUtility.Transfer(String path, Boolean preserveForm)
   at System.Web.HttpServerUtility.Transfer(String path)
   at C3.Code.Controls.Application.Errors.Functions.HandleException(HttpContext context) in ...HandleHTTPException.cs:line 81

Line 81 is the context.Server.Transfer(.. line.

The inner exception is:

TYPE: NullReferenceException
BASE TYPE: SystemException
MESSAGE:
Object reference not set to an instance of an object.

SOURCE:
C3Alpha2

STACK TRACE:
   at C3.Pages.Errors._404.Page_Load(Object sender, EventArgs e) in ...PagesErrors404.aspx.cs:line 12
   at System.Web.UI.Control.OnLoad(EventArgs e)
   at System.Web.UI.Control.LoadRecursive()
   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)

Where line 12 is on of the Page_Load lines:

public partial class _404 : System.Web.UI.Page
{
    public Master_Pages.Main MP => (Master_Pages.Main) Master;

    protected void Page_Load(object sender, EventArgs e)
    {
        MP.IsErrorPage = true;
        MP.SEOPageHeader.Title = "File not found";
    }
}

The requests throwing the error are normal HTTP GET requests, and logging details about the headers etc doesn’t show anything that looks too unusual.

Does anyone know what could be causing this to throw these exceptions?

Edit: As requested, the 404.aspx page:

<%@ Page Language="C#" ValidateRequest="false" EnableViewState="false" MasterPageFile="~/Pages/Master Pages/Main.master" AutoEventWireup="True" Inherits="C3.Pages.Errors._404" Codebehind="404.aspx.cs" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Head" runat="server">
    <base href="<%= C3.Code.Settings.Hosts.SecureRootDomain %>"/>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Body" runat="server">
    
    <span class="preH1">Ahhhh nuts!</span>
    <h1>We Couldn't Find That!</h1>
    <div class="singleCol">

        <Controls:ResponsiveImageFixedSize
            runat="server"
            ImagePath="/errors/404.jpg"
            Width="700"
        />
        <p>The server returned an HTTP 404 error.  That requested URL could not be found.</p>
        
    </div>

</asp:Content>

2

Answers


  1. What I want to say is not the exact answer to your question, but it may help to investigate your problem (because the text was a bit long, I did not write it in the comments).

    This problem of yours reminded me of our problem.

    My problem:

    A few years ago, I wrote an "MVC ASP .NET Core 3.1" application for a company using "KendoUI" and with the company’s development tool, which was "Visual Studio 2019" and "Windows 10". This program received information about the user’s browser and client IP at some point of the operation based on the received request and was logged in the "Microsoft SQL" database (the program could only be used in LAN and the users were inside the company, but the program also had access to the Internet).

    Sometimes we come across strange things in the logs:

    For example, instead of the client’s full domain, a web address was inserted, and that address was mostly the same.

    I think the basic information for the full name of the client was obtained with the following method:

    var ComputerName = Dns.GetHostEntry(Context.Connection.RemoteIpAddress).HostName;
    

    As far as I know, the program’s system was never hacked, but the following possibilities are possible:

    1- It may be related to the behavior of Visual Studio in compiling
    code or .NET classes. Perhaps we should have changed a setting in
    Visual Studio or the project.

    2- It may be the result of the activity of black hat hackers in different parts of the world who may have used its server and temporarily changed the functionality of a part of the website.
    (Of course, that company has implemented strong security measures and the possibility of hacking is low, and as far as I know, MVC in Microsoft web projects prevents some kind of hacking attacks.)

    3- It may be the result of some NuGet packages being installed in the
    project of that website.

    Suggestion:

    In my opinion, run the copy of your site in an isolated server in the
    form of a sandbox and cut off the Internet access for that program and
    after a while the program works, see if these things happen again. If
    it happens, you can rest assured that it is not the work of hackers.

    Also, if you are extracting client information somewhere in the error
    processing, please take a closer look at the information extraction
    functions.

    Login or Signup to reply.
  2. Based on the OP’s problem-description, the long-and-short of it is that when a Server.Transfer() request is made to "~/pages/errors/404.aspx" something causes a NullReferenceException on one of these two lines (the OP didn’t specify exactly which line the stack-trace pointed at):

    this.MP.IsErrorPage = true;
    this.MP.SEOPageHeader.Title = "File not found";
    

    The this.MP property returns the Page.Master property, cast to Master_Pages.Main.

    It is possible but unlikely that this.MP is returning null – because that will only happen in Page_Load if the Page.MasterPageFile property is set to null despite ASP.NET setting it to a valid virtual-path due to the <%@ Page Master="" %> directive property.

    It’s more likely that MP.SEOPageHeader is returning null, which means the next operation (setting .Title = "File not found") will fail with a NullReferenceException.


    The OP declined to share the details of what exactly happens in the SEOPageHeader property’s get accessor – and their description only fuels speculation because it seems to have a big scope of responsibility "it’s a helper that sets various header meta tags for each page (canonical URLs, rel=next/prev etc etc), icon files, page titles etc etc".

    Unable to diagnose the problem thoroughly, the next-best-thing I can do is suggest setting-up appropriate logging – and splitting-up can-fail operations (like this.MP.SEOPageHeader.Title) with intermediate variables which can be safely inspected for null and log accordingly:

    Me: I suggest you rewrite _404’s Page_Load method to add some assertions and logging – so that the next time it happens, you’ll have a much better idea of what’s wrong (e.g. don’t directly access properties-of-properties, instead use a new local-variable to store the result of each property level/depth and test each return-value to ensure it’s not null).

    Tom: i I think that’s a good solution

    So I advocate updating Page_Load to this:

        using MainMasterPage = Master_Pages.Main;
    
    //  public MainMasterPage MP => (MainMasterPage)base.Master;
    
        protected void Page_Load(object sender, EventArgs e)
        {
            try
            {
                this.SetUpMasterPage();
            }
            catch( Exception ex )
            {
                // TODO: Log this exception.
                throw; // <-- Be sure to re-throw this exception instead of swallowing it, because at-this-point-in-time we don't know exactly what went-wrong so we cannot preemptively decide that *any and all* exceptions can be safely ignored like this.
                // For example, supposing there's an exception caused by an ASP.NET Server Control invariant violation during the Init or Load stages in the pipeline/request-lifecycle: - swallowing the exception will make things worse because that same Server Control will then throw a new exception when ASP.NET tries to render it.
                // Instead, prefer to fail-fast, and keep an eye on your logs and frequently re-publish with appropriate graceful handling for each known exception type: https://stackoverflow.com/questions/2807241/what-does-the-expression-fail-early-mean-and-when-would-you-want-to-do-so
            }
        }
    
        private void SetUpMasterPage()
        {
            if( base.Master is MasterPage anyMaster )
            {
                if( anyMaster is MainMasterPage mp )
                {
                    mp.IsErrorPage = true;
                    if( mp.SEOPageHeader is TypeOfSEOPageHeader seoHeader )
                    {
                        seoHeader.Title = "HTTP 404: Not Found";
                    }
                    else
                    {
                        // TODO: Log warning that `base.Master.SEOPageHeader` is null - though this won't necesarily make whatever underlying problem there is any easier to diagnose...
                    }
                }
                else
                {
                    // TODO: Log warning that `base.Master` is non-null, but is also not of the expected type `Master_Pages.Main`
                }
            }
            else
            {
                // TODO: Log warning that `base.Master` is null.
            }
        }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search