Tuesday, February 25, 2014

ウェブアプリの「合理的な」セキュリティ対策に関する一考察

※※※ミドルウェアを中心に、ウェブ関連の研究開発に携わっている者による雑文です※※※

ウェブの脆弱性は、ウェブアプリケーションのバグに起因するものと、ウェブブラウザのバグに起因するものの2者に大別することができる。

ウェブアプリケーションを開発/提供する仕事に従事している者には、この前者、すなわち、ウェブアプリケーションのバグに起因する脆弱性を最小限に抑え込むことを求められる注1

かといって、脆弱性がないことを保障するのは難しい。「ウェブアプリケーションにバグがあっても脆弱性とはならない(あるいは被害が限定される)ような設計」を採用するのが現実的だと考えられる。

OSにおける、プロセス間のメモリ分離やuserIDに基づいたファイルへのアクセス制御を考えてみると、OSがセキュリティを「強制」するため、アプリケーション側で不正なコードが実行されても脆弱性とならない、もしくは、影響を小さく抑え込むことができるようになっていることがわかる。

ウェブ技術における同様の例は数多いが、たとえばXSS脆弱性対策を見ると、


といったものを挙げることができる。また、SQL Injection対策を見ると、


等の手法が知られている。

これらの対策をひとつ選択し、あるいは組み合わせて使うことで、コーディングミスがあったとしても脆弱性が発現しない(もしくは発現する可能性が低い)アプリケーションを実現することができる

ただ、この種の技術には多かれ少なかれ、アプリケーション側のコードに不自由を強いるという側面がある。

たとえば、Content Security Policyには、インラインの<SCRIPT>タグを実行しづらいという制限がある(1.1で修正見込)し、例として挙げたSQL Injection対策のいずれもが現実的でないウェブアプリケーションも多いだろう。また、SQLにおける条件節の漏れによる情報漏洩のように、本質的に対策が難しい注3問題も存在する。

以上のように、共通モジュール(あるいは下位レイヤ)でアクセス方法を「強制」する仕組みを用いることで、脆弱性への耐性を高めるという情報工学における一般的なアプローチは、ウェブ技術においても有効であり、積極的に使用すべきである注4。一方で、述べたように、今後の発展が期待される分野も存在する注5



注1: 後者については、一義的にはウェブブラウザベンダーが対応すべき問題である。もちろん、ウェブアプリケーション側で緩和策が実装できるならすれば良いケースもある

注2: 最新のテンプレートエンジン事情を良く知らないので列挙はしません。また、DOM APIベースのアプローチについても本稿では割愛します。

注3: ウェブアプリケーションにおいては、アクセス制限とアクセスを単一のクエリで記述することを求められることが多いため。この点は、ケーパビリティの概念を導入したORMのようなアプローチで解決可能なのかもしれないが…

注4: 「IPA 独立行政法人 情報処理推進機構:安全なウェブサイトの作り方」では、脆弱性を9種類に類型化して説明しているが、そのほとんどは「アプリケーションプログラマがミスをしても問題ない」ような共通コード(ウェブアプリケーションフレームワークやライブラリ等)の使用により回避することが可能であるし、そのような実装が称揚されるべきである

注5: なので、研究課題として面白いと思います

Friday, February 7, 2014

Why asm.js sometimes runs faster than hand-written JavaScript (and the changes in JSX 0.9.77)

I have released an update (version 0.9.77) of JSX - a statically-typed altJS programming language with an optimizing compiler to JavaScript, with the following changes:

  • the definition of int has been changed to strict 32-bit signed integer
  • introduce Promise class in conformance to the ECMAScript 6 draft

The second change should be obvious. Let me explain the reasoning behind the first one.

Background:

Until now, definition of int in JSX has been: a number that is at least possible to represent integers between -231 to 231-1, or may or may not become NaN or +-Infinity.

This was based on our understanding that enforcing integer arithmetic in JavaScript (i.e. using | 0) would lead to slower execution speed. We wanted the int type of JSX to represent some kind of integral numbers without sacrificing execution speed. And the type had been defined as such.

But the advent of asm.js has changed the game. Such enforced integer arithmetic is one of the most common patterns found in JavaScript generated by Emscripten (since it compiles C/C++ code), and it would be natural to expect that existing JavaScript runtimes would optimize against such patterns.

The Benchmark:

So I decided to take time to run a tiny benchmark that compares the execution speed of ordinary arithmetic vs. enforced integer arithmetic on fib-using-int - jsPerf, and the results are interesting.

The benchmark compares three functions calculating Fibonacci numbers using loops.

// original
function fib(n) {
  var value = 1, prev = 1;
  for (var i = 1; i < n; ++i) {
    var t = prev;
    prev = value;
    value += t;
  }
  return value;
}

// core operation is enforced integer arith.
function fib(n) {
  var value = 1, prev = 1;
  for (var i = 1; i < n; ++i) {
    var t = prev;
    prev = value;
    value = (value + t) | 0;                <--- HERE
  }
  return value;
}

// core operation and loop are integer arith.
function fib(n) {
  n = n | 0;                                <--- HERE
  var value = 1, prev = 1;
  for (var i = 1; i < n; i = (i + 1) | 0) { <--- HERE
    var t = prev;
    prev = value;
    value = (value + t) | 0;                <--- HERE
  }
  return value;
}

Looking at the results below (please refer to the benchmark page for the latest numbers) the fact is that code runs about 10% faster on Chrome and Firefox when explicitly specifying an extra operation (i.e. | 0).


This is not a surprise for people with the understanding of how the JIT (just-in-time-compile) engines of the runtimes work. The engines compile arithmetic operations in the original function of the benchmark into integer arithmetics with guards, so that the calculation can be changed to use floating-point operations once the numbers goes out of the 32-bit integer range. But if | 0 is added to the statement it becomes clear that the result of the arithmetic should be a module of 232 and thus that the guards become no longer necessary.

The Problem and the Solution:

The problem being left is how to write code that takes benefit from such optimizations. It is hard to add | 0 all over the source code, and there would be a negative performance impact unless you succeed in marking all of them correctly. It is once again clear that some kind of automated code generator is desirable for JavaScript, and this is the reason why we are happily applying the described change to JSX :-)

To summarize, JSX as of version 0.9.77 supports strict 32-bit integer arithmetic; and it is easy for the users to benefit from the described optimizations within the JavaScript runtimes. It's just a matter of marking some variables as : int. And the results of assignment to the variable as well as additions, subtractions, and multiplication between such variables would be int.


PS. I have also written the Fibonacci calculator in asm.js, but have excluded the numbers from the benchmark since it was too slow. It seems that there exists a non-marginal overhead when calling asm.js code from JavaScript.