Encrypting connection strings causes App Pool to stop - asp.net

I want to encrypt my connection strings when I first run my code. I call the code below from the Global.asax.
When I try this on my machine, the connectionstrings are encrypted, but when I place this on the server it causes the app pool to stop. I can't really tell why this happens because the connection is reset.
Is this a problem with the write settings of a file? How can I make this work on the web server?
var config = WebConfigurationManager.OpenWebConfiguration("~");
var section = config.GetSection("connectionStrings") as ConnectionStringsSection;
if (section == null)
{
return;
}
if (section.SectionInformation.IsProtected)
{
return;
}
section.SectionInformation.ProtectSection("DataProtectionConfigurationProvider");
config.Save();

I know this is an old question but I just now ran across it.
If you encrypted the connection strings in the web.config on your local machine before copying the web.config file over to your web server, then I'm assuming that's the problem. Unless both machines are using the same IIS RSA key (which I'm not even sure is possible and it's probably unlikely), the destination machine won't be able to decrypt the connection string cipher because it was encoded with the source machine's key.
Therefore, you must encrypt the web.config settings from the target machine itself.
By the way, I got confused by your comments under the question. Invoking the config.Save() method will modify the web.config file, even if the content didn't change. In the example code above, the content should have changed anyway because you encrypted the connectionStrings section before saving. In order for IIS to utilize an updated web.config, it has to recycle its application pool first. This is partly why, by default, IIS automatically recycles the associated app pool when it detects a web.config change.

Related

ASP.NET_SessionId cookie disappearing between request on a specific server

I have differing behavior between a test server and a dev server - on my dev server everything works fine but on the test server the ASP.NET_SessionId cookie disappears after a flow of events and hence so does the servers session. Testing was done in the same browser on the same machine & the code bases are virtually identical. The only significant difference is that the pages are being served from two different pcs.
The flow of pages (all https) that causes this is such:
Load page from domain A that contains an iframe (session cookie exists at this point).
Domain B is loaded into the iframe.
A second page from domain B is loaded into the iframe triggered from the first page.
The second page does a form post to back to domain A where the session cookie is now absent.
EDIT
Forgot to say - we're using SqlInMemoryProvider as our session state.
You could share the session state between two servers using the below ways:
1)Using SQLServer Session:
In this mode of session state, the session objects are stored into SQL Server.
The benefit of using this technique is that all the data in the session will be stored together in a different location or you can say a centralized location in SQL Server, to get it working we just need to configure the SQLServer to store session data.
2)Using the StateServer Session:
In this mode of session state, the session objects are stored in a separate server handled by a Windows Service running on that server.
The benefit of using this technique is that all the data in the session will be stored together in a different location. In this case, the server to be handled by the Windows Service is named "aspnet_state"; this will become the centralized location for session data. To get it working we just need to configure the StateServer to store Session data.
when you share the session state between two servers make sure ASP.NET state service is installed on all the servers and the settings are as below:
Also, the service cannot be accessed remotely by default. To enable that option you need to set the value of the following registry key to 1: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters\AllowRemoteConnection. Don’t forget to restart the asp.net state service after the registry key change.
You need to declare the session management options within the system.web node. Example:
<sessionState mode="StateServer" stateConnectionString="tcpip=machinename:42424">
</sessionState>
If you want to use the SQL Server type then this section may look like the following:
<sessionState mode="SQLServer" allowCustomSqlDatabase="true"sqlConnectionString="the connection string name to the server">
</sessionState>
Where SQL connection string refers to the name of the connection string in the connectionStrings section of web.config which holds the details of the state table. The connection string itself may take up the following format:
<add name="ASPStateConnectionString" connectionString="Data Source=[DB machine name where state DB is stored];Initial Catalog=ASPState;User ID=[db admin user name];Password=[db admin password]"providerName="System.Data.SqlClient" />
we also need to add a machine and a validation key within the system.web node, that may look something like this:
<machineKey
validationKey="some long hashed value"
decryptionKey="another long hashed value"
validation="SHA1"/>
The default setting for the validation key is AutoGenerate which does exactly what the name applies: the key will be generated automatically by IIS. The default generation mode for the decryption key is IsolateApps. It generates a unique key for each application by using the application ID.
We need this common machine key as we want to run this on several machines so we don’t want the machine key to be automatically generated.
For more information you could refer this below links:
https://dotnetcodr.com/2013/07/01/web-farms-in-net-and-iis-part-5-session-state-management/
https://www.c-sharpcorner.com/UploadFile/25c78a/load-balancing-session-state-configuration/
It's because cookies are not stored if domains are different.
It's treated as 3rd party cookies.
You need to use same domain as parent site to iframe site.
Or else you need to use cookieless session.
I have recently gone through this problem and come across the concept of cross-site cookies. If you want to share and use the cookie across the different domains then you have to set your cookie samesite attribute to None (SameSite=None). It must be secure otherwise it will be ignored and not send back to the server by browser (Chrome). To use a secure tag for your cookie you have to enable the HTTPS for your website.
For more detail you visit: https://web.dev/samesite-cookies-explained/

Azure App Service Connection string settings not available custom Session provider

I added all my connection strings to the App Service -> Settings screen.
I'm using Redis to share Sessions between the different instances. Everything is good if I have the connection in the ConnectionString section in the web.config but if I remove it from there and just add it to the Connection string section under the settings screen then it all breaks.
I'm running a classic .net web application on .net 4.7
I've tried the following so far:
Added a connection string in web.config without a value hoping it will overwrite it
Completely removed the connection strings in the web.config file.
Just for a test, I added an extra connection string which I can later retrieve and show on a web page.
How early do the connection strings from azure get applied? Is there a workaround or is this a known issue (haven't managed to find anything about it)?
EDIT: Here is a sample of what I'm trying to do.
I have a connection string called <add name="redis.sessions" value=""/> and a session state provider that points to that connection string
<add name="redis" type="Sitecore.SessionProvider.Redis.RedisSessionStateProvider, Sitecore.SessionProvider.Redis" applicationName="private" connectionString="redis.sessions" pollingInterval="2"/> and in the session provider on Initialization it tries to initialise the Redis connection with a blank connection string. Even through one has been provided in the App Service Settings.

asp.net pages work, but classic asp gives access denied error

I am setting up an existing application on a new server. It is a mix of Asp.Net and Classic Asp pages. The asp.net pages work perfectly, but the classic asp pages give the following error:
[DBNETLIB][ConnectionOpen (Connect()).]SQL Server does not exist or
access denied.
My Settings:
Windows Server 2008 x64
IIS7
SQL 2008 Express with Advanced Services
32bit application
Here are some things I've tried:
Set IIS7 AppPool to enable 32-bit applications
Enabled "Active Server Pages" extension in IIS "ISAPI and CGI Restrictions"
Installed Frontpage 2002 Extensions for IIS7 (from RTR)
Enabled Named Pipes protocol in SQL Config Mgr
My Connection String:
connectionString="Data Source=(local);Initial Catalog=System;Persist Security Info=True;User ID=System;Password=mypassword" providerName="System.Data.SqlClient"
My CLICONFG Alias:
Server Alias = System
Network Library = Named Pipes
Connection Parameters = (local)
I've successfully installed the program in this environment before without any issues. Both *.asp and asp.net are using the same connection string, so I can't see how that is a problem. The User "System" specified in the Connection String is setup as a user in SQL with all permissions granted.
Please help!! I've spent over 3 days on this.
Thanks!
I'm not so sure that classic asp understands all the parameters in your connection string. It likely ignores something it doesn't understand but the on that I think it's having the greatest trouble with is this one:
Data Source=(local)
and possibly
providerName="System.Data.SqlClient"
I would try either:
Creating a second connection string and use one for classic ASP and the other for aspx. Use this 'simple' format for classic asp:
Server=myServerAddress;Database=myDataBase;User Id=myUsername;Password=myPassword;
Change the Data Source parameter to use the actual server or instance name.
System.Data.SqlClient is a data provider for asp.net, it wouldn't work with classic asp.
Here's an example of a Classic ASP connection string for SQL Server
Provider=sqloledb;Data Source=yourServerAddress;Initial Catalog=yourDataBase;User Id=yourUserid;Password=yourPwd;
For more examples see here - look at oledb providers.
http://www.connectionstrings.com/sql-server/
Also, where are you putting your connection string? If it's in web.config then .net will be able to read it but Classic ASP won't. It needs to go in the page which wants to connect itself, in an include or in global.asa
Edit - one extra point. If you're using SQL Server Express then you need to specify this - eg:
Data Source=localhost\SQLEXPRESS
Shawnda, John and Evan make good suggestions and points.
I'll share my active live server configurations with you so you have something to test on your server. That's if you're running MSSQL on IIS 7.x and Windows 2008 Server with any flavor of SQL Server 2008.
I run 2 servers mixed .Net and ASP one Web 2008 and 2008 R2 with IIS .Net sites with ASP using a common db all sites mixed work just fine.
First tip, make your connection string a Call Function or Sub.
From what you said you have to find all the locations you have your connection string.
How we migrate will help you.
Create your function and place it into your SQL Included pages or your master scripts page that is included in all pages that need your connection string.
Function ConnOpen(SqlConn)
Dim strConnSql
Set SqlConn = Server.CreateObject("ADODB.Connection")
strConnSql = "Provider=SQLNCLI10;Server=SERVERNAME\SQLEXPRESS;Database=DBNAME;UID=USER;PWD=PASSWORD;"
SqlConn.Open strConnSql
End Function
Function ConnClose(SqlConn)
SqlConn.Close
Set SqlConn = Nothing
End Function
Follow what has been suggested and change the string.
This is how I migrate sites from databases.
I will add a new connection string as a function and test it on one of my pages.
If the new connection works I'll do a search and replace of the string.
Once you figure out which connection string works you're going to stop spending time like 3 days.
The string above is active on my .Net sites in my inc_sqlpage.asp which is included in all pages that require database connection.
You should find all your connection strings and remove and replace them with a easier to manage function.
Call ConnOpen(MyConn)
... 'your SQL
Call ConnClose(MyConn)
If after this method you still can't connect then I'll say it's your server naming or firewall if this is a new server.
Example: I do not use IP address connections only internal DNS machine names. If i changed the servername to IP I would see the same type of error.
I'm sure you have tried different settings but try the one above switching IP with Machine Name, .\ and localhost but not (local).
I found the solution!!!
Thanks everyone for your assistance. I finally found the solution!
Turns out the connection string for my classic asp pages were expecting SQL to be installed with the default instance....but I had done a named instance. The connection string had "Data Source = System" (System was an alias setup on the computer that only specified (local) as the connection....it did not specify the instance name.).
I changed the connection string to "Data Source = .\SQLEXPRESS" and it worked fine.
The connection string that was in there would have worked fine if I had selected "Default Instance" during the installation....as had been done on other servers I had installed.
Thanks again!

ASP PasswordRecovery Email Failure, DateTime precision

I have an asp.net 4.0 website and I'm using the PasswordRecovery control for a forgot password form. When I run the site locally it works fine, emails are sent. However, when I run the site from my vps, I get an error message when trying to send the email. There's nothing in the server's event log.
My PasswordRecovery aspx code is as follows:
<asp:PasswordRecovery ID="PasswordRecovery1" runat="server"
CssClass="mediumText">
<MailDefinition From="noreply#x.com" BodyFileName="~/EmailTemplates/PasswordRecovery.txt" />
My web.config mail settings are as follows:
<system.net>
<mailSettings>
<smtp from="noreply#x.com">
<network host="smtp.123-reg.co.uk" password="x" userName="x" />
</smtp>
</mailSettings>
</system.net>
I've now run SQL Profiler against the SQL Server Express Instance, and it turns out that an exception is being thrown from the SQL Server on the call to dbo.aspnet_Membership_GetUserByName. There's a type conversion issue because PasswordRecovery is passing a DateTime parameter with 7 decimal places for the seconds. If I manually execute the stored procedure with 3 decimal place,s then it works. Does anyone know why the precision of the DateTime parameter is different on my server than on my laptop?
As you will see from reading this issue and the subsequent responses, the DateTime precision issue you are seeing is just a result of SQL Profiler displaying the date with the wrong format. That issue is unrelated to what is preventing your email from being sent.
What is the error message you receive when you try to send the email? The issue is more than likely related to something preventing your email from making it to the SMTP server. Are you sending to the same SMTP using the same credentials from your machine?
I think it is some connectivity issue from your VPS to SMTP server.
You can test this outside of your code by trying to connect to SMTP server using telnet.
Follow the steps mentioned in the link below to
http://support.microsoft.com/kb/323350
The datetime conversion error is a red herring. That is only occuring when you copy it from the profiler and execute it in management studio. This is a known issue.
You might want to read this:
http://forums.asp.net/t/1398826.aspx/1
Sounds like it might simply be that the membership provider settings are different with regards to the passwords.
There are two possibilities that I see.
You don't have a machineKey defined in your web.config AND your local and VPS instance are both pointing to the same database. If this is true, put a machineKey in your config and regen your passwords.
Your membership provider config on the VPS used to be configured for hashed passwords and somewhere along the way was changed to encrypted passwords. (or vice versa). This would also cause issues.

<machineKey decryptionKey="AutoGenerate"... being ignored by IIS. Won't invalidate previous session's cookies

(See question below for more context):
Are there any situations in which
<machineKey
validationKey="AutoGenerate,IsolateApps"
decryptionKey="AutoGenerate,IsolateApps"/>
in web.config would fail to AutoGenerate a new machineKey on App Pool recycle? This is the behavior I'm seeing...
I'm using standard ASP.NET FormsAuthentication in an MVC app. If I log a user in using FormsAuthentication.GetAuthCookie and don't use a persistent cookie (relying on the browser's session to remember my authorized state), I would expect recycling the IIS App Pool to invalidate the session's knowledge of this cookie...and thus logout all users who don't have persistent cookies.
This DOES happen on one of my IIS installs (XP), but on a different IIS configuration (Server 2K3) the FormsAuthentication cookie (under the standard name ".ASPXAUTH") remains valid and continues to authorize the user.
Does anyone know why this is happening or what configuration controls this behavior?
Obviously recycling the app pool has no control over whether or not the browser still sends the .ASPXAUTH cookie (as long as I haven't closed my browser and the cookie hasn't expired).
In the case of the IIS install that properly denies authentication after a recycle, I can see the incoming cookie in Request.Cookies during the Application_BeginRequest event...but once control moves to the next event available in Global.asax.cs (Application_AuthenticateRequest), the cookie has been removed from the Request.Cookies collection.
Why does this not happen for both IIS/ASP.NET configurations?
In case this isn't clear, a simpler way of forming the question is:
Why does HttpContext.Current.Request.Cookies[".ASPXAUTH"] change from {System.Web.HttpCookie} to null when I step, in a single request, from Application_BeginRequest to Application_AuthenticateRequest?
More debugging information:
If I attach the following code to Global.asax.cs's FormsAuthentication_OnAuthenticate event...
var cookie = Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
var val = cookie.Value;
try
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(val);
}
catch (Exception)
{
}
}
...then during a request before I recycle the IIS App Pool, no exception will be caught. After recycling the IIS App Pool, when the exact same .ASPXAUTH cookie is sent from the browser, a Cryptographic exception is caught ("Padding is invalid and cannot be removed.")
Why is this?
Our application is stateless (no session required), yet we had a situation where an app pool recycle caused invalidation of all machinekey-encrypted cookies on a server environment (above described issue). This was caused because the machinekey changes with every recycle, which should not be the case.
The AutoGenerate modifier specifies that ASP.NET generates a random key and stores it in the Local Security Authority (LSA)
https://msdn.microsoft.com/en-us/library/w8h3skw9%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
"Local Security Authority (LSA)" means the user assigned to app pool, see below for more details as this turned out to be the problem.
The issue lied in the fact that we are using a dedicated user account for running the application pool, and simply creating the user and then assigning it to the app pool did not seem to trigger the creation of the registry section where the machine key is then stored. You can verify this yourself by checking registry
HKLM/SOFTWARE/Microsoft/Windows NT/CurrentVersion/ProfileList (for getting the SID of the user you just created; if the user is not there, then this is already a bad sign)
HKU/[UserSIDFromBefore]/Software/Microsoft/ASP.NET/... (a machine key should be stored there)
The solution was to logon as that user once on the computer (normal Windows logon screen) so that the relevant registry sections are created. There might be quicker or more subtle ways to establish the registry sections though.
Internet Information Services (IIS) 7.0 (Windows Vista, Windows Server 2008) introduced application pool identity, a new isolation mechanism that helps provide increased security for servers that run ASP.NET applications. However, sites that are running under the application pool identity do not have access to the HKCU registry. This is where the ASP.NET runtime stores its auto-generated keys. The result is that ASP.NET cannot persist the auto-generated key when the application pool is reset. Therefore, every time w3wp.exe is reset, a new temporary key is generated.
Note This is not an issue in IIS 7.5 (Windows 7, Windows Server 2008 R2) and later versions. On these versions of IIS, ASP.NET can persist its auto-generated keys in a different location that survives application pool resets.
https://support.microsoft.com/en-us/help/2915218/resolving-view-state-message-authentication-code-mac-errors
Forms Authentication cookies have nothing to do with Session state.

Resources