×

iFour Logo

How to secure asp.net core web app?

Kapil Panchal - December 07, 2020

Listening is fun too.

Straighten your back and cherish with coffee - PLAY !

  • play
  • pause
  • pause
 How to secure asp.net core web app?

Asp.net Core is the most powerful, versatile, and complete framework, widely used by a developer to develop web, desktop, mobile, and cloud-based web application. Unlike Mobile and Desktop application, web application runs on the publicly available address so that the security of web application is important.better features in Asp.Net Core with best security practices, but still, there are Vulnerabilities and it is our responsibility to secure our web application before and after launching our Asp.net core web application.

Why .Net core is better for security?


Asp.net provide features like authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. So that developer can easily configure and manage security for their application.

ASP.NET Core provides tools and libraries such as built-in identity providers, party identity providers such as Facebook, Twitter, and LinkedIn to secure your web application.

Common Vulnerabilities


app-security

 

Vulnerabilities

Software Vulnerabilities means weakness or flaws present in code or anything that allows information security to be exposed to a threat.

Asp.net core contains features that help the developer to secure their web application and prevent security breaches. It is recommended to get best security tips to secure the application There are more vulnerabilities that the developer should be aware of. The following list contains the most common Vulnerabilities:

  • Cross-Site Scripting (XSS) attacks
  • SQL injection attacks
  • Cross-Site Request Forgery (XSRF/CSRF) attacks
  • Open redirect attacks

Cross-Site Scripting (XSS) attacks

Cross-Site Scripting (XSS) is a security vulnerability in which an attacker place client-side scripts (usually JavaScript) into web pages. When other users access affected pages the attacker's scripts will run automatically and, enabling the attacker to steal credentials from cookies and session tokens. A hacker can change the contents of the web page through DOM or redirect the browser to another page.

XSS vulnerabilities generally occur when an application interacts with the user through the input and outputs page without validating, encoding, or escaping it.

The script can be injected in the following ways:

  • Form Inputs
  • URL Query Strings
  • HTTP Headers

cross-site

1.1 Cross-site scripting working

How to prevent cross-site scripting

Cross-site scripting can be prevented in the following way:

 

  • Regular Expression Attributes
  • Regular Expression Object Model
  • HTML Encoding
  • URL Encoding

Regular Expression

Using regular expression form inputs can be validated and the user's form denies special character, symbol and only allow required character before proceeding to the next page.

 
public class Student
{


// Allow up to 15 uppercase and lowercase 
// characters. Use custom error.
[RegularExpression(@"^[a-zA-Z''-'\s]{1,15 }$", 
  ErrorMessage = "Characters are not allowed.")]
public object FirstName;

// Allow up to 15 uppercase and lowercase 
// characters. Use standard error.
[RegularExpression(@"^[a-zA-Z''-'\s]{1,15}$")]
public object LastName;
}
Note:

Using Regular Expression, you can perform Client and server-side validation

Regular Expression Object Model

Using the regular expression object model, the developer can validate user inputs by calling static methods of the Regex class.


HTML Encoding

The Razor engine used in MVC automatically encodes all input sourced from variables so that malicious script will never be executed. <,”, >used in attack.

 
@{
var val = "<\"virat\">";
}
@val

So,Razor engine encode val in following format:


HTML file
<\"virat\">
< "Virat">
URL Encoding

Usually, the developer used plain text in the query string which causes an XSS attack so we should use an encoded query string. You can use the default encoder provided in

 
System.Text.Encodings.Web.			  
      
Example
public class HomeController: Controller
{
UrlEncoder _urlEncoder
public HomeController(UrlEncoder urlEncoder)
{
_urlEncoder = urlEncoder;
}
}
var example = "\"Virat kohli&\"";
var encodedValue = _urlEncoder.Encode(example);

SQL injection attacks

SQL injection attack is the most common attack. In SQL injection attacker place malicious SQL code that then runs in your database and allowing the attackers to access confidential information stored in the database.

In SQL injection the unauthorized user places some condition or special characters in the input field which causes to change in the execution of the whole query.

Example

 

login-form

1.2 Simple Login Form

SELECT * FROM db WHERE Username ="ViratKohli" AND Password ="runMachine"

cross-site

1.3 SQL Injection Example

SELECT * FROM db WHERE Username ="" or ""="" AND Password ="" or ""=""

Enable secret storage

SQL Injection can be prevented in the following way:

  • Validate inputs
  • Use stored procedures
  • Use parameterized queries
  • Use Entity Framework or any other ORM
  • Store encrypted data
Validate Inputs

Validate the user inputs on both the client-side and server-side using Regular expression and data annotation and Don't allow special characters that are used in SQL script.

stored procedures

Use store procedure to prevent SQL injection but also validate parameter pass to store procedure.

Use Parameterized Queries

Example:

 
SqlConnection connection = new SqlConnection(connectionString);
SqlCommand command = new SqlCommand("select name from student where id=@id", connection);
command.Parameters.Add("@id", SqlDbType.Int);
command.Parameters["@id"].Value = id
Use Entity Framework or any other ORM

ORM stands for the object-relational mapper, which maps SQL objects to class. Use Entity Framework for preventing SQL injection because Entity Framework uses a parameterized query.

Store Encrypted Data

Use Encryption technique for confidential data like email, password, etc.

Cross-Site Request Forgery (XSRF/CSRF) attacks

An attacker takes advantage of an authorized session. An attacker acts as a trusted source between authorized user can web and sends some forged data to a site. The site processes the forged data because it believes that data comes from an authorized user.

cross-site

1.4 CRF Work Flow

How to prevent cross-Site Request Forgery

Using AntiForgeryToken developers can prevent an attack. we can use the anti-forgery attribute in the Html tag and set it value as true. The default value for anti-forgery is false. Add [ValidateAntiForgeryToken] attribute in the post method to check whether a valid token is generated.

 
virat\">

...

@Html.AntiForgeryToken()

 

[HttpPost]
[ValidateAntiForgeryToken]
public async Task<\"virat\"> Login(LoginModel data)
{
  …
}

       

Open redirect attacks

Web applications frequently redirect unauthenticated users to a login page when they access resources that require authentication. After successful authentication, The Redirection URL typically includes return URL query string so that the user can be returned to the original Requested URL.

Redirection URL is specified in the query string of the request, an attacker can tamper (interfere with (something) to cause damage or make unauthorized alterations.) with the query string. Query string allows users to redirect to an external, malicious site.

cross-site

1.5 Open Redirect Flow

Protecting Against local redirect
Use LocalRedirect Method

The local Redirect method is the same as the Redirect method but throws an exception when a nonlocal URL is specified.

 
public IActionResult SomeAction(string redirectUrl)
{
return LocalRedirect(redirectUrl);
}					

Searching for Dedicated ASP.NET Core Web Developer? Your Search ends here.


IsLocalUrl

Using the the the IsLocalUrl method user can test URLs before redirecting and protect users from being redirect to malicious sites.

 
private IActionResult RedirectToLocal(string returnUrl)
{
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction(nameof(HomeController.Index), "Home");
}
}				 
       

Important Point for securing Asp.net core web application


Use Custom Error Page for Error Handling

Sometimes, Exception may not handle properly and can lead to the exposure of sensitive information such as database configuration info, table names, stored procedures, data structures, and programming coding structure to users.


How to Add Proper Custom Error Handling
public void Configure(IApplicationBuilder app,IHostingEnvironment env,ILoggerFactory loggerFactory)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/home/error");
}
app.UseMvcWithDefaultRoute();
}

Secure Login

Login Page is like an entrance door for any Application. If attacker can get access to Admin Panel then he/she can access whole application. So, Securing Login is important.


How to Secure Login:

Use complex login credentials

Never use common username and password for Admin Panel.

Example: Never user Username like admin and Password like 1234.Use Strong Username and Password.

Always use .net core identity feature

Asp.Net Core provides many built-in libraries & tools to secure your applications. Use Authorization for complete sign in and signup process.


Suggestions:
  • Use Captcha Like Match Captcha, Letter Captcha in your login because bot can’t fill captcha
  • Block IP address if use fails login for more than 1 time
  • Include Alphabets (A-Z & a-z), Digits (0-9) & Special Characters (! , @, ., #, $, %, ^, &,* and more) in your password and make it strong.

Use Encryption

Example:

Use Hash function to encrypt your sensitive data. Include following namespace in your program.

 
using System;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivatio

Encrypt your data using following function

 
static string HashSh1(string input)
{
byte[] salt = new byte[128 / 8];
using (var rng = RandomNumberGenerator.Create())
{
rng.GetBytes(salt);
}
Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}");

// derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations)
string Encypt = Convert.ToBase64String(KeyDerivation.Pbkdf2(
password: input,
salt: salt,
prf: KeyDerivationPrf.HMACSHA1,
iterationCount: 10000,
numBytesRequested: 256 / 8));
     
return Encypt;
}			   
Clear Cookies

Manage cookie and remove cookie after logout.

Example: Delete all Cookies after logout. Use Response.Cookies.Delete() method to delete all cookies

 
private void DeleteCookies()
{
foreach (var cookie in HttpContext.Request.Cookies)
{
Response.Cookies.Delete(cookie.Key);
}
}

Use SSL

Use SSL stands for Secure Socket Layer to make the communication between Client & Server Side Encrypted using a very strong Key. Access application in HTTPS mode. Starup.cs of your Asp.Net Core Application, you can set Secure Policy for Cookies.

Use SSL stands for Secure Socket Layer To makes the communication between Client & Server Side Encrypted using a very strong Key. SSL provide secure layer between user and Server so that the requests passed between the user browser and the server, and the responses from the server to the user browser, will be encrypted to maintain the integrity and security of the data.

Access application in HTTPS mode. HTTP (Hypertext Transfer Protocol Secure) is used to security in your ASP.NET Core application.

Configuring for HTTPS option is available in Visual studio when selecting web application template

cross-site

1.6 Configuring core app for HTTP

Starup.cs of your Asp.Net Core Application, you can set Secure Policy for Cookies.

HSTS (HTTP Strict Transport Security)

HSTS is a web security policy that prevent your web application from cookie hijacking and provide communication over an HTTPS connection. HTTP Strict Transport Security always rejects insecure HTTP connections.

The asp.net Core web application by default add HTTP Strict Transport Security

cross-site

1.7 Setting HSTS policy in code.

Use Audit Trails

It is a best practice to keep monitoring web application activity logs and used to gather information like login attempts.

Log4Net Elmah are the most commonly used library for activity logging.

Custom Implementation

you can use custom implementation of activity logging.


What to store as Log
  • User Email/Username/Id
  • Full Name
  • Ip Address of Client System
  • Current Time
  • JavaScript Navigator user Agent Property
  • Log Type activity (e.g. Login, Logout, Edit Profile Info, Change Password)

How to get JavaScript Navigator userAgent Property

Simply navigator.userAgent single statement is used to get JavaScript Navigator useAgent Property in Asp.net core web application.


How to get client Ip address?

You can use following statement:

Hide Version

Remove Asp.net version Header

Whenever the client sends an HTTP request to the server in response, the client gets a response header with the following information:

  • server
  • x-powered-by
  • x-aspnet-version
  • x-aspnetmvc-version
  • x-sourcefiles

Server: Server Name.

X-Aspnet-Version: This shows the ASP.NET framework version used by website.

X- AspnetMvc-Version: This shows the ASP.NET MVC framework version used by website.

X-SourceFiles: Used by local host.

Remove X-Powered-By Header

Apply the following changes in the web configuration file


Remove X- AspnetMvc-Version Header

Apply the following changes in the Global.aspx file


Remove X- Aspnet-Version Header

Apply following changes in web configuration file


keep Framework & Libraries Updated

Always use an updated framework and library. Never use outdated Libraries or framework in your Project because attacker always keeps finding the Vulnerabilities in old Frameworks & Libraries.

Conclusion


Asp.net is one of the most secure frameworks but we have to still protect our application from malicious activity. By common practices, users can easily develop secure .net core applications. Using these practices user can prevent their application from various attacks.

How to secure asp.net core web app? Asp.net Core is the most powerful, versatile, and complete framework, widely used by a developer to develop web, desktop, mobile, and cloud-based web application. Unlike Mobile and Desktop application, web application runs on the publicly available address so that the security of web application is important.better features in Asp.Net Core with best security practices, but still, there are Vulnerabilities and it is our responsibility to secure our web application before and after launching our Asp.net core web application. Why .Net core is better for security? Asp.net provide features like authentication, authorization, data protection, HTTPS enforcement, app secrets, XSRF/CSRF prevention, and CORS management. So that developer can easily configure and manage security for their application. ASP.NET Core provides tools and libraries such as built-in identity providers, party identity providers such as Facebook, Twitter, and LinkedIn to secure your web application. Common Vulnerabilities   Vulnerabilities Software Vulnerabilities means weakness or flaws present in code or anything that allows information security to be exposed to a threat. Asp.net core contains features that help the developer to secure their web application and prevent security breaches. It is recommended to get best security tips to secure the application There are more vulnerabilities that the developer should be aware of. The following list contains the most common Vulnerabilities: Cross-Site Scripting (XSS) attacks SQL injection attacks Cross-Site Request Forgery (XSRF/CSRF) attacks Open redirect attacks Cross-Site Scripting (XSS) attacks Cross-Site Scripting (XSS) is a security vulnerability in which an attacker place client-side scripts (usually JavaScript) into web pages. When other users access affected pages the attacker's scripts will run automatically and, enabling the attacker to steal credentials from cookies and session tokens. A hacker can change the contents of the web page through DOM or redirect the browser to another page. XSS vulnerabilities generally occur when an application interacts with the user through the input and outputs page without validating, encoding, or escaping it. The script can be injected in the following ways: Form Inputs URL Query Strings HTTP Headers 1.1 Cross-site scripting working How to prevent cross-site scripting Cross-site scripting can be prevented in the following way:   Regular Expression Attributes Regular Expression Object Model HTML Encoding URL Encoding Read More: Using Linq In MVC .NET Core Regular Expression Using regular expression form inputs can be validated and the user's form denies special character, symbol and only allow required character before proceeding to the next page.   public class Student { // Allow up to 15 uppercase and lowercase // characters. Use custom error. [RegularExpression(@"^[a-zA-Z''-'\s]{1,15 }$", ErrorMessage = "Characters are not allowed.")] public object FirstName; // Allow up to 15 uppercase and lowercase // characters. Use standard error. [RegularExpression(@"^[a-zA-Z''-'\s]{1,15}$")] public object LastName; } Note: Using Regular Expression, you can perform Client and server-side validation Regular Expression Object Model Using the regular expression object model, the developer can validate user inputs by calling static methods of the Regex class. HTML Encoding The Razor engine used in MVC automatically encodes all input sourced from variables so that malicious script will never be executed. used in attack.   @{ var val = ""; } @val So,Razor engine encode val in following format: HTML file URL Encoding Usually, the developer used plain text in the query string which causes an XSS attack so we should use an encoded query string. You can use the default encoder provided in   System.Text.Encodings.Web. Example public class HomeController: Controller { UrlEncoder _urlEncoder public HomeController(UrlEncoder urlEncoder) { _urlEncoder = urlEncoder; } } var example = "\"Virat kohli&\""; var encodedValue = _urlEncoder.Encode(example); SQL injection attacks SQL injection attack is the most common attack. In SQL injection attacker place malicious SQL code that then runs in your database and allowing the attackers to access confidential information stored in the database. In SQL injection the unauthorized user places some condition or special characters in the input field which causes to change in the execution of the whole query. Example   1.2 Simple Login Form SELECT * FROM db WHERE Username ="ViratKohli" AND Password ="runMachine" 1.3 SQL Injection Example SELECT * FROM db WHERE Username ="" or ""="" AND Password ="" or ""="" Enable secret storage SQL Injection can be prevented in the following way: Validate inputs Use stored procedures Use parameterized queries Use Entity Framework or any other ORM Store encrypted data Validate Inputs Validate the user inputs on both the client-side and server-side using Regular expression and data annotation and Don't allow special characters that are used in SQL script. stored procedures Use store procedure to prevent SQL injection but also validate parameter pass to store procedure. Use Parameterized Queries Example:   SqlConnection connection = new SqlConnection(connectionString); SqlCommand command = new SqlCommand("select name from student where id=@id", connection); command.Parameters.Add("@id", SqlDbType.Int); command.Parameters["@id"].Value = id Use Entity Framework or any other ORM ORM stands for the object-relational mapper, which maps SQL objects to class. Use Entity Framework for preventing SQL injection because Entity Framework uses a parameterized query. Store Encrypted Data Use Encryption technique for confidential data like email, password, etc. Cross-Site Request Forgery (XSRF/CSRF) attacks An attacker takes advantage of an authorized session. An attacker acts as a trusted source between authorized user can web and sends some forged data to a site. The site processes the forged data because it believes that data comes from an authorized user. 1.4 CRF Work Flow How to prevent cross-Site Request Forgery Using AntiForgeryToken developers can prevent an attack. we can use the anti-forgery attribute in the Html tag and set it value as true. The default value for anti-forgery is false. Add [ValidateAntiForgeryToken] attribute in the post method to check whether a valid token is generated.   virat\"> ... @Html.AntiForgeryToken()   [HttpPost] [ValidateAntiForgeryToken] public async Task Login(LoginModel data) { … } Open redirect attacks Web applications frequently redirect unauthenticated users to a login page when they access resources that require authentication. After successful authentication, The Redirection URL typically includes return URL query string so that the user can be returned to the original Requested URL. Redirection URL is specified in the query string of the request, an attacker can tamper (interfere with (something) to cause damage or make unauthorized alterations.) with the query string. Query string allows users to redirect to an external, malicious site. 1.5 Open Redirect Flow Protecting Against local redirect Use LocalRedirect Method The local Redirect method is the same as the Redirect method but throws an exception when a nonlocal URL is specified.   public IActionResult SomeAction(string redirectUrl) { return LocalRedirect(redirectUrl); } Searching for Dedicated ASP.NET Core Web Developer? Your Search ends here. SEE HERE IsLocalUrl Using the the the IsLocalUrl method user can test URLs before redirecting and protect users from being redirect to malicious sites.   private IActionResult RedirectToLocal(string returnUrl) { if (Url.IsLocalUrl(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction(nameof(HomeController.Index), "Home"); } } Important Point for securing Asp.net core web application Use Custom Error Page for Error Handling Sometimes, Exception may not handle properly and can lead to the exposure of sensitive information such as database configuration info, table names, stored procedures, data structures, and programming coding structure to users. How to Add Proper Custom Error Handling public void Configure(IApplicationBuilder app,IHostingEnvironment env,ILoggerFactory loggerFactory) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/home/error"); } app.UseMvcWithDefaultRoute(); } Secure Login Login Page is like an entrance door for any Application. If attacker can get access to Admin Panel then he/she can access whole application. So, Securing Login is important. How to Secure Login: Use complex login credentials Never use common username and password for Admin Panel. Example: Never user Username like admin and Password like 1234.Use Strong Username and Password. Always use .net core identity feature Asp.Net Core provides many built-in libraries & tools to secure your applications. Use Authorization for complete sign in and signup process. Suggestions: Use Captcha Like Match Captcha, Letter Captcha in your login because bot can’t fill captcha Block IP address if use fails login for more than 1 time Include Alphabets (A-Z & a-z), Digits (0-9) & Special Characters (! , @, ., #, $, %, ^, &,* and more) in your password and make it strong. Use Encryption Example: Use Hash function to encrypt your sensitive data. Include following namespace in your program.   using System; using System.Security.Cryptography; using Microsoft.AspNetCore.Cryptography.KeyDerivatio Encrypt your data using following function   static string HashSh1(string input) { byte[] salt = new byte[128 / 8]; using (var rng = RandomNumberGenerator.Create()) { rng.GetBytes(salt); } Console.WriteLine($"Salt: {Convert.ToBase64String(salt)}"); // derive a 256-bit subkey (use HMACSHA1 with 10,000 iterations) string Encypt = Convert.ToBase64String(KeyDerivation.Pbkdf2( password: input, salt: salt, prf: KeyDerivationPrf.HMACSHA1, iterationCount: 10000, numBytesRequested: 256 / 8)); return Encypt; } Clear Cookies Manage cookie and remove cookie after logout. Example: Delete all Cookies after logout. Use Response.Cookies.Delete() method to delete all cookies   private void DeleteCookies() { foreach (var cookie in HttpContext.Request.Cookies) { Response.Cookies.Delete(cookie.Key); } } Use SSL Use SSL stands for Secure Socket Layer to make the communication between Client & Server Side Encrypted using a very strong Key. Access application in HTTPS mode. Starup.cs of your Asp.Net Core Application, you can set Secure Policy for Cookies. Use SSL stands for Secure Socket Layer To makes the communication between Client & Server Side Encrypted using a very strong Key. SSL provide secure layer between user and Server so that the requests passed between the user browser and the server, and the responses from the server to the user browser, will be encrypted to maintain the integrity and security of the data. Access application in HTTPS mode. HTTP (Hypertext Transfer Protocol Secure) is used to security in your ASP.NET Core application. Configuring for HTTPS option is available in Visual studio when selecting web application template 1.6 Configuring core app for HTTP Starup.cs of your Asp.Net Core Application, you can set Secure Policy for Cookies. Read More: How To Secure Public Apis In Asp.NET Core? HSTS (HTTP Strict Transport Security) HSTS is a web security policy that prevent your web application from cookie hijacking and provide communication over an HTTPS connection. HTTP Strict Transport Security always rejects insecure HTTP connections. The asp.net Core web application by default add HTTP Strict Transport Security 1.7 Setting HSTS policy in code. Use Audit Trails It is a best practice to keep monitoring web application activity logs and used to gather information like login attempts. Log4Net Elmah are the most commonly used library for activity logging. Custom Implementation you can use custom implementation of activity logging. What to store as Log User Email/Username/Id Full Name Ip Address of Client System Current Time JavaScript Navigator user Agent Property Log Type activity (e.g. Login, Logout, Edit Profile Info, Change Password) How to get JavaScript Navigator userAgent Property Simply navigator.userAgent single statement is used to get JavaScript Navigator useAgent Property in Asp.net core web application. How to get client Ip address? You can use following statement: Hide Version Remove Asp.net version Header Whenever the client sends an HTTP request to the server in response, the client gets a response header with the following information: server x-powered-by x-aspnet-version x-aspnetmvc-version x-sourcefiles Server: Server Name. X-Aspnet-Version: This shows the ASP.NET framework version used by website. X- AspnetMvc-Version: This shows the ASP.NET MVC framework version used by website. X-SourceFiles: Used by local host. Remove X-Powered-By Header Apply the following changes in the web configuration file Remove X- AspnetMvc-Version Header Apply the following changes in the Global.aspx file Remove X- Aspnet-Version Header Apply following changes in web configuration file keep Framework & Libraries Updated Always use an updated framework and library. Never use outdated Libraries or framework in your Project because attacker always keeps finding the Vulnerabilities in old Frameworks & Libraries. Conclusion Asp.net is one of the most secure frameworks but we have to still protect our application from malicious activity. By common practices, users can easily develop secure .net core applications. Using these practices user can prevent their application from various attacks.
Kapil Panchal

Kapil Panchal

A passionate Technical writer and an SEO freak working as a Content Development Manager at iFour Technolab, USA. With extensive experience in IT, Services, and Product sectors, I relish writing about technology and love sharing exceptional insights on various platforms. I believe in constant learning and am passionate about being better every day.

Build Your Agile Team

Enter your e-mail address Please enter valid e-mail

Categories

Ensure your sustainable growth with our team

Talk to our experts
Sustainable
Sustainable
 
Blog Our insights
10 Executive Dashboard Examples for Consultants and CEOs
10 Executive Dashboard Examples for Consultants and CEOs

There is a principle behind every business. “If you don’t keep track of essentials, you won’t get clear direction, eventually causing your company to stumble.” To manage this scenario,...

How Spatial Data Analysis Improves Healthcare
How Spatial Data Analysis Improves Healthcare

Do you know when geospatial analysis took traction in healthcare? It was when John Snow, a London-based physician, used it to analyze the spread of cholera, which ultimately proved...

4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical
4 Types of Power BI Dashboards: Analytical, Strategic, Operational, and Tactical

One interesting aspect you truly love about Power BI, as a CTO, is how it lets you step back and see the bigger picture of your business. Isn’t it? Without getting bogged down in minute...