Getting IIS to return 405 on a disallowed verb
A PEN test discovered that a OPTIONS verb returned data from my (ASP.NET 4/MVC 5) server. Based on a number of sources, in the web.config, I've configured IIS to block this verb using
<system.webServer>
<security>
<requestFiltering>
<verbs>
<add verb="OPTIONS" allowed="false"/>
</verbs>
</requestFiltering>
</security>
</system.webServer>
This "works" but reponds with a 404 (Not Found). The security team that did the PEN test say this is not sufficient. (And my client, who hired the team really wants me to conform to their requirements).
It's also not what I expect and want: Like said here"The request method is known by the server but has been disabled and cannot be used.", thus it should return a 405 (Method Not Allowed).
However, as described here the current response is by design: "When IIS rejects a request based on this feature, the error code logged is 404.6.". According to Wikipedia they call it "verb denied".
I don't get this. Why is -in this case suitable (or even standardized?)- response of "405" not given here? And more important: how can I get IIS to respond with a 405 on a disallowed verb/request method?
1 answer
-
answered 2021-02-20 14:59
JHBonarius
I came up with a workaround using some custom error handling. My web.config now has
<system.webServer> <security> <requestFiltering> <verbs> <add verb="OPTIONS" allowed="false"/> </verbs> </requestFiltering> </security> <httpErrors errorMode="Custom" existingResponse="Replace" > <remove statusCode="404" subStatusCode="-1"/> <error statusCode="404" subStatusCode="6" path="/Error/MethodNotAllowed" responseMode="ExecuteURL"/> <error statusCode="404" path="/Error/NotFound" responseMode="ExecuteURL"/> [...etc] </httpErrors> </system.webServer>
And I've added a method to my ErrorController.cs
public class ErrorController : Controller { [...] public ActionResult MethodNotAllowed() { return new HttpStatusCodeResult(HttpStatusCode.MethodNotAllowed); } }
And this seems to "work". When I use postmaster to request an OPTIONS, I get 405 and when I GET a non existing page, I still get my custom 404 page.
See also questions close to this topic
-
Filter items in a listbox that have been added with json
Well I'm trying to list items that are from listbox created with UserControl and the text properties are defined with a json file.
This is my .json file:
{ "Games": { "Quantity": 2, "Title0": "SomeGame1", "Description0": "Fps game", "Image0": "Some image link", "Link0": "GameStore.com/Somegame1", "Title1": "SomeGame2", "Description1": "RPG game", "Image1": "Some image link", "Link1": "GameStore.com/Somegame2", } }
This is the code to load the games as items in the listbox:
string JsonFile = Environment.CurrentDirectory @"\Test.json"; dynamic jasonfile = JsonConvert.DeserializeObject(JsonFile); GameUserControl[] Games = new GameUserControl[jasonfile["Games"]["Quantidade"]]; for (int quantity= 0; quantity < Games.Length; quantity++) { Games[quantity] = new GameUserControl(); Games[quantity].Descrição.Content = (jasonfile["Games"]["Title" + quantity]); Games[quantity].jog = (jasonfile["Games"]["Titulo" + quantity]); Games[quantity].lin = (jasonfile["Games"]["Link" + quantity]); string image = jasonfile["Games"]["Image" + quantity]; Games[quantity].imag = new ImageBrush(new BitmapImage(new Uri(image, UriKind.Absolute))); GamesListBox.Items.Add(Games[quantity]); }
This is the code I used in a textbox to try to filter:
if (CollectionViewSource.GetDefaultView(GamesListBox.Items) != null) CollectionViewSource.GetDefaultView(GamesListBox.Items).Filter = (o) => { return o.ToString().ToLower().Contains(Search.Text.ToLower()); };
But it didn't work, the item names are always GameUserContro.Can someone help me?
-
Advantage of .Net Core over WCF for RESTful APIs
We are currently using WCF to create RESTful APIs, it is working fine and has an added advantage that it can be consumed via SOAP too if we ever need to. We have all our systems using Microsoft technologies.
There is no active development on WCF but the current functionality is working fine for us. However, I believe the recommended approach is to start using .Net core for RESTful services. What are the additional advantages .Net core offers over WCF (apart from being platform independent)?
-
Generic class type constraint with a generic class having another constraint
Let's say I have a generic class
public class G<T> { }
and I want to declare final class as
public class F<T> where T : G<T> { }
that seems to be possible, but what if I want to complicate the task and add a constraint to the class G like that
public class A { } public class DA : A { } public class DB : A { } public class G<T> where T : A { }
and finally I want to do this
public class F<T> where T : G<T> { }
that does not work, it says T has to be of type A which is understandable and it looks like I can rewrite it like this
public class F<T, U> where T : G<U> where U : A { }
but in this case the usage has a redundant declaration
public class DF : F<G<DA>, DA> { }
I have to repeat DA twice when using class F even though it is quite clear if I use G as a generic type the generic type of G is DA. Is there a way to avoid this redundancy?
-
Cascading databound <ajaxtoolkit:combobox> and <asp:dropdownlist> in asp.net
I have an
asp.net
search form that includes anajaxToolkit Combobox
and a standardasp DropDownList
. Both controls are bound to two separatedSqlDatasource
components.Something like this:
<ajaxToolkit:ComboBox ID="cbConvenzionato" runat="server" AutoCompleteMode="SuggestAppend" DropDownStyle="DropDownList" DataSourceID="sdsConvenzionati" DataTextField="nome" DataValueField="id" AutoPostBack="true" OnSelectedIndexChanged="cbConvenzionato_SelectedIndexChanged" /> <asp:DropDownList ID="ddlVeicoli" DataSourceID="sdsVeicoli" DataTextField="targa" DataValueField="id" runat="server" AutoPostBack="true" OnSelectedIndexChanged="ddlVeicoli_SelectedIndexChanged" AppendDataBoundItems="true"> <asp:ListItem Text="TUTTI" Value="" Selected="True" /> </asp:DropDownList> <asp:SqlDataSource ID="sdsConvenzionati" runat="server" ConnectionString="<%$ ConnectionStrings:db %>" ProviderName="<%$ ConnectionStrings:db.ProviderName %>" SelectCommand=" SELECT id, nome FROM anag_convenzionati ORDER BY nome;" /> <asp:SqlDataSource ID="sdsVeicoli" runat="server" EnableCaching="false" CancelSelectOnNullParameter="false" ConnectionString="<%$ ConnectionStrings:db %>" ProviderName="<%$ ConnectionStrings:db.ProviderName %>" SelectCommand=" SELECT id, targa FROM veicoli_contratti WHERE ((@id_convenzionato IS NULL) OR (id_convenzionato = @id_convenzionato)) ORDER BY targa;"> <SelectParameters> <asp:ControlParameter Name="id_convenzionato" ControlID="cbConvenzionato" PropertyName="SelectedValue" Direction="Input" ConvertEmptyStringToNull="true" DbType="Int32" DefaultValue="" /> </SelectParameters> </asp:SqlDataSource>
There's also a third
sqldatasource
(sdsNoleggi
) that feeds agridview
but this's not a problem right now.In code behind I have two event handlers:
protected void cbConvenzionato_SelectedIndexChanged(object sender, EventArgs e) { sdsVeicoli.Select(DataSourceSelectArguments.Empty); Search(); } protected void ddlVeicoli_SelectedIndexChanged(object sender, EventArgs e) { Search(); } private void Search() { sdsNoleggi.Select(DataSourceSelectArguments.Empty); }
I tought in this way I should filter
ddlVeicoli
items after selecting an item incbConvenzionato
... but it's not working... why?If I look into
sdsVeicoli
SelectParameters
in debug I can seeid_convenzionato
being correctly set to selected value (id coming fromcbConvenzionato
) I bet also thatsdsNoleggi
dataset wiil be correctly updated with new values since I did this many times before. So why bound control it's not? I tried also to force addlVeicoli.DataBind()
aftersdsVeicoli.Select()
call ... but this had no effect. -
Swagger UI not working for REST API (asp.net web api2) application
I have asp.net mvc project with .NET Framework 4.7.2 and the same project contains asp.net web api2 controller in a separate folder : Controllers. The solution is legacy. The API are already in use in the PRODUCTION environment. Now I added the Swagger nuget package (Install-Package Swashbuckle -Version 5.6.0) to this existing project. Post that I see a SwaggerConfig.cs added to the App_Start folder of the Solution Explorer.
Here the asp.net mvc controllers are used by App1 pointing to the server: www.app1.com and asp.net web api2 controllers are used by another frontend angular app: App2 pointing to the server : www.app2.com
The complete deployment package for both App1 and App2 are hosted in IIS
Any request related to App1 is handled by www.app1.com and any api request related to App2 (Angular frontend) is handled by App1 only using IIS Rewrite rules at App2 level which redirect any api request to App1 only.
Now in this case when I tried to navigate to www.app1.com/swagger , I see it is loading the SwaggerUI for me, but when I tried to navigate to www.app2.com/swagger it is not working and instead of that it is loading the Angular frontend application
Here goes the App1 and App2 at IIS level:
Can anyone help me here by providing their guidance to fix this issue?
-
Cors error missing allow origin header. MailKit
I have
cors error missing allow origin header
error only on ONE post request. My CORS Policypublic void ConfigureServices(IServiceCollection services) { services.AddCors(options => { options.AddPolicy("AllowAllOrigins", builder => { builder.SetIsOriginAllowed(_ => true) .AllowAnyHeader() .AllowAnyMethod() .AllowCredentials(); }); }); }
Every request work fine, but one POST request fails, it's really weird. Code in controller action which failed use MailKit and SMTP to send email, maybe that's cause
-
GroupJoin without having to select contents from joined list
So I've got two classes that I'm trying to combine into a ViewModel for use in the application. I'm trying to find the lambda syntax to perform a left join between the two objects (Actual Delivery, DeliveryHdr). For some context the DeliveryHdr is a scheduled delivery on a schedule and the Actual Delivery is details collected once the delivery is made. I'm using the provided method (CovertToViewModel) to conmbine the two objects and return a list of ViewModels and it functions like I want it to but I'm thinking there has to be an easier way? How can I perform a 1 to 1 left join without having to perform Select's on the joined List like I've done below?
public partial class ActualDelivery { public int ActualDeliveryId { get; set; } public int DeliveryId { get; set; } public string DockDoor { get; set; } public string ArrivalComments { get; set; } public string SetTemp { get; set; } public string Unloader { get; set; } public DateTime? UnloadStart { get; set; } public DateTime? UnloadEnd { get; set; } public int? ActualAmbientFull { get; set; } public int? ActualAmbientMixed { get; set; } public int? ActualReefer { get; set; } public int? ActualCageVault { get; set; } public int? ActualBlc { get; set; } public int? ActualTotalPallets { get; set; } public int? ActualTotalLpns { get; set; } public DateTime? CreatedDttm { get; set; } public string CreatedUser { get; set; } public DateTime? UpdatedDttm { get; set; } public string UpdatedUser { get; set; } }
public partial class DeliveryHdr { public int DeliveryId { get; set; } public DateTime? LoadDate { get; set; } public DateTime? ScheduledTime { get; set; } public DateTime? ArrivalTime { get; set; } public int? LoadNumber { get; set; } public string Shift { get; set; } public string SupplierNumber { get; set; } public string SupplierName { get; set; } public string Carrier { get; set; } public bool? IsCancelled { get; set; } public bool? IsConfirmed { get; set; } public bool? IsBackHaul { get; set; } public int? ActAmbientFullPallets { get; set; } public int? ActAmbientMixedPallets { get; set; } public int? ActReeferPallets { get; set; } public int? ActCageVaultPallets { get; set; } public int? ActBlcpallets { get; set; } public int? ActTotalPallets { get; set; } public int? ActTotalLpns { get; set; } public bool? MarkAsDeleted { get; set; } public string CreatedUser { get; set; } public DateTime? CreatedDttm { get; set; } public string UpdatedUser { get; set; } public DateTime? UpdatedDttm { get; set; } }
public class ActualDeliveriesViewModel { public int DeliveryId { get; set; } public int ActualDeliveryId { get; set; } public string CompositeId { get; set; } public DateTime? LoadDate { get; set; } public DateTime? ScheduledTime { get; set; } public DateTime? ActualTime { get; set; } public string Shift { get; set; } public int? LoadNumber { get; set; } public string SupplierName { get; set; } public string Carrier { get; set; } public bool? IsConfirmed { get; set; } public bool? IsBackHaul { get; set; } public bool? IsCancelled { get; set; } public string DockDoor { get; set; } public string ArrivalComments { get; set; } public string SetTemp { get; set; } public string Unloader { get; set; } public DateTime? UnloadStart { get; set; } public DateTime? UnloadEnd { get; set; } public int? ActualAmbientFull { get; set; } public int? ActualAmbientMixed { get; set; } public int? ActualReefer { get; set; } public int? ActualCageVault { get; set; } public int? ActualBlc { get; set; } public int? ActualTotalPallets { get; set; } public int? ActualTotalLpns { get; set; } }
public List<ActualDeliveriesViewModel> CovertToViewModel(List<DeliveryHdr> deliveries, List<ActualDelivery> actuals) { return deliveries.Where(e => e.MarkAsDeleted == false).GroupJoin(actuals, d => d.DeliveryId, a => a.DeliveryId, (d, a) => new ActualDeliveriesViewModel() { DeliveryId = d.DeliveryId, ActualDeliveryId = a.Select(i => i.ActualDeliveryId).FirstOrDefault(), CompositeId = d.DeliveryId + "_" + a.Select(i => i.ActualDeliveryId).FirstOrDefault(), LoadDate = d.LoadDate, ScheduledTime = d.ScheduledTime, ActualTime = d.ArrivalTime, LoadNumber = d.LoadNumber, SupplierName = d.SupplierName, Carrier = d.Carrier, IsConfirmed = d.IsConfirmed, IsBackHaul = d.IsBackHaul, IsCancelled = d.IsCancelled, DockDoor = a.Select(i => i.DockDoor).FirstOrDefault(), ArrivalComments = a.Select(i => i.ArrivalComments).FirstOrDefault(), SetTemp = a.Select(i => i.SetTemp).FirstOrDefault(), Unloader = a.Select(i => i.Unloader).FirstOrDefault(), UnloadStart = a.Select(i => i.UnloadStart).FirstOrDefault(), UnloadEnd = a.Select(i => i.UnloadEnd).FirstOrDefault(), ActualAmbientFull = a.Select(i => i.ActualAmbientFull).FirstOrDefault(), ActualAmbientMixed = a.Select(i => i.ActualAmbientMixed).FirstOrDefault(), ActualBlc = a.Select(i => i.ActualBlc).FirstOrDefault(), ActualCageVault = a.Select(i => i.ActualCageVault).FirstOrDefault(), ActualReefer = a.Select(i => i.ActualReefer).FirstOrDefault(), ActualTotalPallets = (a.Select(i => i.ActualAmbientFull).FirstOrDefault() + a.Select(i => i.ActualAmbientMixed).FirstOrDefault() + a.Select(i => i.ActualBlc).FirstOrDefault() + a.Select(i => i.ActualCageVault).FirstOrDefault() + a.Select(i => i.ActualReefer).FirstOrDefault()) ?? 0 }).ToList(); }
-
OutputCache an ActionResult that only returns a View
Would it make sense to [OutputCache] something like this?
[HttpGet] public ActionResult About() { return this.View("About"); }
-
The entity type was not found. Ensure that the entity type has been added to the model
I'm new to ASP.NET Core and i'm trying to insert an entity into an Entity Framework Core model scaffolded from a simple existing MariaDB database.
This is the entity model:
public class ScrapeAsincroni { public int Id { get; set; } public string Paese { get; set; } public string Engine { get; set; } public string Keywords { get; set; } }
This is the controller action that is supposed to add the entity:
public JsonResult create(string paese, string engine, string keywords) { ScrapeAsincroni scrapeAsincrono = new ScrapeAsincroni { Paese = paese, Engine = engine, Keywords = keywords }; _context.Add(scrapeAsincrono); try { _context.SaveChangesAsync(); } catch (Exception ex) { return Json(new Dictionary<string, int?> { { "id", null } }); } return Json(new Dictionary<string, int?>{ {"id", scrapeAsincrono.Id} }); }
The database context (_context) has been initialized on the controller's constructor. the line
_context.Add(scrapeAsincrono);
throws the following exception:
System.InvalidOperationException: The entity type 'ScrapeAsincroni' was not found. Ensure that the entity type has been added to the model.
This is the modelBuilder code relative to this model
public partial class ScraperDbContext : DbContext { public ScraperDbContext() { } public ScraperDbContext(DbContextOptions<ScraperDbContext> options) : base(options) { } public virtual DbSet<ScrapeAsincroni> ScrapeAsincroni { get; set; } protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { if (!optionsBuilder.IsConfigured) { #warning To protect potentially sensitive information in your connection string, you should move it out of source code. See http://go.microsoft.com/fwlink/?LinkId=723263 for guidance on storing connection strings. optionsBuilder.UseMySql("server=51.255.74.100;port=3306;user=luca.ceccagnoli;password=Hb93#2ql;database=scraper_db", x => x.ServerVersion("10.3.25-mariadb")); } } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<ScrapeAsincroni>(entity => { entity.HasComment("Informazioni su una ricerca asincrona dello Scraper"); entity.Property(e => e.Id) .HasColumnName("id") .HasColumnType("int(11)"); entity.Property(e => e.Engine) .HasColumnName("engine") .HasColumnType("varchar(255)") .HasCharSet("utf8") .HasCollation("utf8_general_ci"); entity.Property(e => e.Keywords) .IsRequired() .HasColumnName("keywords") .HasColumnType("text") .HasCharSet("utf8") .HasCollation("utf8_general_ci"); entity.Property(e => e.Paese) .HasColumnName("paese") .HasColumnType("varchar(255)") .HasCharSet("utf8") .HasCollation("utf8_general_ci"); }); OnModelCreatingPartial(modelBuilder); } partial void OnModelCreatingPartial(ModelBuilder modelBuilder); }
I can't seem to understand why this happens, and couldn't find any solutions online.
-
Mapping IIS application with domain name. (Working perfectly for the real IP)
I have an application deployed in IIS. It's working fine with the real IP address. When I hit the IP address outside the virtual machine application is loading.
I want to bind the real IP with a domain name like (www.domain.com) so that I can access the application using the domain name.
Please suggest me the process.
Advanced Thanks.
-
Automation of IIS Farms
I am trying to automate many different aspect of IIS when site are running using the server farm option. My problem is I am unable to figure out which command if any can get any values from the server farm themselves. All I am currently able to get is information's on the basic IIS settings or anything related to a website (except farm).
This is all the
Get
method I have and none seems to have an option for server farms. Am I missing a component on my server ?Cmdlet Get-IISAppPool 1.0.0.0 IISAdministration Cmdlet Get-IISCentralCertProvider 1.0.0.0 IISAdministration Cmdlet Get-IISConfigAttributeValue 1.0.0.0 IISAdministration Cmdlet Get-IISConfigCollection 1.0.0.0 IISAdministration Cmdlet Get-IISConfigCollectionElement 1.0.0.0 IISAdministration Cmdlet Get-IISConfigElement 1.0.0.0 IISAdministration Cmdlet Get-IISConfigSection 1.0.0.0 IISAdministration Cmdlet Get-IISServerManager 1.0.0.0 IISAdministration Cmdlet Get-IISSharedConfig 1.0.0.0 IISAdministration Cmdlet Get-IISSite 1.0.0.0 IISAdministration
The minimum I would need to get is the health check status of each server in each farms. All my server in all my farms implement the health check status to know if they are online or not. If I can at least get that value I can manage the rest from the config files on all the servers. Obviously I rather be able to get every value from a PowerShell command.
-
Give Write access to IIS of wwwroot/image folder in Elastic Beanstalk, .net core
I want to give write permission to IIS (running on elastic beanstalk) of a sub folder of
wwwroot
folder, asiis
has no write permission onwwwroot
folder by default, how can I do this.I have tried following.
- tried including folder
.ebextension
and create config file in it as stated here, but when I am creating a file with.config
extension it becomes axml
file so can't put anyjson/yaml
code in it.
Please suggest me a right way to do it or any easy solution to this issue, I found the docs pretty confusing.
- tried including folder
-
IIS 10.0 Request Filtering / Allow unlisted file name extensions won't work as expected
I have unchecked the option allow unlisted file name extensions , and then added all the following extensions with which I am working with.
- .cfm (allow)
- .cfc (allow)
- .js (allow)
- .css (allow)
- .jpg (allow)
- .png (allow)
- .gif (allow)
- .woff (allow)
- .woff2 (allow)
Everything works great, however when I attempt to make a call of one of my CFML components, such as
/mywebsite.com/mvc.cfc?method=getCustomers
then the request is blocked. I would expect that this wouldn't be blocked as the extension of mvc.cfc is a .cfc which is a member of the allowed list.
Could you please help understand what is going on? If I enter any other extension such as .js or .cfm , all is ok, the only problem is with the .cfc though.
Thank you
-
How to allow only certain query string parameters in IIS?
In IIS URL Rewrite, I need to Abort all requests, Excepted those which :
- do not have any querystring parameter
- or
- do have one or more querystring parameters within a limited set of querystring parameters.
Every request with one or more querystring parameters outside of the limited set will get an AbortRequest.
So for example :
- https://mysite123/page.html Will be accepted
- https://mysite123/page.html?allowed3=ccc Will be accepted
- https://mysite123/page.html?allowed1=aaa&allowed2=bbb Will be accepted
- https://mysite123/page.html?allowed1=aaa&disallowed4=nope Will be rejected
I've been playing and fiddling for days, but did not come to a working solution.
-
requestFiltering has Invalid Child element <alwaysAllowedUrls>
I want to block xml files to have direct access by urls but want to give access to only one URL with xml extension. Tried this code from microsoft and done some modifications.
<system.webServer> <security> <requestFiltering> <fileExtensions> <add fileExtension=".xml" allowed="false"/> </fileExtensions> <alwaysAllowedUrls> <add url="/bad_sequence.txt" /> </alwaysAllowedUrls> </requestFiltering> </security> </system.webServer>
visual studio showing is invalid child. my IIS is 10.version.