以前の記事でcurlの使い方について書きましたが、今回はcurlを実践的に使っていきます。
curlでページアクセスしたい場合、単純なアクセスだけであれば以下のようにするだけで簡単にアクセスできます。
curl https://syachiku.net
ただし、実際にはアクセスしたいページにログオン認証がされており、その認証をクリアしないとアクセスできない場合が多くあります。 社内のシステムにおいても基本的には認証が必要とされているのではないでしょうか。
Pythonを使うと比較的簡単に実装することができるのですが、今回は素のLinuxで実現したいのでcurlを使います。セッション管理の機能などがないので少し手間ですが、できないことはないです。
今回はそのようなログオンのフォーム認証をクリアしながらcurlでアクセスする方法についてまとめました。
最近はほぼ間違いなくログオンで実施されているcsrf対策についてもクリア
するようにします。
1. curlでログオン認証をクリアするために利用するオプション
はじめにcurlでログオン認証をクリアするために利用するオプションと意味について確認していきます。
もし分からない、詳細をもっと知りたいといった場合には以下の記事でを参照しながら進めてください。
1.1. POSTでのパラメータしてのアクセス(-F)
- フォームログオンなどでPOSTを利用する場合に使います。
curl -F "user=value1" -F "passwd=value2" http://www.hogehoge.com/logon
1.2. クッキーを指定してアクセスする(-b)
- cオプションで保存したクッキーファイルを利用してアクセスすることができます。
$ curl -b <cookie file名> http://www.hogehoge.com/
1.3. リダイレクトも追うように(-L)
- もしアクセスしたページがリダイレクトされた場合に、リダイレクト先のURLを表示します(ログオン認証などでよく使います)
$ curl -L <cookie file名> http://www.hogehoge.com/
1.4. レスポンス関連(-Iと-i)
//レスポンスメッセージのボディのみ
$ curl http://www.hogehoge.com/
// ステータスラインとヘッダのみ(-I)
$ curl -I http://www.hogehoge.com/
//すべてのレスポンスメッセージを表示(-i)
$ curl -i http://www.hogehoge.com/
1.5. 結果をファイルに書き出す(-o)
- 結果をファイルに書き出します
- ダウンロードファイルを指定するのを同じオプションです
$ curl http://www.hogehoge.com/ -o <file名>
- 何も表示させたくない場合(/dev/nulへ送る)
$ curl http://www.hogehoge.com/ -o /dev/null
1.6. 指定した文字列だけを表示する(-w)
- レスポンスコードだけ取得したい場合には以下の様に利用します
$ curl http://www.hogehoge.com/ -o /dev/null -w '%{http_code}\n'
1.7. 進捗やエラーを表示しない(-s)
- シェルスクリプトなどで結果が表示されるのが邪魔な場合に利用します。
$ curl -s http://www.hogehoge.com/
1.8. 詳細をログ出力(-vもしくは–verbose)
$ curl -v http://www.hogehoge.com/
2. 今回のログオン認証をクリアする例
今回はコンテナで構築しているローカルPC内にあるgitlabをサンプルとして使います。
なお、curlを使ってインターネット上にあるサイトにアクセスする際には色々と注意してください。
2.1. ログオン認証をクリアするまでの流れ
まずは、ログオン認証をクリアするまでの流れについて確認します。
※ログオン認証をクリアしていない場合には、未認証とみなされるため、全てログオンページにリダイレクトされます(302)
- ログオンページに
GET
でアクセスしてcookieを受け取る
- ログオンページ内の
csrf tokenの値を取得
する - 1で得たcookieを添えたうえで再度ログオンページアクセスする。さらにユーザ名やパスワード、csrf tokenなどの値を設定して
POST
でアクセスしてログオン認証を実施する。そして再度認証が成功したcookie
を受け取る - 3で得たcookieを添えた上でログオン後のページにアクセスする
3. ログオンページ構成を解析する
では、実際にページを解析する方法について説明していきます。
最初にするべきことはログオンページ構成を確認することです。 やり方としてページソースを解析しながら進める
ことでももちろん問題ありませんが、今回はChromeの開発者ツールで通信の中身を見ながら解析
をしてみます。
3.1. フォームで利用するユーザ名とパスワードなどのパラメータを確認する
Ctrl+Shift+i
でChrome開発者ツールを起動します。 Gitlabのログオンページを開いてから実際にログオンしてみます。
ログオンに成功した際のパラメータを見てみます。
Network
を選択したらName
にあるsign_in
を選択します。
下のほうにあるForm Data
を確認してください。 その中に今回のログオンで利用したパラメータが何なのかが表示されています。 具体的には以下のパラメータです。
- authenticity_tokens
- user[logon]
- user[password]
- user[rember_me]
また、General
の部分を見るとStatus Code
が302
でリダイレクトされていることが分かります。
3.2. csrf対策で送信されているパラメータを確認して取得する
では次にauthenticity_tokens
で渡しているパラメータの取得方法についてです。
csrf token
の値を取得するにはログオンページのソースファイルを見る必要があります。
ソースを開いてcsrf
で検索すると以下のような部分があります。この値がcsrf token
です。 アクセスするタイミングで毎回値は変わります。
<meta name="csrf-param" content="authenticity_token" />
<meta name="csrf-token" content="Dc/t5Bp8jLKDnKc6g3ldvwcVO1Q7+XpbfQB27uelheTdxqLrRk6Qja4XKT0N/9b1vN3fMjvcCJa/WdwEazsf6g==" />
4. crulでのログオン認証ページにアクセスする
では、パラメータが分かったところで以下の処理を実装していきます。 私の環境は以下の通りです。
gitlab_url="[http://xxxxxx](http://192.168.10.31)"
gitlab_user="root"
gitlab_password="pass"
1. ログオンページにGETでアクセスしてcookieを受け取る
2. ログオンページ内のcsrf tokenの値を取得する
3. 1で得たcookieを添えたうえで再度ログオンページアクセスする。
4. さらにユーザ名やパスワード、csrf tokenなどの値を設定してPOSTでアクセスしてログオン認証を実施する。そして再度cookieを受け取る
5. 3で得たcookieを添えた上でページにアクセスする
4.1. ログオンページにGETでアクセスしてcookieを受け取る
まずは初回のログオンページにアクセスします。この時にcookieファイル
を保存します。
curl -c cookie01.txt -s -L -X GET "http://192.168.10.31/users/sign_in"
そうするとcookieファイル
が新規で作成されることが確認できます。
4.2. ログオンページ内のcsrf tokenの値を取得する
次にcsrf token
の値を取得します。 先ほどのソースファイルを確認していてcsrf-token
の行をgrepを使って抽出します。
curl -c cookie01.txt -s -L -X GET "http://192.168.10.31/users/sign_in" | grep csrf-token
<meta name="csrf-token" content="Y0SkL8y9vlwHXTrzclHhm9boPjAHsFqeny/qOoSRQ68u4GK+EitoGT+XPxso+95nlEPYB0pSFUEKrn1h0KglSw==" />
で、さらにsedでいらない部分を消しちゃいます。
curl -c cookie01.txt -s -L -X GET "http://192.168.10.31/users/sign_in" | grep csrf-token | sed -e 's/.*content\=\"//g' | sed -e 's/\" \/.*//g'
3Tha+3kMshjgVwLFydJ5lMeyZgg/xJqFQL5FSdWvvCzSiJfd8qSDwTTgdOvhSrbVbSUaPOyOyqELNDcyD/DRVw==
4.3. 先ほどのcookieを添えたうえで再度ログオンページアクセス/ログオン認証
先ほどのcookie01.txt
を使って、ログオン認証を試してみます。 また、今回の認証に成功した時に保存されるcookieファイルとしてcookie02.txt
を保存するようにします。
curl -b cookie01.txt -c cookie02.txt -s -L -F "user[login]=root" -F "user[password]=P@ssw0rd" -F "user[remember_me]=0" -F "authenticity_token=3Tha+3kMshjgVwLFydJ5lMeyZgg/xJqFQL5FSdWvvCzSiJfd8qSDwTTgdOvhSrbVbSUaPOyOyqELNDcyD/DRVw==" "http://192.168.10.31/users/sign_in"
もし、ログオン認証に成功した場合にはcookie02.txtに以下の行(known_sign_in
の部分)が追加されているはずです。 cookie01.txt
とcookie02.txt
のサイズも見比べてみて下さい。
#HttpOnly_192.168.10.31 FALSE / FALSE 1627794758 known_sign_in UnV3MnkveGdReTdIOEs5MXRBY3FPM252bm80cUtIQUFtNCsxMWV4R0ZLQ3ZGY1lyVGdjcjlMbU92WDdQSU1nenFIYjBualdzWER6bTAyQkZTQXVHaTRlV0VWWGNuOHlvcXc1SU1McHNTcGJ5amxjaGNnYUJLaTZOUWhaWEtJdXEtLWlZQ1JqY2xCZjRpdE9QY05LdllFemc9PQ%3D%3D--8f29a2a382a02e3b643428e2b0b5e605857453b8
4.4. 認証cookieを添えた上でページにアクセスする
では最後に認証に成功した際のcookieであるcookie02.txtを添えてページにアクセスすることができます。 こんな感じですね。
# curl -b cookie02.txt -I -X GET "http://192.168.10.31/admin/projects"
HTTP/1.1 200 OK
Server: nginx
Date: Sun, 18 Jul 2021 05:17:13 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: max-age=0, private, must-revalidate, no-store
Etag: W/"f2c2fda319a936ed7f3185ee4b25ed0f"
Pragma: no-cache
Referrer-Policy: strict-origin-when-cross-origin
X-Content-Type-Options: nosniff
X-Download-Options: noopen
X-Frame-Options: DENY
X-Permitted-Cross-Domain-Policies: none
X-Request-Id: ggiHdTXmOk
X-Runtime: 0.374683
X-Ua-Compatible: IE=edge
X-Xss-Protection: 1; mode=block
Strict-Transport-Security: max-age=31536000
Referrer-Policy: strict-origin-when-cross-origin
ちなみに、cookie02.txtを指定しない場合には以下のように302
でサインインページにリダイレクトされる形になります。
[root@gitlab curl_test]# curl -I -X GET "http://192.168.10.31/admin/projects"
HTTP/1.1 302 Found
Server: nginx
Date: Sun, 18 Jul 2021 05:18:20 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 100
Connection: keep-alive
Cache-Control: no-cache
Location: http://192.168.10.31/users/sign_in
Set-Cookie: experimentation_subject_id=eyJfcmFpbHMiOnsibWVzc2FnZSI6IkltSXpNelprWmpoakxUZGpNRGt0TkRnMVlpMWlNRFZtTFRBME9UUm1ORFV6WVdGbVppST0iLCJleHAiOm51bGwsInB1ciI6ImNvb2tpZS5leHBlcmltZW50YXRpb25fc3ViamVjdF9pZCJ9fQ%3D%3D--b728a632acbe94c7c47d8bc697c02275df6bd599; path=/; expires=Thu, 18 Jul 2041 05:18:20 -0000; HttpOnly
Set-Cookie: _gitlab_session=48e8ca606e7042ff7d40a947b03c5c76; path=/; expires=Sun, 18 Jul 2021 07:18:20 -0000; HttpOnly
X-Request-Id: Fduw65opLu
X-Runtime: 0.018545
Strict-Transport-Security: max-age=31536000
Referrer-Policy: strict-origin-when-cross-origin
5. まとめ
今回はパーツ単位で解析したので、一部手動での作業が発生しましたが、シェルスクリプトの形にすればGitlabページへのアクセスを自動かする事もできます。
curlでログオン認証するのは場合にもよりますがこのやり方に従ってうまくいけば簡単に実現できるかと思います。
Pythonのオススメ勉強方法
私がオススメするPython初心者向けの最初に購入すべき書籍は「シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全」です。
シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全
この書籍は実際にシリコンバレーの一流エンジニアとして活躍している酒井潤さんが書いた本です。
内容も初心者から上級者までまとめられており、各Lessonも長すぎずに分かりやすくまとめられているので、初心者の方にもおすすめです。
シリコンバレー一流プログラマーが教える Pythonプロフェッショナル大全
今回は以上となります。
コメント