Tuesday, December 31, 2019

C# programming: Debug and trace


To generate a trace, use

System.Diagnostics.Trace.WriteLine("some trace");

This code works when TRACE is turned on during compiling. Add the compile option in web.config:

<compilation defaultLanguage="c#" debug="true" targetFramework="4.5">
  <compilers>
    <compiler language="c#" ... compilerOptions="/d:DEBUG;TRACE" />
  </compilers>
</compilation>

During the development, the trace can be found in the Visual Studio's console. If the application is deployed, the trace can be seen with the tool Debugview, which can be downloaded from:

https://docs.microsoft.com/en-us/sysinternals/downloads/debugview


Monday, December 30, 2019

OWASP Top Ten 2017 Examples and Fixes | C# Programming


1. Injection

The problem: SQL Injection

string sql = @"SELECT *  FROM Memos WHERE Id = " + idString;
using (OleDbConnection cnn = new OleDbConnection(connectionString))
{
  cnn.Open();
  OleDbCommand cmd = new OleDbCommand(sql, cnn);
  OleDbDataReader reader = cmd.ExecuteReader();

  while (read.Read())
  {
    ...
  }
}

If idString comes from the user input, it can be manipulated to create unexpected SQL commands.

The fix is to use prepared statement:

string sql = @"SELECT *  FROM Memos WHERE Id = ?";
using (OleDbConnection cnn = new OleDbConnection(connectionString))
{
  cnn.Open();
  OleDbCommand cmd = new OleDbCommand(sql, cnn);

  cmd.Parameters.AddWithValue("@Id", idString);
 
  OleDbDataReader reader = cmd.ExecuteReader();

  while (read.Read())
  {
    ...
  }
}



2. Broken Authentication

The problem: Session is kept after logout

public ActionResult LogOut()
{
  return RedirectToAction("LogOn");
}

The fix is to remove the user session from DB and server side:

public ActionResult LogOut()
{
  string userName = Session["UserName"].ToString();
  db.RemoveUserSession(userName);
  Session.Abandon();
  return RedirectToAction("LogOn");
}


3. Sensitive Data Exposure

The problem: Store password in plain text

var user = new User()
{
  Email = email,
  Login = login,
  Password = password,
  Name = name,
  Role = role
};

The fix is to store the hash so that the password won't be stolen from the memory:

var user = new User()
{
  Email = email,
  Login = login,
  Password = Argon2.Hash(password),
  Name = name,
  Role = role
};


4. XML External Entities (XXE)

var resolver = new XmlUrlResolver();

var settings = new XmlReaderSettings
{
  DtdProcessing = DtdProcessing.Parse,
  XmlResolver = resolver
};

XmlReader reader = XmlReader.Create("items.xml", settings);

The fix:

var resolver = new XmlUrlResolver();

var settings = new XmlReaderSettings
{
  DtdProcessing = DtdProcessing.Prohibit,
  XmlResolver = null
};

XmlReader reader = XmlReader.Create("items.xml", settings);


5. Broken Access Control

The problem: Unvalidated Redirects and Forwards

private ActionResult RedirectToLocal(string retureUrl)
{
  if (!string.IsNullOrEmpty(returnUrl))
  {
    return Redirect(returnUrl);
  }
  return RedirectToAction("Index");
}

The fix is to validate the URL first before redirect:

private ActionResult RedirectToLocal(string retureUrl)
{
  if (Url.IsLocalUrl(returnUrl))
  {
    return Redirect(returnUrl);
  }
  return RedirectToAction("Index");
}


6. Security Misconfiguration

The problem: Information Exposure of Error Details

Logger.LogError(ex.Message + ex.StackTrace);

The fix is to avoid logging stack trace unless it is in debugging:

if (Debugger.IsAttached)
  Logger.LogDebug(ex.Message + ex.StackTrace);

Logger.LogError(ex.Message);


7. Cross Site Scripting (XSS)

userModel.Information = reader["Information"].ToString();

The fix:

string information = reader["Information"].ToString();
string encodedInfo = AntiXssEncoder.HtmlEncode(information, false);
userModel.Information = encodedInfo.ToString();


8. Insecure Deserialization

using (var filestream = File.Open(filename, FileMode.Open))
{
  return DeserializeObject<T>(filestream, settings);
}

The fix is to use encryption/decryption during serialization/deserialization:

using (var filestream = File.Open(filename, FileMode.Open))
{
  using (var cs = new CryptoStream(filestream,
                        CreateRijndael(password).CreateDecryptor(),
                        CryptoStreamMode.Read))
  {
    return DeserializeObject<T>(cs, settings);
  }
}

private static Rijndael CreateRijndael(string password)
{
  var rijndael = Rijndael.Create();
  var pdb = new Rfc2898DeriveBytes(password, Pepper, 1000000);
  rijndael.Key = pdb.GetBytes(32);
  rijndael.IV = pdb.GetBytes(16);
  return rijndael;
}


9. Using Components with Known Vulnerabilities

Linking a file from an untrusted website:

<link href="http://a.company.com/some.styles.css" rel="stylesheet" />

The fix:

 <link href="https://a.trustworthy.website.com/some.styles.css"
       rel="stylesheet" 
       integrity="sha256-......." 
       crossorigin="anonymous" />









10. Insufficient Logging and Monitoring

Console.WriteLine(ex.Message);

The fix:

Logger.LogError(ex.Message);



Friday, November 22, 2019

Oracle: create index for column that allows NULL



CREATE INDEX table1_nullable_col1_idx
       ON table1 (nullable_col1, 1);

The ", 1" makes Oracle add into the index the record whose nullable_col1 field has a NULL value.


Thursday, November 21, 2019

Oracle: update one table with joined condition from another table


UPDATE table1 
       SET t1_col1 = 'something'
       WHERE id IN (SELECT t1.id FROM table1 t1, table2 t2
                                 WHERE t1.id = t2.id
                                 AND t2.t2_col1 = 'some condition');

Monday, November 11, 2019

Adding a CA to the trust store for Eclipse


If a Eclipse plugin uses a self-signed updating web site, you may encounter the authentication failure error when updating the plugin.

The solution is to add the CA of the self-signed certificate to the trust store that Eclipse uses.

By default, Eclipse uses the Java trust store at $JAVA_HOME/lib/security/cacerts.

To list the certificates in it, go to $JAVA_HOME/lib/security/ and run command:
$ $JAVA_HOME/bin/keytool -list -keystore ./cacerts

You may not have the permission to add a new certificate into the default trust store. We can make a copy of the default trust store and add the new certificate in the new copy.
$ cd /path/to/my/trust/store/location
$ cp $JAVA_HOME/lib/security/cacerts mytruststore

The password of Java's default cacerts is "changeit". You will need to input it when adding a new certificate into mytruststore.

Run the following command to import the new certificate (e.g. cloudServicesRootCA.cer, this post shows how to download the certificate of a CA) into mytruststore:
$ $JAVA_HOME/bin/keytool -alias cloudServicesRootCA -import -file cloudServicesRootCA.cer -keystore mytruststore

Exit Eclipse if you are running it and let Eclipse know the new trust store by adding it to Eclipse's configuration file eclipse.ini which locates in the root directory of the Eclipse installation. Use an editor to open eclipse.ini and add/modify these two parameters:
-Djavax.net.ssl.trustStore=/path/to/my/trust/store/location/mytruststore
-Djavax.net.ssl.trustStorePassword=changeit

Friday, November 8, 2019

Windows 10: use MMC (Microsoft Management Console) to add a trusted CA


1. Right click on the Windows icon. Select menu Run.

2. Input command: mmc

3. In MMC, click on menu File->Add/Remove Snap-in...

4. Select Certificates in the snap-ins list; Click on the Add button. "Certificates - Current User" will be added in the "Selected snap-ins" list. Click on the OK button.

5. In the left panel, expand "Certificates - Current User"; Right click on "Trusted Root Certification Authorities"; Select "All Tasks->Import...".

6. Use the Import Wizard to browse and select the certificate to import.

Note: Only add the CA if you absolutely trust it.


Monday, November 4, 2019

Some curl command options


To access a web page:
$ curl http://www.google.com

If the web server does not provide a trusted certificate, or it is using a self-signed certificate, we can accept the it by using the -k option:
$ curl -k http://www.google.com

To turn on verbose mode:
$ curl -v -k http://www.google.com

To use HTTP 1.0:
$ curl -v -k http://www.google.com --http1.0

To remove the "Host:..." header:
$ curl -v -k http://www.google.com --http1.0 -H 'Host:'

To remove more headers:
$ curl -v -k http://www.google.com --http1.0 -H 'Host:' -H 'User-Agent:' -H 'Accept:'



Friday, November 1, 2019

IIS web application to reject HTTP requests without a Host header


Step 1:

Download and install the URL Rewrite module (https://www.iis.net/downloads/microsoft/url-rewrite).

Step 2:

Add the rewrite rule in the web.config for the web application:

<system.webServer> 
......
    <rewrite>
            <rules>
              <rule name="RequestBlockingRule1" patternSyntax="Wildcard" stopProcessing="true">
                <match url="*" />
                    <conditions>
                        <add input="{HTTP_HOST}" pattern="*.*" negate="true" />
                    </conditions>
                    <action type="AbortRequest" />
                </rule>
            </rules>
    </rewrite>

</system.webServer>

Now, any HTTP requests without a "Host:..." header will get a connection reset.

Thursday, October 31, 2019

CVS: change file type from text to binary


$ cvs admin -kb my-files
$ cvs update -A my-files
$ cvs commit -m 'make them binary' my-files


Wednesday, October 30, 2019

To prevent IIS from showing IP in the Location header of HTTP response


Change web.config of the application to add a hostname to be shown in the Location header:

<system.webServer>
......
    <serverRuntime alternateHostName="myserver" />
......
</system.webserver>

This change may trigger an authentication error complaining about the locked section in the configuration. To fix it, run command:
> %windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/serverRuntime

It unlocks section system.webServer/serverRuntime at configuration path "MACHINE/WEBROOT/APPHOST". What it actually does is changing the following file
        C:\Windows\System32\inetsrv\config\applicationHost.config
by adding
        <serverRuntime />
to the "Allow" sections:
<location path="" overrideMode="Allow">
    <system.webServer>
    ......
        <serverRuntime />
    </system.webServer>
</location>

However, "myserver" is only returned in the Location header when the request does not contain the Host header. If the request headers include the Host, the value of the Host header will be returned in the Location header.
 
Get This <