I have a base page in my asp.net application where where am setting _antiXsrfTokenValue like below.
const string ViewStateFieldName = "__VIEWSTATEKEY";
private const string AntiXsrfTokenKey = "__AntiXsrfToken";
private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
private string _antiXsrfTokenValue;
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
if (this.IsViewStateEnabled)
{
if (requestCookie != null && requestCookieGuidValue != Guid.Empty)
{
// Use the Anti-XSRF token from the cookie
_antiXsrfTokenValue = requestCookie.Value;
Page.ViewStateUserKey = _antiXsrfTokenValue;
}
else
{
// Generate a new Anti-XSRF token and save to the cookie
_antiXsrfTokenValue = Guid.NewGuid().ToString("N");
Page.ViewStateUserKey = _antiXsrfTokenValue;
var responseCookie = new HttpCookie(AntiXsrfTokenKey)
{
HttpOnly = true,
Value = _antiXsrfTokenValue
};
}
}
}
I'm also setting the user name in Page_PreLoad like below.
protected void Page_PreLoad(object sender, EventArgs e)
{
// this check is required because when user come from MTS then CUser is null, so get user identity
string userName;
if (CUser.Current == null)
{
userName = string.Empty;
if (Request.IsAuthenticated)
{
var userClaims = User.Identity as System.Security.Claims.ClaimsIdentity;
userName = userClaims?.FindFirst("preferred_username")?.Value;
}
}
else
{
userName = CUser.Current.UserName;
}
if (ViewState != null && Context != null && userName != string.Empty)
{
if (!IsPostBack)
{
if (Page != null)
{
// Set Anti-XSRF token
ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey ?? "";
ViewState[AntiXsrfUserNameKey] = userName;
}
}
else
{
// Validate the Anti-XSRF token
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != userName)
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
}
}
}
So with the code samples above, does any one know how i can do the below C# check in javascript?
// Validate the Anti-XSRF token
//I need to do the below check in Javascript.
if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
|| (string)ViewState[AntiXsrfUserNameKey] != userName)
{
throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
}
Related
This is a simple function that use AJAX and get information about an image in the database with id=219 when a button is clicked
Anyone loading this webpage can change the javascript code by going to the source code.
Then by clicking the button he will run the modified code (like changing image_id from 219 to 300). So he can get information about any image just by changing image_id
The question is how to protect against that client-side attack or XSS ?
function clicked () {
var xhttp = new XMLHttpRequest () ;
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200){
var obj = JSON.parse (this.responseText);
alert (obj.description);
}
};
xhttp.open ("POST","get_title_description.php", true);
xhttp.setRequestHeader ("Content-type", "application/x-www-form-urlencoded");
xhttp.send ("image_id=219") ;
}
You can use something like this for generating and validating the cookie:
define('COOKIE_TOKEN', 'my_token');
class BaseAuth
{
protected $uid;
private static function base64url_encode(string $s): string
{
return strtr($s,'+/=','-|_');
}
private static function base64url_decode(string $s): string
{
return strtr($s,'-|_','+/=');
}
// Encodes after encryption to ensure encrypted characters are URL-safe
protected function token_encode(String $string): string
{
$iv_size = openssl_cipher_iv_length(TYPE_CRYPT);
$iv = openssl_random_pseudo_bytes($iv_size);
$encrypted_string = #openssl_encrypt($string, TYPE_CRYPT, SALT, 0, $iv);
// Return initialization vector + encrypted string
// We'll need the $iv when decoding.
return self::base64url_encode($encrypted_string).'!'.self::base64url_encode(base64_encode($iv));
}
// Decodes from URL-safe before decryption
protected function token_decode(String $string): string
{
// Extract the initialization vector from the encrypted string.
list($encrypted_string, $iv) = explode('!', $string);
$string = #openssl_decrypt(self::base64url_decode($encrypted_string), TYPE_CRYPT, SALT, 0, base64_decode(self::base64url_decode($iv)));
return $string;
}
// performs log-out
public function clear_cookie()
{
setcookie(COOKIE_TOKEN, '', time() - 300, '/api', '', FALSE, TRUE); // non-secure; HTTP-only
}
private function userIP(): string
{
return $_SERVER['REMOTE_ADDR'];
}
// validates Login token
public function authorized(): bool
{
if(isset($_COOKIE[COOKIE_TOKEN]))
{
$stamp = time();
$text = $this->token_decode($_COOKIE[COOKIE_TOKEN]);
if($text != '')
{
$json = json_decode($text,TRUE);
if(json_last_error() == JSON_ERROR_NONE)
{
if($json['at'] <= $stamp AND $json['exp'] > $stamp AND $json['ip'] == $this->userIP() AND $json['id'] != 0)
{
// check if user account is still active
$res = $db->query("SELECT id,active,last_update,last_update > '".$json['last']."'::timestamptz AS expired FROM account WHERE id = ".$json['id']);
$info = $db->fetch_assoc($res);
if($info['active'] != 0)
{
if($info['expired'] == 0)
{
// extend the token lifetime
$this->sendToken($info);
$this->uid = $json['id'];
return TRUE;
}
}
}
}
}
$this->clear_cookie();
}
return FALSE;
}
public function login(String $username, String $password): bool
{
$stm = $db-prepare("SELECT id,user_name AS username,user_pass,full_name,active,last_update,COALESCE(blocked_until,NOW()) > NOW() AS blocked
FROM account WHERE user_name = :user");
$res = $stm->execute(array('user' => strtolower($json['username'])));
if($res->rowCount())
{
$info = $db->fetch_assoc($res);
if($info['active'] == 0)
{
// Account is disabled
return FALSE;
}
elseif($info['blocked'] != 0)
{
// Blocked for 5 minutes - too many wrong passwords
// extend the blocking
$db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
return FALSE;
}
elseif(!password_verify($password, $info['user_pass']))
{
// Wrong password OR username
// block account
$db->query("UPDATE account SET blocked_until = NOW() + INTERVAL 5 minute WHERE id = ".$info['id']);
return FALSE;
}
else
{
unset($info['user_pass']);
unset($info['blocked']);
$this->sendToken($info);
return TRUE;
}
}
}
}
If you do not need to authenticate and authorize your users and just need random unpredictable image IDs - you can simply use UUIDs.
I have a volley StringRequest in my MainActivity like this
StringRequest strReq = new StringRequest(Method.POST,
G.serverLevelAdress, new Listener<String>() {
#Override
public void onResponse(String response) {
// TODO Auto-generated method stub
Log.e(TAG, "Response to get All Online Users \n "
+ response);
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
// TODO Auto-generated method stub
if (error.getMessage() != null)
Log.e(TAG, TAG + ": " + error.getMessage());
try {
G.showToast(activity.getResources().getString(
R.string.network_error));
} catch (Exception e) {
// TODO: handle exception
}
}
}) {
#Override
protected Map<String, String> getParams() {
// Posting params to register url
Map<String, String> params = new HashMap<String, String>();
params.put("tag", "getAllOnlineUsers");
params.put("email", email);
return params;
}
};
G.getInstance().addToRequestQueue(strReq, tag_string_req);
In local host, everything works fine and I would easily call a local server. This is my php code to request and returns its response :
<?php
if (isset($_POST['tag']) && $_POST['tag'] != '') {
// get tag
$tag = $_POST['tag'];
// include db handler
require_once 'DB_Functions.php';
$db = new DB_Functions();
// response Array
$response = array("tag" => $tag, "error" => FALSE);
// check for tag type
if ($tag == 'login') {
// Request type is check Login
$email = $_POST['email'];
$password = $_POST['password'];
// check for user
$user = $db->getUserByEmailAndPassword($email, $password);
if ($user != false) {
// user found
$response["error"] = FALSE;
$response["uid"] = $user["user_unique_id"];
$response["user"]["name"] = $user["name"];
$response["user"]["email"] = $user["email"];
$response["user"]["created_at"] = $user["created_at"];
$response["user"]["updated_at"] = $user["updated_at"];
$response["user"]["paycard"] = $user["paycard"];
$response["user"]["phone"] = $user["phone"];
$response["user"]["real_name"] = $user["real_name"];
$response["user"]["role"] = $user["role"];
echo json_encode($response);
} else {
// user not found
// echo json with error = 1
$response["error"] = TRUE;
$response["error_msg"] = "Incorrect email or password!";
echo json_encode($response);
}
} else {
$response["error"] = TRUE;
$response["error_msg"] = "Required parameter 'tag' is missinggg!";
echo json_encode($response);
}
?>
The problem is when the code I loaded on the online host I receive this message as an response :
<noscript>This site requires Javascript to work, please enable Javascript in your browser or use a browser with Javascript support</noscript>
Where is the problem? How can I disable Javascript through activity I send my request?
Infinitely thank you for your attention.
There is a server from which I consume web services (https://example.com/zzzzzz/rest/services/)
If I just paste this in Chrome, I'm prompted to authenticate. I put my known credentials and them I'm free to roam around.
However, if I try to access something like :
https://example.com/zzzzzz/rest/services/tttttt/uuuuuu/MapServer
in Javascript with XMLHttpRequest, I get a 401 Unauthorized response every time. It works if I add a header to this request with my credentials:
xml_req.setRequestHeader("Authorization", "Basic " + btoa("username:password");
However, this would mean to expose that username and password in every JS code and also add a header to each XMLHttpRequest (which I cannot do at this point).
The above server is not mine, so I cannot do anything to it other than consume services after I login.
Is there a way I can get my own server (IIS) to handle this authentication for me whenever I try to access those services?
Extra info : This is all for an ArcGIS server.
I found the solution.
The idea is to create a webservice (ashx in my case) which gets the requested service to be proxied as a parameter (myproxy.com?https://websitetobeproxied.com/serviceToBeProxied), sends it to the proxied server along with the credentials (using network credentials), fetches the result and sends it back to the client.
This would be the http request function which passes the credentials :
private System.Net.WebResponse doHTTPRequest(string uri, byte[] bytes, string method, string contentType, ServerUrl serverUrl) {
System.Net.HttpWebRequest req = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(uri);
req.ServicePoint.Expect100Continue = false;
// Add credentials
req.Credentials = new NetworkCredential("username", "password");
//For testing I automatically validate any ssl certificates. You may want to disable this in production
req.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => {
return true;
};
//Get the request method ("GET", "SET" etc.)
req.Method = method;
if (bytes != null && bytes.Length > 0 || method == "POST") {
req.Method = "POST";
req.ContentType = string.IsNullOrEmpty(contentType) ? "application/x-www-form-urlencoded" : contentType;
if (bytes != null && bytes.Length > 0)
req.ContentLength = bytes.Length;
using (Stream outputStream = req.GetRequestStream()) {
outputStream.Write(bytes, 0, bytes.Length);
}
}
return req.GetResponse();
}
And this would be the method to fetch and send the result back :
private bool fetchAndPassBackToClient(System.Net.WebResponse serverResponse, HttpResponse clientResponse, bool ignoreAuthenticationErrors)
{
if (serverResponse != null)
{
clientResponse.ContentType = serverResponse.ContentType;
using (Stream byteStream = serverResponse.GetResponseStream())
{
// Text
if (serverResponse.ContentType.Contains("text") ||
serverResponse.ContentType.Contains("json") ||
serverResponse.ContentType.Contains("xml"))
{
using (StreamReader sr = new StreamReader(byteStream))
{
string strResponse = sr.ReadToEnd();
if (
!ignoreAuthenticationErrors
&& strResponse.IndexOf("{\"error\":{") > -1
&& (strResponse.IndexOf("\"code\":498") > -1 || strResponse.IndexOf("\"code\":499") > -1)
)
return true;
clientResponse.Write(strResponse);
}
}
else
{
// Binary response (Image or other binary)
// Don't cache the result
clientResponse.CacheControl = "no-cache";
byte[] buffer = new byte[32768];
int read;
while ((read = byteStream.Read(buffer, 0, buffer.Length)) > 0)
{
clientResponse.OutputStream.Write(buffer, 0, read);
}
clientResponse.OutputStream.Close();
}
serverResponse.Close();
}
}
return false;
}
I want to extend a facebook access token using the method below:
function extend(fb_access_token) {
var extendingUrl;
try{
console.log("Extending Facebook Access Token.");
if (app_id == "" || app_id == null) {
alert("App ID not configured properly.");
hasError = true;
return;
} else {
hasError = false;
}
if (app_secret == "" || app_secret == null) {
alert("App Secret not configured properly.");
hasError = true;
return;
} else {
hasError = false;
}
if (fb_access_token == "" || fb_access_token == null) {
alert("Facebook Access Token not was not generated.");
hasError = true;
return;
} else {
hasError = false;
}
if(hasError) {
alert("URL not formed.");
} else {
extendingUrl = "https://graph.facebook.com/oauth/access_token?client_id="+app_id+"&client_secret="+app_secret+"&grant_type=fb_exchange_token&fb_exchange_token="+fb_access_token;
window.location.replace = extendingUrl;
console.log("Facebook Access Token successfully extended.");
}
} catch (OAuthException) {
console.log("Login status or access token has expired, been revoked, or is otherwise invalid.");
}
}
I want to get the generated access token from the page that will eventually give the extended access token, see var extendingUrl.
The page will return something like:
access_token=CAAERkjuisOYBALHbBZB9oq01ybCoyBfyGlSHtkkZBDqDvevrWZC42JwMawxxxOxQsiKHMNVPHZCbh3ntF7GdnYwnq3BLTh6ZA2YUJCVSh8QA5nEZACZCXVtZCL5RZC72pl3afKMAOMG2WGKtjnD1GJTjQEPC2XH3X1ycr3GeAUWBShDj7ojFVCWhDe6jBGvBu2nn7Ohu9C2udBoamOBxoQFun&expires=5182005
and I will substring the string above and eliminate access_token= and &expires=5182005 to a new variable, and store it into my database.
Got it. I used jquery and fed the url (extendingUrl), in return, it gave me the contents of the url I requested. Then I used regex and substring to eliminate the unwanted text.
$.get(extendingUrl, function(data) {
var raw = data;
var patt1 = /(access_token=)(.*)(?=&expires=)/;
var result = raw.match(patt1);
var longToken = result[0].substring(13, 400);
});
I was trying to make a register function using angularJS and webAPI
After registering , API should set a cookie. However when I reload the page there is no cookie! I don't know what is the problem!!!!
This is how I set the cookie
public HttpResponseMessage register(User UserToRegister)
{
UserToRegister.UserID = Guid.NewGuid();
YanceySiteDBEntities db = new YanceySiteDBEntities();
db.Users.Add(UserToRegister);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, UserToRegister);
var cookie = new CookieHeaderValue("useremail", UserToRegister.UserEmail);
cookie.Expires = DateTimeOffset.Now.AddDays(1);
cookie.Domain = Request.RequestUri.Host;
cookie.Path = "/";
response.Headers.AddCookies(new CookieHeaderValue[] { cookie });
return response;
}
And this is how I read the cookie.
public bool CheckIfLogIn()
{
bool LogedIn = false;
CookieHeaderValue cookie = Request.Headers.GetCookies("useremail").FirstOrDefault();
if (cookie != null) LogedIn = true;
return LogedIn;
}
Hope anyone can help me , Thanks in advance!