HttpModule for encrypting querystrings - c#

i found this great little HttpModule that encrypts and decrypts all querystrings. It can be found here: HttpModule for query string encryption
There is one major flaw that i could really use some input on how to solve. On a postback of the page the HttpMethod POST gets skipped and the QueryString gets shown decrypted. Obviously this is a major security risk.
void context_BeginRequest(object sender, EventArgs e)
{
try
{
HttpContext context = HttpContext.Current;
if (context.Request.Url.OriginalString.Contains("aspx") && context.Request.RawUrl.Contains("?"))
{
string query = ExtractQuery(context.Request.RawUrl);
string path = GetVirtualPath();
if (query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
{
// Decrypts the query string and rewrites the path.
string rawQuery = query.Replace(PARAMETER_NAME, string.Empty);
string decryptedQuery = Decrypt(rawQuery);
context.RewritePath(path, string.Empty, decryptedQuery);
}
else if (context.Request.HttpMethod == "GET")
{
// Encrypt the query string and redirects to the encrypted URL.
// Remove if you don't want all query strings to be encrypted automatically.
string encryptedQuery = Encrypt(query);
context.Response.Redirect(path + encryptedQuery);
}
}
}
catch (ThreadAbortException)
{
//do nothing. let it pass
}
catch (Exception exc)
{
ReportError(exc);
}
}
I tried putting a addition if catch for the POST method:
else if (context.Request.HttpMethod == "POST")
{
if (!query.StartsWith(PARAMETER_NAME, StringComparison.OrdinalIgnoreCase))
{
string encryptedQuery = Encrypt(query);
context.Response.Redirect(path + encryptedQuery);
}
}
However this reloads the page becuase of the Response.Redirect and so the PostBack is useless.
Does anyone have any ideas or know if there is a way to determine is the HttpContext is a PostBack?

Sending sensitive data in the querystring is not a good idea. If you have to then better to encrypt the data before building your querystring rather than encrypting the whole querystring. Also your site should not be compromised by a user changing the querystring. URI takes a user to where he wants to go so navigating by changing your querystring (URI) is a standard for the web. The web should be RestFul.

Related

"Cannot redirect after http headers have been sent", but Response.Redirect doesn't work if I remove RedirectToAction

So I'm trying to recycle some code that was for a 'code behind' patterned .NET app for my MVC app and the Authenticate class they used. How the SignInController's Index method based on the code they gave me is supposed to work is to call an Authenticate class method in the else if which gets a token and redirects back to the Index method at which point since the app now has a token, it goes into the first if conditional and a different method in the aforementioned Authenticate validates the token. Since users will not start out with a token, the else if will always be dove into first.
In order to soothe the "Not all code paths return a value" error I have to add a return statement at the end of the else if clause and an else clause. However, if I return null Index doesn't get redirected to as confirmed by breakpoints. However, if I do return RedirectToAction("Index", "SignIn"); I get an error about "Cannot redirect after HTTP headers have been sent" which I suspect is because the Redirect call from the Authenticate class hasn't been completed yet. However I'm at odds as to how to remedy situation as either return value fails to redirect the web app back to Index...
Original "look behind" styled .NET code that I'm trying to recycle from a colleague's app:
if (string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name) && HttpContext.Current.Request.QueryString["Token"] != null)
{
// we’ve got a token, they must have logged in .. double-check the token
string ssoToken = HttpContext.Current.Request.QueryString["Token"].ToString();
string userRoles = string.Empty;
if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
{
string userName = HttpContext.Current.User.Identity.Name;
((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
RedirectOnSuccess();
}
else
{
RedirectToForbiddenPage();
}
}
else if(string.IsNullOrEmpty(HttpContext.Current.User.Identity.Name))
{
// no user data..go ask them to get SSOToken from service
Authenticate.isUserAuthenticated();
}
My attempt to repurpose it into a MVC styled .NET app:
public ActionResult Index()
{
if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name) && System.Web.HttpContext.Current.Request.QueryString["Token"] != null)
{
// we’ve got a token, they must have logged in ... double-check the token
string ssoToken = System.Web.HttpContext.Current.Request.QueryString["Token"].ToString();
string userRoles = string.Empty;
if (Authenticate.ValidateSSOToken(ssoToken, out userRoles))
{
string userName = System.Web.HttpContext.Current.User.Identity.Name;
//((BaseApplicationPage)(this.Page)).CurrentSecurity.SetUser(userName, "", userRoles);
//RedirectOnSuccess();
// TODO: Not sure what the MVC equivalent would be for commented out code above
return RedirectToAction("Index", "Checklist");
}
else
{
//RedirectToForbiddenPage();
HttpStatusCodeResult(HttpStatusCode.Forbidden);
}
}
else if (string.IsNullOrEmpty(System.Web.HttpContext.Current.User.Identity.Name))
{
// no user data...go ask them to get SSOToken from service
Authenticate.isUserAuthenticated();
return null; // Screwed if I don't return anything because of build error, screwed if I do return something because it messes with the redirect
}
else
{
return null;
}
}
Authenticate class snippet at the end of isUserAuthenticated that gets the token:
//string RedirectURL = GetBaseVirtualDirectory() + "/SignIn/Index";
string RedirectURL = "https://localhost:XXXX1/SignIn/Index";
HttpContext.Current.Response.Redirect(authServiceURL + "/Windows/Auth?RedirectURL=" + RedirectURL, true);
The problem is that your Authenticate.ValidateSSOToken method already called HttpContext.Current.Response.Redirect, which, as error message confirms, added a redirect header (Location) to the response.
You might be able to clear the response before calling RedirectToAction.
But a method called ValidateSSOToke probably should not do any redirects itself. It should return a status and you should do any redirects outside of it based on that status.
And doing all that validation inside your Action is probably not a good practice to begin with.

How to request client cookies on server ASP.NET

I have a javascript function that updates a cookie in the following manner:
aspx page:
function setCookie()
{
//...
document.cookie = "myCookie = HelloWorld";
//...
}
After an asp control triggers an event, the entire page gets sent back from the client. I want to be able to read the value of my cookie. How do I do that?
I've tried:
string temp = Request.ServerVariables["myCookie"].ToString(); but that is the wrong way to do it.
How do I read the client cookie on the server
if(Request.Cookies["userName"] != null)
Label1.Text = Server.HtmlEncode(Request.Cookies["userName"].Value);
Source MSDN
Here is the helper method to retrieve cookie at server side.
public static String GetCookie(String cookieName)
{
try
{
if (HttpContext.Current.Request.Cookies[cookieName] == null)
return String.Empty;
return HttpContext.Current.Request.Cookies[cookieName].Value;
}
catch
{
return String.Empty;
}
}
Usage
var result = GetCookie("myCookie");
If you want to set cookie at client side, look at this Cookie plugin.

ASP.Net Redirect to secure

I am wanting to redirect a page to a secure connection for an ASPX file.
Clients are asked to copy and paste a URL that looks like this foo.com.au into the browser.
I have this code below working on the code behind file but am wondering when it is deployed to production if this will update the URL to have www after the https://www as the URL provided to clients does not have www in it?
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e);
if (!Request.IsLocal && !Request.IsSecureConnection)
{
string redirectUrl = Request.Url.ToString().Replace("http:", "https:");
Response.Redirect(redirectUrl);
}
}
Rather than using Request.Url, use Request.Url.AbsoluteUri. In addition, you should not assume that the URL will be entered in lowercase. I would revise the code to be:
if (!Request.IsLocal && !Request.IsSecureConnection)
{
if (Request.Url.Scheme.Equals(Uri.UriSchemeHttp, StringComparison.InvariantCultureIgnoreCase))
{
string sNonSchemeUrl = Request.Url.AbsoluteUri.Substring(Uri.UriSchemeHttp.Length);
// Ensure www. is prepended if it is missing
if (!sNonSchemeUrl.StartsWith("www", StringComparison.InvariantCultureIgnoreCase)) {
sNonSchemeUrl = "www." + sNonSchemeUrl;
}
string redirectUrl = Uri.UriSchemeHttps + sNonSchemeUrl;
Response.Redirect(redirectUrl);
}
}
If you do this, all it will change is the schema. So, if the absoluteUri is
http://foo.com.au
it will be changed to
https://foo.com.au
One last note: when we have done this, we have never tried it in OnPreInit, we always perform this logic in Page_Load. I am not sure what, if any, ramifications there will be for redirecting at that portion of the page lifecycle, but if you run into issues, you could move it into Page_Load.
This was my final implementation to account for a request comes through for https://foo and not https://www.foo
if (!Request.IsLocal &&
!Request.Url.AbsoluteUri.StartsWith("https://www.", StringComparison.OrdinalIgnoreCase))
{
string translatedUrl;
string nonSchemeUrl = Request.Url.AbsoluteUri;
string stringToReplace = (Request.Url.Scheme == Uri.UriSchemeHttp ? Uri.UriSchemeHttp + "://" : Uri.UriSchemeHttps + "://");
nonSchemeUrl = nonSchemeUrl.Replace(stringToReplace, string.Empty);
if (!nonSchemeUrl.StartsWith("www", StringComparison.InvariantCultureIgnoreCase))nonSchemeUrl = "www." + nonSchemeUrl;
translatedUrl = Uri.UriSchemeHttps + "://" + nonSchemeUrl;
Response.Redirect(nonSchemeUrl);
}

Instagram Login without oAuth

I am trying again to login to instagram, but i have to do this without using their api v2 which uses oAuth for verifying.
The only thing i have is Username and Password to login.
So what i did was looked for the way, instagram application for Android and hopefully IOS does that.
I see that it creates a request at the following url:
https://instagr.am/api/v1/accounts/login/
If you would visit that link directly, you will more likely get a error saying that the page couldn't be find. After a little bit of googling, i came across a 2 years old post which states that in the Useragent, we have to contain the string "Instagram" for it to work.
I did that by faking the useragent and the result is as follows:
{"status":"fail","message":"Your version of Instagram is out of date. Please upgrade your app in the Play Store to log in to Instagram."}
Now, i am guessing that we also need to add something else or some other headers too, so i was looking for a way to grab the request being sended to instagram by either of their Android or IOS app.
So next i downloaded Bluestack and installed and ran instagram on my computer using this. I was able to install and login it successfully, but then i was unable to log it using Charles since the request is being sent to https:// server
I also tried to grab it through Wireshark but unfortuantely, i am not much experienced in using it and hence don't know it purpose.
So could anyone help me to get how to login to instagram with C# without using oAuth, cuz i just have username and password.
I would probably code the end part of requesting myself, but i am unable to capture the headers being sent to instagram.
Also, if there is anything like Charles/Wireshark which captures network traffic for Android, do let me know about it too.
You should be able to capture the request and see the request headers using Fiddler if you can tell your device to use your pcs internet connection by going through USB. It seems your getting close but might just need a version number somewhere in your request.
Yeah you can do this using Webview
Here you go
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
view.loadUrl(url);
UrlQuerySanitizer.ValueSanitizer sanitizer = UrlQuerySanitizer.getAllButNulLegal();
// remember to decide if you want the first or last parameter with the same name
// If you want the first call setPreferFirstRepeatedParameter(true);
sanitizer.sanitize(url);
String value = sanitizer.sanitize("username"); // get your value
if(MyBridge.getUsername()!=null)username = MyBridge.getUsername();
return true;
}
#Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
super.onPageStarted(view, url, favicon);
// showLoading();
CookieManager.getInstance().removeAllCookies(null);
// CookieManager.getInstance().flush();
progressBar.setVisibility(View.VISIBLE);
}
#Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
progressBar.setVisibility(View.GONE);
if (url.equalsIgnoreCase(mURL)) {
view.addJavascriptInterface(new MyBridge(InstagramOfficalLoginActivity.this), "bridge");
String javascript = "javascript: document.getElementsByClassName(\"_0mzm- sqdOP L3NKy \")[0].onclick = function() {\n" +
" var username = document.getElementsByName(\"username\").value;\n" +
" var password = document.getElementsByName(\"password\").value;\n" +
" bridge.saveData(username, password);\n" +
" };";
view.loadUrl(javascript);
}
if (isSessionid ) {
// username = MyBridge.getUsername();
//сохранение данных пользователя
Logins logins = new Logins();
logins.setUserId(InstaUtils.getUserId());
logins.setUserName("");
logins.setProfilePic("");
logins.setSession_id(InstaUtils.getSessionid());
logins.setCooki(InstaUtils.getCookies());
logins.setCsrf(InstaUtils.getCsrf());
long id = DataObjectRepositry.dataObjectRepositry.addNewUser(logins);
PreferencesManager.savePref(GlobalConstant.USERNAME,username);
PreferencesManager.savePref(GlobalConstant.USER_ID, InstaUtils.getUserId());
PreferencesManager.savePref(GlobalConstant.TOKEN, InstaUtils.getSessionid());
PreferencesManager.savePref(GlobalConstant.PROFILE_PIC,"");
Intent intent = new Intent(InstagramOfficalLoginActivity.this, MainActivity.class);
PreferencesManager.savePref("isLogin",true);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
intent.putExtra("user", InstaUtils.getUserId());
intent.putExtra("database_id",String.valueOf(id));
mWebView.destroy();
mWebView = null;
startActivity(intent);
}
}
#Override
public void onLoadResource(WebView view, String url) {
super.onLoadResource(view, url);
progressBar.setVisibility(View.GONE);
cookies = CookieManager.getInstance().getCookie(url);
try {
String session_id = getCookie(url, "sessionid");
String csrftoken = getCookie(url, "csrftoken");
String userid = getCookie(url, "ds_user_id");
if (session_id != null && csrftoken != null && userid != null) {
isSessionid = true;
InstaUtils.setSessionId(session_id);
InstaUtils.setUserId(userid);
InstaUtils.setCookies(cookies);
InstaUtils.setCsrf(csrftoken, cookies);
}
}catch (Exception e){
e.printStackTrace();
}
}
#SuppressWarnings("deprecation")
#Override
public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
ToastUtils.ErrorToast(InstagramOfficalLoginActivity.this, description);
}
#TargetApi(android.os.Build.VERSION_CODES.M)
#Override
public void onReceivedError(WebView view, WebResourceRequest req, WebResourceError rerr) {
// Redirect to deprecated method, so you can use it in all SDK versions
onReceivedError(view, rerr.getErrorCode(), rerr.getDescription().toString(), req.getUrl().toString());
}
});
mWebView.loadUrl(mURL);
You can also download fully working code from my github profile Here is the link.
I hope it work,Thanks :)
you can always login through https://instagram.com/accounts/login/ having only login\password.
having ability to sniff traffic will not help you, as they sign all their messages now to prevent things you are trying to achieve.
You can find Instaguser library at here. https://github.com/ThinhVu/InstagramUser
Instaguser allow you login into instagram without OAuth.
At the moment, you can change user information: username, biography, ... etc.

When is Application_BeginRequest invoked in parent site

I have this senario where my site www.skinb5.com should redirect to www.skinb5.com/au/
and www.skinb5.com/au should directly go to the www.skinb5.com/au and www.skinb5.com/us
should go to www.skinb5.com/us.
www.skinb5.com is a parent site which pretty much does nothin but to redirect. /au/ and /us/ are child sites sitting under it.
Please have a look at my Global.asax file in my parent site where the only redirect happens.
The problem is when i go www.skinb5.com/us/ it returns 200 which is good. But
www.skinb5.com/au/ it returns 302 to www.skinb5.com/au/. Though it doesn't go in an infinite loop, I am concerned why it returns 302.
you might want to test here at http://www.internetofficer.com/seo-tool/redirect-check/
My questions is, when I invoke www.skinb5.com/au/ directly, will the application_beginRequest in parentsite be invoked? Shouldn't it directly go to the child site? If so how does the 302 redirect happen.
protected void Application_BeginRequest(object sender, EventArgs e)
{
var redirectSite = "au";
HttpCookie languageCookie = HttpContext.Current.Request.Cookies.Get("Customer.SelectLanguageID");
if (languageCookie != null)
{
redirectSite = languageCookie.Value.Split('-')[1];
}
string rawUrl = HttpContext.Current.Request.RawUrl;
if (string.IsNullOrEmpty(rawUrl))
{
rawUrl = "/";
}
rawUrl = redirectSite + rawUrl;
bool useSsl = IsCurrentConnectionSecured();
var storeHost = GetStoreHost(useSsl);
if (storeHost.EndsWith("/"))
storeHost = storeHost.Substring(0, storeHost.Length - 1);
string url = storeHost + '/' + rawUrl;
url = url.ToLowerInvariant();
HttpContext.Current.Response.Redirect(url, true);
HttpContext.Current.Response.End();
}
A redirect tells the browser to load a different URL. The browser does this just as though the new URL was typed in the address bar. It is a request like any other.
So all requests and redirects will cause Application_BeginRequest() to fire.
If you don't want it to do anything on the redirected request, you'll need to test the target URL and decide if any action is to be taken.

Categories