Encrypt URL in asp.net - asp.net

My site is in asp.net 3.5 and C#. I am sending link to my user through mail, now I want to send each user a specific URL. So instead of sending the clear text I want to send link with encrypted string URL, which I will decrypt on my home page.
Like instead of www.mysite.aspx\mypage?userId=12 I'll send www.mysite.aspx\mypage?UserId=)#kasd12
and the same I'll decrypt on my page so that I'll get the userId = 12.
Please let me know if my approach is correct and not and how can I encrypt & decrypt the string in simplest and easier manner.

isn't it more appropiate to generate a temporary access key?

Generate a random string value instead of encryption/decryption :) And make it at least 6 or 7 characters long. Store the the value in the database and once the value is received through a query string, run a SQL query to do whatever for the corresponding row :)
Page_Load()
string x = Request.QueryString["UserID"];
SqlCommand x = new SqlCommand("UPDATE UserTable SET UserStatus='Activated' WHERE RandomKey='x'", connection);

I'm pretty sure this code project page is what your after. Its basically a HttpModule that can be used to encrypt querystrings.

Related

Password Digest authentication in WSE3

I was able to implement the method AuthenticateToken and authenticate the user when the given password is in plain text.
Is it possible to authenticate the user when the given password is hashed (Passworddigest)? If so, please shed some light. Thanks in advance.
I found the solution. Yes, it is possible to authenticate the user when the password in SOAP header is PasswordDigest.
No change in the AuthenticateToken implementation; implementation is same (returning the original password string) for both plain text and hashed password.
During debugging, I learnt that the following line in "ComputePasswordDigest(byte[] nonce, DateTime created, string secret)" method from the "Microsoft.Web.Services3.Security.Tokens.UsernameToken" object, was causing the issue to not compute the correct password digest.
byte[] bytes = Encoding.UTF8.GetBytes(XmlConvert.ToString(created.ToUniversalTime(), "yyyy-MM-ddTHH:mm:ssZ"));
I have defined the same method locally and changed the above line as follows to change the format to include milliseconds "yyyy-MM-ddTHH:mm:ss.fffZ".
And implement the "VerifyHashedPassword(UsernameToken token, string authenticatedPassword)" method from the object "Microsoft.Web.Services3.Security.Tokens.UsernameTokenManager" to call my local method instead of "ComputePasswordDigest(byte[] nonce, DateTime created, string secret)" method from "Microsoft.Web.Services3.Security.Tokens.UsernameToken" object. Now, it works like a charm.
byte[] bytes = Encoding.UTF8.GetBytes(XmlConvert.ToString(created.ToUniversalTime(), "yyyy-MM-ddTHH:mm:ss.fffZ"));

Dynamic connString (now stored in session, bad)

I working on a project where the connString is stored in a session variable. The problem is that the session runs out when the user is not around for a while (makes sense), thereby making the user having to log in again to create a new connection.
The user selects his database from a list of ODBC connection configured on the web server, therefore the different connStrings the user can chose from cannot be stored in the web.config as the user can add new ones as they wish.
I was wondering how to fix this problem. Should I just tell the user not to leave his computer for 20mins+ or can I perhaps store the connString someplace else? Ive seen websites making a pop-up saying "your session will expire in 5 mins, press ok to continue using the site", or something like that.
Furthermore it is not a possbility to make a static varible as the website is shared between many users, so if user1 choses "connString1" and user2 choses "connString2" afterwards, then user1 will unfortunatly be running on "connString2" aswell.
Hope you can help :)
**
Can this be a solution?:
I create a "BasePage" which my pages inherit from. In this basepage i create a hiddenfield and add the connString to the value property on load. Furthermore I will encrypt the connString so the user cannot see the value in the source code.
Then, if the session has a timeout, i will restore the session by using the value in the hiddenfield and the site will not crash.
Can you store the user's connection string preference in their Profile and then persist their profile? http://odetocode.com/articles/440.aspx
You should also be able to do this for anonymous users.
As an aside, I don't know how secure the Profile APIs are, they should be fine, but just in case, you might want to store an Enum value and then map that to a Connection string in your code.
You could use the app.config to get and set config files. Take a look at this to see implementation of storing files. Its just as easy to get settings.
ConfigurationManager doesn't save settings
//Edit: If you don't want the user to be able to see your connectionstring name then you can provice an another in hidden_html or cookie or session cookie. In this example I use a cookie. THis should solve your problem.
To set cookie:
HttpCookie myCookie = new HttpCookie("UserSettings");
myCookie["ConnectionString"] = "MyCOnnectionValue";
myCookie.Expires = DateTime.Now.AddDays(1d);//For one day.
Response.Cookies.Add(myCookie);//Will store the cookie within the users browser so your code can read from it at every request.
then:
if (Request.Cookies["UserSettings"] != null)
{
string userSettings;
if (Request.Cookies["UserSettings"]["ConString"] != null)
{ userSettings = Request.Cookies["UserSettings"]["ConString"]; }
}
string connectionStringNameToUse;
if(userSettings =="Connection1"){
connectionStringNameToUse = "here you can have your name of connectionsstring";
}etc with ypur other connectionsstrings here.
//Then use your connectionsstring here:
using (SqlConnection cn = new SqlConnection(ConfigurationManager.ConnectionStrings[connectionStringNameToUse ].ToString()))
{
cn.Open();
using (SqlCommand command = new SqlCommand
("delete TBL from RatingListObjects TBL where ( TBL.TradeObject1Id = #MY_ID ) or ( TBL.TradeObject2Id = #My_ID ) ", cn))
{
command.Parameters.Add(new SqlParameter("#MY_ID", customerToRemove.TradeObjectId));
command.ExecuteNonQuery();
}
}
On the other hand. I would go for saving the users database of choice in with the other user data in the db. But this is doable if you only want the user to have a chosen connectionsstring a certain time, set by the program. It wont allow them to see the connections string name. Hopes this helps, good luck!

Obfuscating a url

I'm working on an asset management website where in whenever an asset is issued to a user the system would send an email notification with a url in it that would show the user all the assets issued to him. I could have used the query string to pass the user ID but again people could abuse it to view assets issued to other users. My client doesn't wants the user to authenticate themselves when they click on the link. So i need something that would hide the parameters being passed in the query string or at least make them obscure. I've read about url encoding, GUID etc. but i'm not sure what to do. I'm just a beginner. Please pardon my ignorance and point me in the right direction.
Taken what you have said, that you're just a beginner, and assuming that this will be public, you can do the easiest way:
Create a new table in your database and called for example tbl_links, as columns just add 3
user_id (foreigner key to the user table)
guid (primary key, unique)
settings (nvarchar(250)
When you need to send an email, create a new row for the user, for example:
Guid guid = Guid.New();
String settings = "date_from:2012/01/01;date_to:2013/01/01";
And insert it one the database, where the link that you put in the email, should have the guid, for example, http://domain.com/info/?g=....
You could append Json to that settings column and parse it into an object again in the code, ask a new question if you want to take this route.
I personally use a security algorithm to pass only the user_id but you did said you're a beginner, so I only showed you the easy and still valid way.
P.S. for security reasons, you should say in the email that your link is only valid for the next 4 hours or so you can prevent people from generating GUIDs in order to try and get some information.... Simple add a create_date column of type datetime and use that to see if the link already expired or not...
For obscuring URL parameters, you want to use a modified Base64 encoding. Please keep in mind that obscurity is not security, and Base64 encoding something does not in any way make anything secure.
If you're intending to use this for authentication purposes, I think you should reconsider. Look into public key encryption and digital signatures as a starting point.
Trying to secure access to a URL is not the right approach. Give the urls away freely and authenticate your users instead.
I would also highly recommend using SSL for serving up this data.
Security through obscurity fails 100% of the time once the obscurity is not longer obscure.
What you can do is to add some prefix and suffix to the id and the encrypt that string. Something like this:
static public string EncodeTo64(string toEncode)
{
byte[] toEncodeAsBytes
= System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode);
string returnValue
= System.Convert.ToBase64String(toEncodeAsBytes);
return returnValue;
}
static public string DecodeFrom64(string encodedData)
{
byte[] encodedDataAsBytes
= System.Convert.FromBase64String(encodedData);
string returnValue =
System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes);
return returnValue;
}
string prefix = "lhdsjñsdgñdfj";
string suffix = "dfknsfñn3ih";
var strToEncode = prefix + "|" + id + "|" + suffix;
var encoded = EncodeTo64(str);
var decoded = DecodeFrom64(encoded).Split('|');
if( decoded.length != 3 || decoded[0] != prefix || decoded[2] != suffix )
throw new InvalidArgumentException("id");
var decodedId = decoded[1];

Sending encrypted text in Url

I have a very simple (rather stupid) question, I hope someone can clear my mind on this :)
I want to send an email to my site user once he clicks a button. This email will contain a link with the userID of a user in the link URL (as query param of a link).
Once the user clicks this email link, my server side code will parse and decrypt the userID query string key to get the user ID and perform some action on it.
I cannot use base64 encoding as it can be reversed and 'hackers' can get to know the real userID. I have to encrypt the ID but when I am using AES alogrithms for encryption, the encrypted text is not "understandable" by the browser, ie I cannot pass the encrypted userId text as a part of the URL because it contains un-encoded characters like "/" which the browser cannot by pass. One option I can think of is to base64 encode the encrypted text once I send it across via URL. Then I can bease64 decode and decyrpt it.
Is this approach better than using Uri.EscapeDataString() on the encyrpted text?
You should continue to base64 encode the AES data, as at that point it is likely binary rather than a string that can be escaped. You should also check that you are using url safe base64 encoding.
Use a one-way hash like SHA1 or MD5, and use JavaScript to send the values as encrypted. Then, if a hacker intercepts the request, they would only have the hashes and not the actual values. They could still send the hashes to login, though; one solution is to include a JavaScript parameter (generated via your server-side language) based on IP (but not possible for a hacker to find the formula for), and use it to salt the username and password hashes.
Then on server-side you would do (in PHP, in this case):
$ipHash = sha1("random" . $_SERVER['REMOTE_ADDR'] . "salt_here10381") // place this as a hidden element in the form and use it in the JavaScript to calculate the hash
$userHash = $_POST['userHash'];
$passwordHash = $_POST['passwordHash']
// TODO: Escape $ipHash, $userHash, $passwordHash
$results = mysqli->query("SELECT * FROM `users` WHERE SHA1(CONCAT('" . $ipHash . "', `user`)) ='$userHash' AND SHA1(CONCAT('" . $ipHash . "', `password`)) = " '$passwordHash'");
Then, if a hacker wanted to login with the hash and username they found, they would need the same IP of the user originally logging in whose credentials were intercepted.
Note that this assumes you have passwords stored in your database as plain-text, which you should never do.
For hashing with SHA1, on client-side, take a look at this.
To answer your specific question (I see I got a bit off topic, oops,) it would be acceptable to base64encode the hashes when you send them to the server. If possible, try to send it as POST data and save it in a cookie or session variable.
I think of a simple solution you try to generate a random number(make it as a key) and for the encryption use some simple technique of yourself like XOR 'ing the ASCII value of the characters in the user name with the key that you have generated .so the long random key results in a greater result.
When creating the email you need to encrypt the user ID, then base64 encode it, then URL encode it. Put this as the userID param in the link.
When decrypting the email you do the same in reverse; get the userID param, URL decode it, base64 decode it then decrypt it.
Remember to use a different intitialisation vector every time you encode a user ID. You will need to put the initialisation vector in the emailed link as a URL parameter too in order to decrypt it.

Issue with sending Base64 encoded query string in aASP.Net

I am creating a web site in .Net 3.5 , I am converting the string into Base64String to send it through querystring. The Response.Redirect works fine for smaller string. But if the original string size is 1670, the response.redirect results in error "Page can not be found".
item is the string in below code snippet.
byte[] data = Encoding.Default.GetBytes(item);
return Convert.ToBase64String(data)
Can any one please help in resolving this?
A query string shouldn't be used for long values - while it depends on the browser and web server exactly what the maximum safe length is, it's certainly not safe above about 2000 characters, and I'd be wary about relying on it above 255. The solution is to use a POST request instead, or possibly to save the data on the server and pass a key to it in the query string.
There is a limit on characters sent as a query string - it varies from browser to browser:
http://support.microsoft.com/kb/q208427/
I'd save it to a DB and retrieve it on the other end with a key.

Resources