Security in Sciter-based applications

Please check “Security in Sciter-based applications” article of Juan Manuel Fernandez @ tarlogic.

And here are recipes of how to deal with the problems explained in the article.

Code injection prevention

Typical mistake is in use of non-escaped text in HTML composition.

Example (of bad code):

eval("alert("Hello " + $(form).value["name"] +"!");");

And malicious input in the name  field: ");System.Process.exec("cmd", ["/c","start"]);//

will effectively produce this:

alert("Hello ");System.Process.exec("cmd", ["/c","start"]);// !");

By default eval() and system function access are disabled in Sciter so all above is not the problem at all. Yet all such functions can physically be removed from compilation (you need access to Sciter’s source code for that).

The problem only arises when you put something like this in native code of your application:

  // enable features to be used from script
  SciterSetOption(NULL, SCITER_SET_SCRIPT_RUNTIME_FEATURES, 
                          ALLOW_FILE_IO | 
                          ALLOW_SOCKET_IO | 
                          ALLOW_EVAL |
                          ALLOW_SYSINFO );

where you deliberately enable eval() (ALLOW_EVAL) and System.Process.exec() (ALLOW_SYSINFO).

Solutions:

  1. Do not enable eval() and system function access from scripts in your applications.
  2. If you do need eval() then all variables in the expression that contain user input (form fields values, configuration files, etc) must be properly escaped, for example as userinput.toHtmlString().

Resource manipulation prevention

  1. HTML/CSS/script files that constitute UI of your application must reside inside your application. As packaged (packfolder and sciter::archive) or as resources of your exe and dll files. All exe and dll files should be digitally signed so OS will prevent their load if they were tampered.
  2. You should not enable file and network access by default ( ALLOW_FILE_IO and ALLOW_SOCKET_IO ) if they are not needed by the application.
  3. All HTML composition code that uses user input variables must use proper escapement.
    So not

    el.html = "Hello " + username; // What if username is "<frame src='steal.com/something'>"?

    but

    el.text = "Hello " + username; // or
    el.html = "Hello " + username.toHtmlString(); // or
    el.$content(Hello {username});
    
  4. On native side: SCN_LOAD_DATA callback handler that receives all resource requests from the UI shall use “white list” logic. It shall allow loading of resources only from designated places. If your application do need to load something from your site then you should have something like this
    virtual LRESULT on_load_data(LPSCN_LOAD_DATA pnmld)
    {
      LPCBYTE pb = 0; UINT cb = 0;
      aux::wchars wu = aux::chars_of(pnmld->uri);
    
      if(wu.like(WSTR("http:*"))
        return LOAD_DISCARD; // we do not use non-secured communication at all
    
      if(wu.like(WSTR("https:*")) {
        if( !wu.like(WSTR("https://mysite.com/*" )
          return LOAD_DISCARD; // we communicate only with our site! Reject all other URLs
      }
      ...
    }