I am submitting a query string that contains a value
Body=%3Ch2%3E (Body=<h1>)
to a servicestack rest endpoint. That results in:
A potentially dangerous Request.QueryString value was detected from the client (Body=\"<h2>\").
I know that in MVC 4 you can allow Html content for an specific field, if you decorate the field in the model with [AllowHtml] like so:
[AllowHtml]
public string Body { get; set; }
Did that, but the error persists. Had doubts that it was service stack not partaking properly in the validation process, so tested by creating a pure MVC 4 controller with the same model, and that works fine.
However I need a solution for ServiceStack. Their documentation is thin and Google searches lead nowhere.
It looks like you are hosting your ServiceStack service inside an ASP.NET application.
You could add the following to the <system.web> section of your web.config file in order to disable request validation for the entire application:
<system.web>
<httpRuntime requestValidationMode="2.0" />
...
</system.web>
And if you want to disable request validation only for a particular endpoint and not the entire application use the <location> tag in your web.config:
<location path="hello">
<system.web>
<httpRuntime requestValidationMode="2.0" />
</system.web>
</location>
This will disable request validation for all /hello endpoints in your application. For example /hello?Body=%3Ch2%3E will work but /bar?Body=%3Ch2%3E won't work.
You can read more about request validation in ASP.NET in the following MSDN article.
And obviously you should not be worried about this if you are self-hosting your ServiceStack service.
Related
I have a .NetCore 3.1 API project that uses Entity Framework.
It is working perfectly when I run it locally from Visual Studio.
However, after publishing to a production IIS 8.5 server, I get the following errors when I try to hit an API that uses PUT on the production server.
xhr.js:178 PUT https://nationalparks.xyz.gov/api/plants/91 405 (Method
Not Allowed)
My controller begins like this:
[HttpPut("{id}")]
public async Task<IActionResult> PutPlant(long id, [FromBody] Plant plant)
{
...
}
And client-side looks like this:
await axios({
method: "PUT",
url: "api/plants/" + plant.id,
data: JSON.stringify(plant),
headers: { 'Content-Type': 'application/json; charset=utf-8' }
});
Honestly I'm stumped...I'm not sure why it's doing that.
I've seen a few posts saying to modify the web.config, but my app uses appsettings.json, not a web.config.
Any ideas?
Thanks!
The reason behind the issue is the WebDAV module intercepted the request. to resolve the issue you could follow the below workaround.
1)Remove WebDAV from your system:
open control panel-> “Turn Windows Features On or Off”->un-ticking the WebDAV publishing checkbox.
or
2)Add below code in your web.config file:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
Please remember that after doing these changes you can nit use the WebDAV module in iis.
dotnet core applications do use web.config when running under IIS. You will notice that the publish command makes a web.config file that tells IIS which DLL to run for your application.
I think I had the same issue a while back. I fixed it by adding lines to web.config to remove the WebDAV modules. See this answer for more detail:
https://stackoverflow.com/a/12443578/65432
I've recently run into an issue with a simple Web API service I'm running for a customer. The service accepts either a GET or a POST. The POST method is defined like this:
public IHttpActionResult PostUpload(UploadModel model)
{ ... }
The model looks like this:
public class UploadModel
{
public Guid UserKey { get; set; }
public string OrgCode { get; set; }
public byte[] Export { get; set; }
}
The customer reported today that he's started having trouble with the client program we built to interact with the service. The program logs whenever it receives a status code from the service other that 200. Whenever the customer runs the program, he's receives a 404 - Not Found. I verified in the IIS logs that the program is sending a POST request, and that the URI is correct.
When I run the program, it always receives a 200 status.
The code in the method only returns one of two possible IHttpActionResult: Ok if there were no issues, otherwise InternalServerError().
Using Postman, I've tried sending a variety of different combinations/values for parameters UserKey, OrgCode, and Export, but I can't get the API to send back anything other than 200 or 500 status. I've tried using the same data as the customer, and from my end it always goes through.
It seems to be some sort of routing issue, like it can't identify the correct method, but I can't see what the issue is. Would appreciate someone pointing out what I'm obviously missing.
Sharing the resolution with the community: After further contact with the customer, it turns out that the data I had to test with wasn't the same as what he had. The data he was sending in the POST was quite a lot larger than what I was sending. This triggered a thought regarding something I had run into in the past. I was so focused on the URI and routing, and the specific error (404) that I didn't think about max allowed upload size.
Setting the following in the web config to allow requests of up to 100MB fixed the issue:
<system.web>
<httpRuntime maxRequestLength="102400" />
</system.web>
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="104857600" />
</requestFiltering>
</security>
</system.webServer>
I'm using Forms Authentication for an internal company website. I authenticate users against the local Active Directory server.
I have my Web.config file set up as follows:
<authentication mode="Forms">
<forms name=".ADAuthCookie" loginUrl="~/Login" timeout="30" slidingExpiration="true" protection="All" defaultUrl="/" />
</authentication>
This works fine as long as a user moves to a new page, or refreshes the page they're on. However, much of my UI is based on javascript templating and AJAX, so it's quite possible for a user to be working on a page for longer than 30 minutes.
So, how do I query and/or extend how much time they have remaining in their session via an AJAX call? I don't need help with the AJAX call, just what I'd put in a controller (such as /user/keepalive)
I have an MVC4 Web application which uses Windows Authentication, that is in web.config I have
<authentication mode="Windows" />
And that works fine and everything is ok.
However now I need a controller (an Web API controller in fact) that should be accessed anonymously from a third party component. The problem is that every time I want to invoke this method it requests user credentials.
I tried putting AllowAnonymous attribute to controller and methods but it was not successful.
[AllowAnonymous]
public bool Get(string Called, string Calling, string CallID, int direction)
I checked on both IIS Express and IIS 8 with Anonymous authentication and Windows authentication enabled.
It seems that windows authentication precedes any other authentication and cannot be overridden.
Is there a way to accomplish this?
Add this to your Web.config. Here, my controller is named "WebhookController".
<location path="Webhook">
<system.web>
<authorization>
<allow users="*"/>
</authorization>
</system.web>
</location>
See this KB article for more info.
Edit
- As Erik mentioned below, in MVC applications you should not use web.config <authorization> tags for security. Instead, use [Authorize] attributes. Doing so will allow your [AllowAnonymous] attributes to work correctly. You can read more about this here.
The accepted answer seems to be out of date, so...
In your web.config, remove these lines:
<authorization>
<deny users="?" />
</authorization>
In the solution explorer, click your project, then click f4 (or open the properties explorer). Enable Anonymous Authentication.
Now you're free to use the Authorize and AllowAnonymous Attributes. They're pretty straightforward, Authorize means the user needs to be authorized in order to access the action or controller, AllowAnonymous means the opposite. If an unauthorized user attempts to access a controller or action with the Authorize attribute, they'll be redirected to a login page. If you put Authorize on a controller it applies to all the controller's actions, except ones with AllowAnonymous.
web.config should not be touched as indicated here.
In order to achieve desired result AllowAnonymous and [Authorize] (and maybe some custom authorization attribute, if needed) should be used.
Steps to be performed:
Ensure IIS has both Anonymous Authentication and Windows Authentication configured for the web application / web site
All controllers should use [Authorize] attribute. This can be easily achieved if all inherit from a common controller class (e.g. BaseController / BaseApiController). E.g.:
[Authorize]
public class BaseController : System.Web.Mvc.Controller
{
}
[Authorize]
public class BaseApiController : System.Web.Http.ApiController
{
}
Add [AllowAnonymous] attribute to all actions that are supposed to be anonymous. E.g.:
[RoutePrefix("Api/Anonymous")]
[Authorize]
public class AnonymousController : ApiController
{
[HttpGet]
[Route("GetServiceStatus")]
[AllowAnonymous]
public string GetServiceStatus()
{
return "OK";
}
}
I have an ASP.NET MVC 4 project that's using Windows authentication in the Web.config like so:
<system.web>
<authentication mode="Windows" />
</system.web>
However, if I investigate ServiceSecurityContext.Current from a Controller method, it's null. Shouldn't it contain the authentication info of the user since I'm using Windows authentication?
The reason I'm trying to figure this out is because I would like to know what credentials CredentialCache.DefaultNetworkCredentials is using from a Controller method. From what I gathered by reading the MSDN article on the property, it uses the current security context's credentials... which is null.
Thanks for the help!
The ServiceContext classes is intended to be used inside WCF services. It has nothing to do with ASP.NET MVC.
Trying to use ServiceContext.Current inside an ASP.NET MVC application is like trying to use HttpContext.Current inside a console application => you get NULL.
The reason I'm trying to figure this out is because I would like to
know what credentials CredentialCache.DefaultNetworkCredentials is
using from a Controller method
Then you are looking for the User.Identity.Name property:
[Authorize]
public ActionResult Index()
{
string currentUser = User.Identity.Name;
...
}