やまろぐはてな

勉強会レポートとか技術メモとか戯言とか

XSS対策のセキュアJSについて(基本編)

社内ブログでまとめた内容をこっちでも書いてみる。ただ、フレームワーク使ったりしている中級者以上にはあんま参考にならないと思いますが基本編みたいなノリで御覧ください。

エスケープをする

すぐできる対策であり、割と効果的なものがエスケープ処理です。これは問題を起こしうる特殊文字文字参照に変換して、実行させないようにする処理です。対応する特殊文字「&」「<」「>」「”」「’」の5つです。

function escapeHTML(str) {
 str = str.replace(/&/g, '&');
 str = str.replace(/</g, '&lt;');
 str = str.replace(/>/g, '&gt;');
 str = str.replace(/"/g, '&quot;');
 str = str.replace(/'/g, '&#39;');
 return str;
}

ちなみにES6であればテンプレートリテラル(=Template strings)を使用して下記処理もできます。

function escapeHTML() {
 var raw = String.raw.apply(null, arguments)
 var safe = raw.replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"').replace(/'/g, ''');
 return safe
}
var input = "<img src=# onerror=alert(1)>";
var html = escapeHTML`<div>${userinput}</div>`;

テンプレートリテラルの使い方は「`」(バッククオート)で囲むだけです。

URLはhttpおよびhttpsスキーム

URLを取り出し、それをデータとして扱う際に気をつけたいことは、javascriptスキームなど複数のスキームを介在させないために、リンク先がhttp://かhttps://なのかを判断して挿入するようにすることです。

var url = decodeURIComponent(location.href);
if( url.match( /^https?:\/\// ) ){
    var elm = document.getElementById("link");
    elm.setAttribute("href" url);
}

javascriptスキームはいわゆるブックマークに登録して便利な機能として使うというのが一般的ですが、それをXSSとして使用されるのを防ぐための策であります。

JSONPの取り扱い注意とJSON.parse

JSONPはクロスドメイン、つまり同一のドメインのデータでなくても引っ張ってこれるもので便利なものではありますが、同時に他者が仕組んだ悪意のあるJSONPデータも入り込む可能性があります。

JSONPをまったく使用するな、ということではないのですが使用する際は信頼のあるデータであることを証明した上で使用するのが吉です。

そしてJSONほか外部データを使用する際は必ず JSON.parse関数 を使用してください。これは文字列を JSON として解析するためのものなので、eval関数だとJSONの中に実行文が紛れていると実行されてしまう恐れがありますので意識して使いましょう。

レンダリングメソッド使用廃止

主に下記のソースになります。これは上述したエスケープ処理がない場合、確実にXSSの標的になり得ますし、この部分を使って悪用されるおそれがあるかもしれないからです。

element.innerHTML = “…”;
element.outerHTML = “…”;
document.write(…);
document.writeln(…);

jQueryに頼り過ぎるな

jQueryはjsライブラリの1つですが、煩雑なコードを容易に記述しやすくして、デザイナーさんにも扱える簡単なもので今も制作会社で広く使用されていると思われます。

実はjQueryでもXSS対策はできるものがあり、それは text() です。受け取る値をテキストデータにエスケープしてくれる代物なのでinputでの入力を即出力するものには適しています。

$('input').on('keyup', function(e){
 $('.hoge').text($(this).val());
});

しかしながら、jQuery自身の長所でもあり弱点としても見られる「DOMの直接操作」部分が割とネックとなってきています。つまりDOM操作によるXSSの介入が起こりうる可能性があるのです。

以前のver.1.6では $(location.hash) の脆弱性が指摘されており、要素の検索や作成などを引数の文字列で判断するため、$()内でスクリプトを記載すると#idで指定したものがそのまま要素として判断されることがありました(ver1.6.3にて修正済み)

http://my-web-app/#<img onerror="alert(1)" src="xxx">
$('#<img onerror="alert(1)" src="xxx">') //ハッシュ値で判断すると左の値で取得する
//<img>タグで処理されるようになってしまう。

jQuery自身もver3.0の更新(2016年5月)があったように、日々使いやすくかつ脆弱性を潰してきて、簡単な装飾程度であれば使用する面では問題無いかもですが、セキュリティ面を考えた上でwebサイト・アプリに使い続けるというのは難しい選択のようにも思えます。

なのでjQueryのみに頼り続けるのは危ないかも、というのを念頭に置いておくと良いかもしません。(※使用をやめろ!と固く禁じる訳ではないです)


こちらからは以上です。つまりReact.jsについてちゃんとやれということでした。

マテリアルデザインについて学ぶ社内勉強会

先週の水曜日に初主催の社内勉強会でマテリアルデザインについてやりました。

正直なところ曖昧な部分でしかしれてなかったので自分の勉強と改めて理解する・社内として共有知識にするみたいな感じでスライドつくりました。あくまで基本的な要点だけなので詳しく突っ込まれると、つらい。

speakerdeck.com

結局一番伝えたい部分はデザインのフレームワークはいっぱい出来てきたけど、流行りのために使うのではなく、自分たちの発信がどのようなものでそれに合うにはどういうフォーマットがいいか、ということを見失ってはいけないなということです。アーリーアダプターみたいな感じでもいいけど、ユーザーは皆そういう感じではないので。

初夏のJavaScript祭2016 行ってきた。

jsfes.net

個人的には参考になった。jsってやっぱ色々できるんだな。

以下発表順メモなど

node.jsでデスクトップアプリをつくる

@CHIHIRO_KAASAN

仕事中に自動で開発コストをかけずにいろいろできるものをつくる。

  • 実行環境の準備
  • 猫ファイルを取得
  • jsonで保存
  • Electronで実施

cheerio-httpcli スクレイピングを実行する。

www.npmjs.com

moduleを呼び出す。ダウンロードする。

画像、自分のほしい文字列を指定してあげる。

qiita.com

  1. セレクタで呼び出す。セレクタjqueryライク。each文でまわす。
  2. JSON作成
  3. デスクトップアプリ→Electronで動かす

npm パッケージをつくろう

@anticyborg

小規模のwebページ、LP制作について

  • 製作期間が短い
  • html, css, jsも同じような記述が多い
  • jsのui実装はだいたい自作・・・
  • ライブラリの解析・カスタムにかける時間で作れる

npm パッケージ化でいけそう!

  • npm アカウント作成
  • パッケージ名
  • 実装
  • リポジトリ用意
  • package.jsonの用意

package/${name}

普通に実装してもgulpビルドやBabelでもOK。common.jsスタイルで書くといろいろと楽。

パッケージを使う時

npm i packagename -D

呼び出し方法

  • htmlにスクリプトタグ
  • gulpfile.jsにconcatする
  • main.jsでrequire (browserify)

バージョンの管理:セマンティックバージョニング

セマンティック バージョニング 2.0.0

speakerdeck.com

APIの呼び出し回数に制限があって困ったのを、SEQ-QUEUEを使ってどうにかした話

@ampersand_xyz

ハッカソンで優勝した作品をローンチすることになった

fashionhack.jp

ハッカソンで使っていたAPIを実際ローンチするために使うのは無理。PUXがAPIを提供。

PUX「APIリクエストは3秒に1回まで」

APIとは?

アプリケーションの機能を利用するための入り口

つまり仕事を頼むのは3秒に1回までね

処理手順

  • アップロードファイル受け取り
  • iMageMagickでサイズ調整・保存
  • APIリクエスト
  • APIレスポンス処理
  • 一時ファイルの削除

www.npmjs.com

seq-queueはsetTimeoutのように処理時間を調整できる キュー数を取得して処理が多かったらsubmit前に混んでいるかどうかを知らせる

JAVASCRIPTでLEAPMOTION事始め

@kuwk

www.leapmotion.com

  • v1は割と動作が糞
  • 2014にv2リリースして、手の動きなどが詳細的になった。
  • VR対応までできた

github.com

SDKは色々ある

JavaScript SDK Documentation — Leap Motion JavaScript SDK v2.3 documentation

デモの様子

ES2015の今とこれから

@lion_man44

  • ES2015
  • ES Next

www.slideshare.net

ES2015, ES6でそれぞれQiitaで検索するとES6のが検索数が多い

ES2015仕様に関する議論

GitHub - tc39/ecma262: Status, process, and documents for ECMA262

ES2015の各ブラウザサポート状況

ECMAScript 6 compatibility table

JAVASCRIPTでデバイス連携してみて出会える技術!広がる知識!

http://www.1ft-seabass.jp/memo/

www.slideshare.net

連携の流れ IFTTT → heroku → milkcocoa

milkcocoaだとjsでリアルタイム通信が開発できる

CSSプロパティの記述順について - CSScomb解決編

yamanoku.hatenablog.com

以前CSSプロパティの記述順に対してどうするかなどと悩んでいましたが、1つの解決策を見つけました。

CSScombを使用してみる

自分で記述順を悩むなんてアホくさいので機械に全部処理してもらうということになりました。というわけで以下をインストール。

CSScomb: Makes your code beautiful

npm install csscomb --save-dev 

CSScombってどういうものなの

CSScombはcssのプロパティの整形をしてくれるプラグインで、sublimeTextにもパッケージがあります。整形はpleeeaseでもできそうな気がしたけど、思っているプロパティ整理はなさそうなので有用そうなものを使用してみました。

以下はgulpを使っているので他の記述とは異なる箇所もあるのでご了承ください。

gulpfile.js

var conf = require('./config.json');
var gulp = require('gulp');
var comb = require('gulp-csscomb');

gulp.task('style', function() {
  gulp.src(conf.PATH.css)
    .pipe(csscomb())
    .pipe(gulp.dest('./src' + conf.URL + 'css'))
});

// 僕の環境ではこんな感じ
gulp.task('stylus', function () {
  gulp.src(conf.PATH.stylus)
  .pipe($.plumber())
  .pipe($.stylus({
    use: function(style) {
      for(key in conf) {
        style.define(key, conf[key]);
      }
    }
  }))
  .pipe($.pleeease({
    autoprefixer: ['last 2 versions','iOS >= 8','Android >= 4'],
    rem: false,
    mqpacker: true,
    minifier: false
  }))
  .pipe(comb())
  .pipe(gulp.dest('./src' + conf.URL + 'css'))
});

config.json

{
      "TITLE": "test",
      "URL": "/",
      "hostname": "localhost",
      "PATH": {
            "css"        : ["css/**/*.css", "!css/_**/*.css"],
            "stylus"    : ["stylus/**/*.styl", "!stylus/_**/*.styl"],
      }
}

出力先のdestとかPATH設定とかは各自ご自由に。comb()追加するだけでやってくれます。

整形の設定を変えたい

gulpを走らせて、保存すれば自動的にcombしてくれるのですがこんな感じです。

f:id:cardboarder:20160508211041p:plain

いわゆるデフォルトのソート順であったり、それぞれのプロパティの関連順に整列して1段空きがあったりなど、整形はしてくれたけど見た感じは微妙な感じかもしれません。また、このデフォルトの記述欄整形では他の人との連携でルールが明確で無いのでやりづらいのでこのままでは求めている記述順の正攻法にはなりません。

なのでCSScombの設定(config)をいじります。以下にアクセスどうぞ。

CSScomb: Build config

ここではどのような整形ルールにするかを設定できます。やってほしいrulesetを選んで順々に進めていきます(計24個) すると設定をしてくれたjsonを吐き出すのでこれを .csscomb.json と命名して、gulpfile.jsと同じ階層のディレクトリに保存します。(もしくはプロジェクトのルートフォルダ)

んで整形したのが以下の感じです。

f:id:cardboarder:20160508212012p:plain

アルファベット順の整形、ベンダープレフィックスの頭揃え、カラーコードは小文字で3文字省略できるものは省略するなどでいじりました。

ちなみに自分で設定した.csscomb.jsonはこんな感じです。ご参考までにどうぞ。

{
    "remove-empty-rulesets": true,
    "always-semicolon": true,
    "color-case": "lower",
    "block-indent": "\t",
    "color-shorthand": true,
    "element-case": "lower",
    "eof-newline": false,
    "leading-zero": false,
    "quotes": "double",
    "sort-order-fallback": "abc",
    "sort-order": ["..."],
    "space-before-colon": "",
    "space-after-colon": " ",
    "space-before-combinator": " ",
    "space-after-combinator": " ",
    "space-between-declarations": "\n",
    "space-before-opening-brace": " ",
    "space-after-opening-brace": "\n",
    "space-after-selector-delimiter": " ",
    "space-before-selector-delimiter": "",
    "space-before-closing-brace": "\n",
    "tab-size": true
}

これでcssだけ弄る人でもconfigルールを明確にしとけば、混乱はないんじゃないのかなと思います。テンプレートと素のcssとの併合とか考えだすとめんどくさくなるのでひとまずこれでいきましょう。

余談ではありますが

もしアルファベット順ではなく独自の記述順がある際は sort-order で設定できたりします。なんかより分かりづらくなりそうですが。

"sort-order": [
    [
    "font",
    "font-family",
    "font-size",
    "font-weight",
    "font-style",
    "font-variant",
    "font-size-adjust",
    "font-stretch",
    "font-effect",
    "font-emphasize",
    "font-emphasize-position",
    "font-emphasize-style",
    "font-smooth",
    "line-height"
    ]
]

割とスッキリできたので皆様もご参考にどうぞ。こちらからは以上です

参考

qiita.com

blog.sakurachiro.com

katoken.hatenadiary.jp