196の日記

セキュリティ系の勉強、その他開発メモとか雑談、忘れそうな計算式などを書き溜める場所になっています. githhubはUnity触っていた頃ものがメイン https://github.com/196kakinuma [twitter https://twitter.com/196Ikuchil]

form_with の label 内に<i>タグを使用する

Railsdeviseを使用してサインアップフォームを生成し、ビューのコードをSlimで書き換える際に困りました。以下のようなform_withを用いてフォームを生成している場面

<div class="field">
    <%= f.label :password %> <i>(leave blank if you don't want to change it)</i><br />
    <%= f.password_field :password, autocomplete: "new-password" %>


以下のように書き換えられます。

  .field
    = f.label :password
    i
      |  (leave blank if you dont want to change it)
    br/
    = f.password_field :password,id:"password", class: "form-control", autocomplete: "new-password"

インデントがわかりにくいのは申し訳ないです。この書き方において、<i>タグはlabelには含まれていないです。上の元コードも含まれていないので。

ハニポログイン試行パスワードランキング(2018年後期ウチのt-pot ver.)

はじめに

タイトル通りですが、ウチに植えていたt-potにアクセスしてきた方々が、ログイン試行に使用したユーザ名とパスワードを書き留めておこうと思います。ただ、設置したのが10月後半なので、3ヶ月に満たない物になるのはご了承ください。

ユーザ名

ユーザ名 回数
root 397169
admin 123183
enable 74671
shell 66570
(空白) 25687
user 12734
guest 12591
sh 10681
default 9605
1234 8818

パスワード

パスワード 回数
system 67187
sh 63135
61162
1234 27995
admin 18825
123456 18232
password 16520
12345 12216
user 10625
1111 9500

2018年最悪なパスワードランキングは..

ランク パスワード
1位 123456
2位 password
3位 123456789
4位 12345678
5位 12345
6位 111111
7位 1234567
8位 sunshine
9位 qwerty
10位 iloveyou

以下から引用してきています。100位まで載っているのでぜひ見て下さい。 gigazine.net

The Worst Passwords of 2018 100-50 | SplashData

比べてみて

123456passwordは入っていますね。11111234..に属するものも見受けられます。この最悪パスワードランキングはシステム系からwebサイト全般など全ての統計と思われるので、4桁のパスワードが登場しないのはそれだけ桁数制限をかけている場所が多いからではないでしょうか?対してハニポさんには4桁のものやshまで登場しますから(adminとか手抜き設定すぎる..)、比較したランキングの分野が多少違うのかなと感じます。それでも、王道のパスワードはやはり王道でした笑

RubyOnRailsチュートリアルのテストをRSpecで書く

前書き

最近Rubyチュートリアルをやっていたのですが、その中で紹介されているテストコードはMinitestで書かれています。今回はそれをRSpecに書き換えながら行ったので、どうせなら公開しておこうと思います。(RSpec初心者なので綺麗な書き方はできていません!)rubyRSpecも初心者だった私はとても苦戦したので、そんな人の助けになればとおもいます。チュートリアルは下のページから飛べます。 現時点でRails5.1版を参考にしました。

railstutorial.jp

書き換える際に..

書き換えながら思ったことは、ビュー周りのテストをどう書くか。CapybaraというGemを使用すればほとんどの事は出来ますが、そもそもビューのテストをチュートリアルが紹介しているほど正確にやるべきかと、疑問には思いました。
それと、可能な限りチュートリアルのテストコードがやっているテストを再現したつもりですが、コントローラとフィーチャーテストの境が微妙なテストは、別の場所に書いたり、省略していたりします。(初心者なので許してください。)
また、検索で引っかかるRSpec書き換えのブログさんの物を多少借りている部分もあったと思うので、被っていたら申し訳ないです!

本題

以下のリンクから飛べます。一応プロジェクトごと載せておきます。

github.com

Docker You are using pip version 10.0.1, however version 18.1 is available.

状況

https://graneed.hatenablog.com/entry/2018/06/14/231740
上のサイトを参考にt-potに新しくWOWHoneypotを追加しようと、イメージのBuild中。下のようなエラーが出た。よく見るエラーだけどわかりづらいエラー。

  Could not find a version that satisfies the requirement install (from versions: )
No matching distribution found for install
You are using pip version 10.0.1, however version 18.1 is available.
You should consider upgrading via the 'pip install --upgrade pip' command.

環境は

16.04.5 LTS (GNU/Linux 4.15.0-39-generic x86_64)

今回

# Install packages 
RUN apk -U upgrade && \
    apk add build-base git libssl1.0 openssl-dev libffi-dev  python-dev py-cffi py-ipaddress py-lxml py-mysqldb py-pip py-pysqlite py-requests py-setuptools && \
    pip install --upgrade pip
RUN    pip install pyOpenSSL==16.2.0


1. 上記のエラーからpipのバージョンを上げるために、 pip install --upgrade pip追記 1. ここと似たエラーが出たため、libffi-devapk add行に追記。  

これでビルドに成功

まとめ

linux内のpip系は全く関係ない。Dockerfile内での記述を変更する。Docker初心者にはわかりにくかった。

t-pot 観察 #7 2018/12/9-15 SMTPへの継続アクセス観測中

お久しぶりです。しばらくサボっていました。 先週の状況を簡単にまとめます。(サボってたので先々週分とかはないです)

全体

f:id:thinline196:20181217002702p:plain f:id:thinline196:20181217002708p:plain

気になるのは香港のグラフですね。

香港からtelnet(23)

f:id:thinline196:20181217004554p:plain CVE-2015-7755。Juniper ScreenOS の脆弱性TELNETセッション中に不特定のパスワードを入力することによって管理者アクセス権を取得できるそう。送信元は前者が223.197.136[.]59で18364アクセス、後者が219.76.242[.]60で21313アクセス。

2018/12/11ごろからSMTPポート25への継続アクセス

f:id:thinline196:20181217005205p:plain 見にくいですが、12/11ごろから大陸棚のようにグラフに出てます。国別に見てみますと、  

f:id:thinline196:20181217005503p:plain ブラジル、中国、アメリカ、台湾、イタリアが筆頭です。送信元IPもバラバラです。何かのキャンペーンでしょうか?プロトコルとしてはSMTPで、Mailoneyでの観測。今これを書いている日曜夜現在も攻撃が続いているので、ちょっと注目するべきですね。 f:id:thinline196:20181217012436p:plain 上位3つが関係していそうです。下で紹介しているブログさんの通り、私の観測でも、HELO mailserver, AUTH LOGINの後にQUITが順番にきています。接続してログイン要求を確認して、接続解除していました。

SMTPのハンドシェイクについては下のブログさんが解説してます。 https://tk-secu.hateblo.jp/entry/2018/07/30/001417#%E3%83%A1%E3%83%BC%E3%83%AB%E3%83%8F%E3%83%8B%E3%83%BC%E3%83%9D%E3%83%83%E3%83%88%E3%81%AE%E6%A4%9C%E8%A8%BC

ruby チュートリアル 14章メモ

ActiveRecord through

n:mの関係を表すのに使用。1:nの関係はhas_manybelongs_toで表した。また後者の繋ぎ方であると、直接的な結びつきになるのに対して、throughを使用する場合は、2モデル間にクッションとなるモデルを定義してそこに関係をしまっていくイメージ。チュートリアルではユーザ間のフォローに使用して、誰が誰をフォローしているかを表すために使用。
f:id:thinline196:20181205135325p:plain
f:id:thinline196:20181205135432p:plain

userに追加する

userモデルと新たに作成したrelationshipモデルに関係性を追記する。

# app/models/user.rb
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy # micropostは外部キーがuser_idであったためこれでok
  has_many :active_relationships, class_name:  "Relationship", #外部キーはfollower_idとして定義しなければならない(followerというクラスは存在しない)
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  ...
end


# app/models/relationship.rb
class Relationship < ApplicationRecord
  belongs_to :follower, class_name: "User"
  belongs_to :followed, class_name: "User"
end


定義されるメソッド

active_relationship.follower フォロワーを返します active_relationship.followed フォローしているユーザーを返します user.active_relationships.create(followed_id: other_user.id) userと紐付けて能動的関係を作成/登録する user.active_relationships.create!(followed_id: other_user.id) userを紐付けて能動的関係を作成/登録する (失敗時にエラーを出力) user.active_relationships.build(followed_id: other_user.id) userと紐付けた新しいRelationshipオブジェクトを返す

非同期通信

form_withを使用して非同期通信を行う場合、remote:trueを指定してあげることで非同期通信となる。一つ注意としては、form_withではデフォルトでremote:trueが設定されている。(前身のform_forではデフォルトではなく明示的に指定が必要であった) なので、非同期にしたくない場合にlocal:trueを指定してあげることを忘れないようにする。

Unobtrusive Javascript

RailsではJSを前面に出さないようにする習わしがあるらしい。 http://railscasts.com/episodes/205-unobtrusive-javascript

respond_to

コントローラ内で使用した。リクエストで指定されたフォーマットでレスポンスを返すためのメソッド。

    respond_to do |format|
      format.html { redirect_to @user }
      format.js
    end

例えばこれがcreateメソッド内で呼ばれているのであれば、views/対応するモデル複数名/create.js.erbJSでのレスポンスの際に呼ばれるファイルとなる。

にしてもこの記事は酷いと思う。 => https://techacademy.jp/magazine/17744

Ajaxのテスト(RSpec)

RSpecajaxフォームのテストを行うにはxhrを追記してあげる。具体的には下。

    xhr :get ~~~

model間のRailsの予測

# models/user.rb
has_many :followeds, through: :active_relationships

上の1行をみて、railsactive_relationshipsfollowed_idを使って対象ユーザを取得しようとする(複数形を単数形にする). 自分でカラムを指定する場合、自分で名前を指定したい場合は下のように書く。

has_many :following, through: :active_relationships, source: :followed

followed+_idカラムを対象とし、userモデル内で呼び出すときはfollowingという名前で呼び出すことが可能。

個人的なメモ

# /models/user.rb
  has_many :active_relationships, class_name: "Relationship",
                                  foreign_key: "follower_id",
                                  dependent: :destroy
  has_many :following, through: :active_relationships, source: :followed

上のコードがuserモデルに書いてあることで、follower_idfollowed_idのカラム(どちらもUserモデルにbelongs_to)をもつRelationshipモデルから、user.followingで、relationshipのfollowedにあるid(userがフォローしているアカウント)が配列で取得できる。鍵になっているのが上の定義で、active_relationshipsを呼ぶことで、関連付いている自分のidfollower_idを頼りに、関係あるデータだけを取得してきている。よって、下のfollowingの定義では実質”関係あるデータの中から”のみデータを探索することができている。(下の定義だけ見てては、どうやって自分に関係あるレコードを抽出している理解できず、困惑していた)

memberとcollection

config/route内でresourcesを使用してルーティングを設定するとき、collectionメソッドを使用すると、resourcesで設定したルーティングにつけ加わる感じで、新たなアクション&ルーティングを定義できる。

resources :users do
  collection do
    get :tigers
  end
end


memberメソッドを使用すると特定のデータに対するアクションを生成することが可能になる。チュートリアルでは、ユーザのフォロー/フォロワーを表示するために使用。(~/users/1/following)

  resources :users do
    member do
      get :following, :followers
    end
  end


map

rubyのmapメソッドは、列挙可能なオブジェクトを配列に変換してくれる。

[3] pry(main)> [1,2,3,4].map{|i| i.to_s}
=> ["1", "2", "3", "4"]

[4] pry(main)> [1,2,3,4].map(&:to_s) #省略系
=> ["1", "2", "3", "4"]

[7] pry(main)> [1,2,3,4].map(&:to_s).join(",")
=> "1,2,3,4"
[8] pry(main)>

チュートリアルではユーザがフォローしている人のidを取得するの使用

>> User.first.following.map(&:id)
=> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51]

ActiveRecordでは、下のようなメソッドも用意されていて全く同じ動きをする。これはhas_many :followingの関連付けを行った時に自動で生成され、+_idsをつける形で実装される。

>> User.first.following_ids
=> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41,
42, 43, 44, 45, 46, 47, 48, 49, 50, 51]

サブクエリ

SELECT文のなかにSELECT文を記述する(括弧でくくる)。一般的に可読性はよくなる。チュートリアルでは効率をあげるためとの表記があった。これは、既存実装のfollowing_idsを使用した場合、DBへのアクセスが二回発生するからとのこと。サブクエリとして自分で実装することで、DB内でちょちょいとやってくれるらしい。

ruby チュートリアル 13章 メモ

belongs_to

指定したモデルと1対1の関係を持つ。参照元テーブルから参照先テーブルにアクセスする。モデル生成時にuser:referencesをつけるとモデル内に自動生成される。

#app/models/micropost.rb
class Micropost < ApplicationRecord
   belongs_to :user
end

user:references

上の通りコマンドでモデル生成時にuser:referencesをつけると、自動的にインデックスと外部参照キー付きのuser_idカラムが追加される。

  def change
    create_table :microposts do |t|
      t.references :user, foreign_key: true #ここ
      t.timestamps
    end
  end

複合キーインデックス (Multiple Key Index)

複数の条件で並び替えができるようにする。下の時は、user_idに関連付けられたすべてのマイクロポストを作成時刻の逆順で取り出しやすくなる。注意としては、2つ目以降にしてしたカラムのみでインデックスは使用できない。あくまでuser_idでのソート後にcreated_atでソートが可能。

    add_index :microposts, [:user_id, :created_at]


モデルのvalid?メソッド

モデル内でのvalidatesで弾かれてる値が入っている場合にfalseが返される。正確に言うと、valid?メソッドを使用した際に初めて保持されている値が評価され、booleanを返す。errors.messagesインスタンスメソッドを使用すると、発生したエラーにアクセスできる。

 test "content should be present" do
    @micropost.content = "   "
    assert_not @micropost.valid?
  end


デフォルトスコープ

dbから引っ張り出す際の条件(orderやwhere)をデフォルトで指定できる。が、ググると否定的な記事が多かった。ある時特別な条件で引っ張ってきたい時に、スコープを外すのが大変&見落としがちになるからだそう。チュートリアルではmicropostを新しい順に取得するために使用していた。

Dependent: destroy

下のように使用すると、Userを削除した際にUesrに紐づいていたMicropostも同時に削除される。こうすることで、db内にアクセス不可能なMicropostが残ってしまうのを防ぐことができる。

takeメソッド

チュートリアルでUserモデルから最初の6人を取得するために使用した。1~10のArrayから最初の6つをとるコードは下。

[5] pry(main)> (1..10).to_a.take(6)
=> [1, 2, 3, 4, 5, 6]


uninitialized constant ~Controller

この章に直接関係しないですが、RSpecでテスト書いている際に下のようなエラーが出ました。出現箇所としては、Controllerのテストで、createや`destroy``アクションを読んだ時でした。

ActionController::RoutingError:
        uninitialized constant MicropostController


根本原因としては、config/route.rbのルーティングミス。

#間違い
resources :micropost,           only:[:create,:destroy]
#正しい
resources :microposts,           only:[:create,:destroy]


単数形のままだと、確かにcreateのパス取得にmicropost_index_pathとか言う謎文字列を使わされました。正しく設定ができていれば、createアクションはmicroposts_pathで取得することができます。

current_userヘルパー

app/controllers/microposts_controller.rbで以前作成したcurrent_userヘルパーが再び使用されるが、これは定義元のSessionsHelperが大元のApplicationControllerincludeされているため、どこでも使える。
注意として、決してユーザ情報が保持されたインスタンス変数がコントローラ間で共有されているわけではなく、ヘルパーを介してセッションとクッキーを調べ、その情報を利用してユーザ情報についてコントロールしている。なので、共有しているように見えているのは、ヘルパーの実装がそうやって扱えるようにされているから。

SQLクエリのエスケープ

?記号で実現する。具体的には下参照。しかし、ググってみてもあまりこのやり方はヒットしないので、今後チュートリアルで別のやり方が登場するかも..?

 Micropost.where("user_id = ?", id)


request.referrer

リクエストが発行されたページのURLを返してくれる。フレンドフォワーディングではrequest.urlを使用して飛ぼうとしていた先のURLを拾っていた。注意として、nilを返してくる場合もあるので、||でデフォルトのジャンプ先を指定してあげておくと良い。

redirect_to request.referrer || root_url


Rails5の新機能としてredirect_back(fallback_location: root_url)と書くと上のコードと同じ動きをしてくれる。

テストでwill_paginateが表示されない

この賞に限ったことではないが、テストでdiv.paginationに一致する部分を探しても見つからないことがあった。ブラウザ上では確認済みだったので原因探しに困った。結果として、ページネートするコンテンツが1つしか生成されていなかったのが原因。テスト時のページ表示前にダミーデータをたくさん作ってあげることで解決する。(1ページのデフォルト値よりも多く)

CarrierWave

画像アップローダのgem

Mini_Magick

画像のリサイズができるようになるGem. ただ、ImageMagickを使用することになるので、脆弱性とか心配? MiniMagick自身の役割としては、本体にインストールしたImageMagickRubyの橋渡しになってくれるGem ImageMagickは様々な画像に対応できているがゆえにガバガバになっているイメージがあるので、載せられる画像のフォーマットを制限する。チュートリアルではCarrierWaveを利用している。

MIMEタイプ

データのタイプを指定したりする。元々は、テキストしか扱えない電子メールで様々なフォーマットのデータを扱えるようにするために使用されている。チュートリアルでは画像の拡張子をクライアント側で限定するために使用。