private tips

プログラミングとその他諸々の備忘録。

【bash】の while の中で read したいとき

 はじめに

bash で、while に入力用のファイルを一行ずつ読み込ませて処理の結果を表示するかしないかを対話形式で決めて表示する、というようなスクリプトを書いていて、躓いたので備忘録。

 

例として、次のようなテキストファイル ( IPアドレス ホスト名 ) があるとする。

f:id:zvub:20170211111728p:plain

今回やりたかったのは、このファイルを1行ずつ読み込んで、表示の際にIPアドレスの網掛け行うかどうかをキーボード入力により決定する、というもの。

 

当初の bash スクリプトの中身は以下。

#!/bin/bash

### Sub-shell verification code ###

HOME=/opt/scripts
TARGETS=${HOME}/sample.txt

while read LINE
do
ADDR=`echo $LINE | awk -F' ' '{print $1}'`
NAME=`echo $LINE | awk -F' ' '{print $2}'`
echo -e -n "Do you want to display the IP address ?(yes/no) : "
read -r ANSWER
if [ "$ANSWER" == 'yes' ] || [ "$ANSWER" == 'y' ] ; then
echo "IP address : ${ADDR} , Hostname : ${NAME}"
else
echo "IP address : xx.xx.xx.xx , Hostname : ${NAME}"
fi
done < $TARGETS

while にファイルをリダイレクトするかたちで読み込んで、

while の中で read する事で、IP アドレスを表示する際に網掛けを行ったり行わなかったりを決定して表示を行いたかった。

が、何も考えずに実行すると下のようになる。

失敗例

f:id:zvub:20170218110349p:plain

冒頭に示したテキストファイルを1行ずつ読み込んで処理を行っているわけだけど、一周目の while の中の read でテキストファイルの2行目が標準入力として読まれてしまっている。

結構ハマりました。

原因

 何が駄目だったのかというと、while ループにリダイレクトしているファイルが、標準入力扱いになるからだった。

UNIX系OSにはファイル・ディスクリプタと呼ばれるものがあり、それによって、プロセスとそれが利用するファイル等を結びつける役割を担っている。それぞれ

標準入力:0

標準出力:1

標準エラー出力:2

という風に、0 からの 3つが既に予約されている。

 

つまり、上記のスクリプトの場合、while do ~ done の後ろでリダイレクトしているテキストファイルが標準入力【0】に入るのに対し、while ループ内の read でも、受け取る入力が標準入力【0】であるために失敗した。ということになる。

 

対策

対策と呼べるほどでもないかと思うけれど、どうやって回避したのか、という結果のスクリプトが以下になる。

#!/bin/bash

### Sub-shell verification code ###

HOME=/opt/scripts
TARGETS=${HOME}/sample.txt

while read LINE <&3
do
ADDR=`echo $LINE | awk -F' ' '{print $1}'`
NAME=`echo $LINE | awk -F' ' '{print $2}'`
echo -e -n "Do you want to display the IP address ?(yes/no) : "
read -r ANSWER
if [ "$ANSWER" == 'yes' ] || [ "$ANSWER" == 'y' ] ; then
echo "IP address : ${ADDR} , Hostname : ${NAME}"
else
echo "IP address : xx.xx.xx.xx , Hostname : ${NAME}"
fi
done 3< $TARGETS

while read LINE の後ろ "<&3" と、末尾 done 句の後ろ "3<" に注目して欲しい。

ここで何を行っているかというと、

上記で説明した"予約済みのファイル・ディスクリプタ"以外のファイル・ディスクリプタ、3番を利用している、という記述になる。

つまり3番目のファイル・ディスクリプタにファイルをリダイレクトし、while read 部で3番目のファイル・ディスクリプタから入力を読み込む事により、「標準入力を使用しない」while 文になっているわけである。

そうすると安全に while の中で標準入力が扱えるようになり、以下のように想定した動作を行うことができるようになる。

f:id:zvub:20170218113458p:plain

 

対策として不十分な気がしないこともないけど、回避策としては十分かな、ということで備忘録でした。

 

 

 

Net-SNMP の設定について

所要でNet-SNMPの設定を行う機会があったので、備忘録。

 

***** Net-SNMP *****

以下ディレクティブ群は基本的に全て、

/etc/snmp/snmpd.conf にて設定する項目となる。

 

アクセス及びセキュリティに関する項目

■com2sec (アクセス制御に関する項目)

書式 :
# sec.name source community
com2sec <security-name> <source> <community-name>

●例
com2sec testLocal01 localhost testCommunity01
com2sec testNetwork01 192.168.x.x/24 testCommunity01

説明 :

セキュリティを定義する部分。

ローカルホスト 及び 192.168.x.x/24 に属するホストからの

snmpwalk コマンドによる情報の取得を許可する。

コミュニティ名は任意だが、概念的に言うと所謂「パスワード」のようなものなので、

推測が容易な名前にするのはセキュリティ上、よろしくない。

複雑で推測が困難な名前にするべきである。

 

■group (グループの定義)

書式 :
# groupName securityModel securityName
group <group-name> <snmp-version> <security-name>

●例
group localGroup v1 testLocal01
group localGroup v2c testLocal01
group localGroup usm testLocal01
group networkGroup v1 testNetwork01
group networkGroup v2c testNetwork01
group networkGroup usm testNetwork01

説明 :
グループを定義する部分。

com2sec で定義したセキュリティ名に対して、

「どのバージョンのsnmp通信を許可するか」を定義する部分。

バージョンは securityModel で指定し、それぞれが以下のように対応する。

SNMP version1 : v1
SNMP version2 : v2c
SNMP version3 : usm

 

グループ名は任意だが、接頭辞として

"ro(Read Only)" や "rw(Read Write)" のついた名前をよく見かけるので、つけるのが一般的?

つけると分かりやすくていいですね。

 

■view (SNMP で取得可能な情報の範囲を指定)

書式 :

# name incl/excl subtree mask(optional)

view <view-name> <type> <subtree> <hex mask value>

 

●例

view testView01 include .1.3.6.1.2.1.1

説明 :

MIB ツリーの取得範囲を決定する部分。ビュー名は任意。

"subtree" 列で指定したオブジェクトID を基準に情報を取得するよう定義する。

"type" を「included」とすると "subtree" で指定したOIDを含む範囲の指定となり

「excluded」とすると、"subtree" で指定したOIDの範囲外の指定となる。

"mask" は16進数で指定するマスク値の事で、8bitごとに":"で区切って指定する。

 

※例 : TCP に関する情報のみを取得したい場合

OID = 1.3.6.1.2.1.6 (MIB tree 参照) となる。

上記OIDのみ許可するため、マスクはOIDの数値の数だけ"1"をたてる。

1.3.1.6.1.2.1.6 = 1.1.1.1.1.1.1 = 1111 1110 = 0xfe となり

上記の例を用いると、結果的に以下のようになる

view testView01 include .1.3.6.1.2.1.6 0xfe

この状態で snmpwalk コマンドを発行すると、

TCPに関する情報のみが得られるようになる。

 

以下、実行結果例

# snmpwalk -v 2c -c testCommunity01 localhost .
TCP-MIB::tcpRtoAlgorithm.0 = INTEGER: other(1)
TCP-MIB::tcpRtoMin.0 = INTEGER: 200 milliseconds
TCP-MIB::tcpRtoMax.0 = INTEGER: 120000 milliseconds
TCP-MIB::tcpMaxConn.0 = INTEGER: -1
TCP-MIB::tcpActiveOpens.0 = Counter32: 60995
TCP-MIB::tcpPassiveOpens.0 = Counter32: 59025
...

MIB ツリーに関する記事は別の機会に。

 

 

access (アクセス許可に関する設定)

書式 :

# group context sec.model sec.level prefix read write notify

access <group-name> <context> <snmp-ver> <sec-level> <condition> <view-name> <view-name> <view-name>

●例

access localGroup "" any noauth exact testView01 none none

access networkGroup "" any noauth exact testView01 none none

 

※ v1 又は v2 を使用した場合、<context>, <sec-level>, <condition> は指定不可となるため、「"" any noauth exact」はほぼお決まり。

 

説明 :

事前に定義した group 情報や view の定義を用いて最終的にアクセスに関する設定を行う部分。

各パラメタ及び詳細については以下のようになる。

"group" : group 定義部で定義したグループ名を指定。

このグループ単位でアクセスの許可を定義することになる。

"context" : SNMP v3 を使用する場合のみ、事前に定義したコンテキストを指定する。

v1, v2 の場合は空文字""を指定。

"sec.model" : 使用するSNMPのバージョン。「v1」「v2c」「usm」「any」のいずれかを指定する。

"sec.level" : model が「usm」の時のみ「auth」又は「priv」を指定可能。

v1 及び v2 の場合は「noauth」となる。

"prefix" : 「exact」又は「prefix」のいずれかを指定。

「exact」はコンテキストとの厳密な一致(完全一致)を指し、「prefix」は部分一致?

"read" : 読み取りに関して事前に定義したビュー名を指定。

"write" : 書き込みに関して事前に定義したビュー名を指定。なければ「none」を指定。

"notify" : 通知に関して事前に定義したビュー名を指定。なければ「none」を指定。

 

 

システム情報に関する項目

■syslocation (システムの場所)

説明 :

syslocation <location>

の書式で記述する。例として、データセンターの2階、4号室内の

6列目のラックに格納された上から3番目の物理サーバを指す場合、

syslocation Datacenter2F, room03, Rack 6, Row 3

のようになる。

■syscontact (システムの連絡先)

説明 :

syscontact <contact information>

の書式で記述する。担当者が田中一郎氏の場合、例として下記の様な記載となる。

syscontact Ichiro.Tanaka <ichiro.tanaka@example.com>

■sysname (システム名)

説明 :

システム名に関する記載。指定が無い場合、ホスト名が設定される。書式は下記。

system <system-name>

 

 

以上。

MIBツリーの構造などその他細かい部分については、またの機会に。

 

 

 

 

RHEL7 系の NIC の命名規則について

RHEL7 ではデフォルトでNetworkManagerというサービスがenableになっている。

これが何をするかというと、ざっくりと説明するなら端末のNW構成を管理してくれるわけだが、NICの名前付けも管理している。

 

初期状態のRHEL7の /etc/sysconfig/network-scripts 以下を見ると、

6以前まで"ifcfg-ethX"だったファイル名が、"ifcfg-eXXXXXXX"とかになっている。

 

これを回避する手段は無いわけではないけれど、Red Hat的には思いっきり非推奨らしい。

 

しかし検証がてらやってみた。

 

手順としてはそんなにややこしくはなく、いくつかのパラメタを追記したgrubの設定ファイルを再構築するだけ。

 

*手順

( 注※ 検証はCentOS 7 で実施 )

 RHEL7 系においてデフォルトの命名スキーマを無効化する場合、/etc/default/grub を編集する必要がある。

編集箇所は GRUB_CMDLINE_LINUX パラメータで、該当の行の末尾にnet.ifnames=0 及びbiosdevname=0 を追記する。

追記前:

# nmcli connection show

 

コマンドでインターフェイスの接続状況を確認する。( オプションは connection=c, show=s に省略可能 )

f:id:zvub:20161204234018p:plain

 

次に grub の設定ファイルを編集し、再構築する。

f:id:zvub:20161205232205p:plain

以下が再構築用のコマンド

BIOS の場合

# grub2-mkconfig -o /boot/grub2/grub.cfg

UEFI の場合

# grub2-mkconfig -o /boot/efi/EFI/redhat/grub.cfg

 

f:id:zvub:20161206000227p:plain

この状態で

# nmcli connection show

コマンドを実行すると以下のようになった。

 

f:id:zvub:20161206000343p:plain

 

この状態で /etc/sysconfig/network-scripts/ifcfg-enp0s8 を編集し、デバイス名を変更。

f:id:zvub:20161206000451p:plain

ついでにファイル名も mv し、システムの再起動 ( この時点で NetworkManager の無効化も実施 ) 。

 

再起動後、NetworkManager が無効化され nmcli コマンドが使えなくなるので、

# ip address show

 で設定を確認すると、以下のようになった ( host名を変更&他2つのデバイスも同様に修正済み ) 。

f:id:zvub:20161206001242p:plain

これで以前のメジャーバージョンのOS同様、NICのデバイス名が "ethX" 系になり、可読性が上がる。

非推奨なのであまりやるべきではないのかもしれないが、NetworkManager も合わせて無効化してしまえば動作に特に影響は無さそうだった。

 

# NetworkManagerを無効化せずに設定の編集を続けていると、場合によってはネットワークの設定が吹っ飛んだりする。。。w

 

手探りで設定しつつのTipsなので、ここでは記載してないタイミングでOSの再起動等を挟んだりした気もするが、概ねこの設定で編集できるはず。

 

以上、1年以上ぶりの投稿でした。

めでたしめでたし

encode encode

※以下 Write up の為、ネタバレにります。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

解いたのはこれです。

http://ctf.katsudon.org/problem/9

ジャンル:misc

ポイント:90

 

 

解法

 

まず上の例を見る。

# regular UTF-8 encode
漢 -> \346\274\242
# encode twice in UTF-8
漢 -> \303\246\302\274\302\242 

なるほど。

「漢」をUTF-8で二回エンコードするとこうなるらしい。

ちなみに、二重エンコードというものがあるのを知ったのはこれを解く時でした。

ということは、問題文も二重エンコード??ってことでその問題文を見る。

c3:a3:c2:81:c2:8d:c3:a3:c2:82:c2:83:c3:a3:c2:81:c2:b7:c3:a3:c2:81:c2:a1:c3:a3:c2:82:c2:83:c3:a3:c2:83:c2:bc:c3:83:c2:a3:c3:82:c2:83:c3:82:c2:bb:c3:83:c2:a3:c3:82:c2:82:c3:82:c2:b6:c3:83:c2:a3:c3:82:c2:83:c3:82:c2:bb:e3:81:b5:e3:82:89:e3:81:a3:e3:81:90

ん?

なんだこれは。としばらく呆然。

で、以下の記事↓を見ると、「二重エンコード」のパラグラフに問題文に似たような英数字の配列があることが分かる。

d.hatena.ne.jp

 

どうやら二重エンコードされた結果、c3 a3 c2 ...
のようなビット列になるらしい。

とりあえず python

f:id:zvub:20151016165430p:plain

変数 str に一旦入れて普通に表示する。とりあえず「:」が邪魔、かつ16進表記にしたいのでちょっと整形して print してみる。

f:id:zvub:20151016165824p:plain

なんか出た。

「ふらっぐ」という文字が見えているので、どの辺からそうなってるのか、って事でutf-8 でデコードしてみる。

f:id:zvub:20151016170612p:plain

ちょっと見づらいので、後半部分だけ見る↓

f:id:zvub:20151016170822p:plain

変わってる。この、末尾の「¥u」から始まっている部分がutf-8でデコード出来た部分っぽい。

で、ここでちょっと閃いて「これ切り取っておけば良いのでは?」となる

ってことで、これをとりあえず切り離しておく。

f:id:zvub:20151016171212p:plain

second_str には切り離した部分「¥xbb」までを格納。

とりあえずもう一回この状態で print してみる。

f:id:zvub:20151016171444p:plain

また出てきた。

というわけで再び decode('utf-8') する。

f:id:zvub:20151016171754p:plain

なるほどこの部分。で前回と同様に、切り離して残った部分を print してみる。

f:id:zvub:20151016172232p:plain

「・ザ・」と出てくる

文字として読むことができたこの3箇所をまとめて print すると、

f:id:zvub:20151016172517p:plain

となるので、これで旗が得られたわけである。( print すると変数の間に半角スペースが挟まるので、フラグを投げる時は半角スペースを削除)

 

まとめ

・CTF力はまだ全然無いので、当初はutf-8でdecodeしたものを何か別の形式でdecodeするのでは…と試行錯誤して無駄に時間を食った。

・こういうのは解いてて楽しい。

・cheap cipher (revenge) を解くのが次の目標。あと ksnctf の 村人A も解きたい。

 

 

LPIC 102 の受験

 

お久しぶりの投稿です。

 

先日、LPIC 102 を受験してきました。

101は取得済みだったので、これでようやく Level 1 認定となります。

 

大げさに結論を言ってしまうと、なんだこれはという感じでした。

 

101の知識を持った状態で日を開けていたので、

102自体の勉強期間は実質2〜3週間程度。

あずき本、白本、今日の一題(Web)を用いて勉強しましたが、

当の試験本番では、上記の3つで見なかったコマンドや設定ファイルが3割〜4割ほど出ていたのではないかと思います(言い過ぎ?)。

 

点数は割りと危うい感じで、合格点が500点/800点ですが、600点での合格でした。

ネットワーク辺りは90%取れていたのでまあいいかな…という感じですが

セキュリティと管理業務(?)な部分が60%前後なので、もうちょっと取りたかったなあと。

実務経験ありきで解けそうな問題もちらほらとあったので、

11月の早期出社後に向けて Level 2 の取得も頑張りたいと思います!

 

 

CTFっぽい話(Double Blind)

 

※前回同様、以下ネタバレなので注意

 

 

 

 

 

 

 

 

 

 

 

解いた問題↓

ksnctf.sweetduet.info

ksnctf の #29 「Double Blind」。

 

問題

まず docx ファイルがあるので、とりあえず落とす。

f:id:zvub:20150713171107p:plain

で、普通に開いたら全英文の論文ぽい何かが出てくるので、ここで一旦イミフ状態に陥ります。

プロパティとか見るけど怪しい所は特にない。

で、タイトルの「Double Blind」をググると、「Double-Blind Review」(二重盲査読)という謎システムが出てきます。

これも全然意味が解らないので再びイミフ状態に陥ります。笑

 

解法

 

正直この問題が解けたのは運の力も大きいですが、解けたきっかけは「docx 拡張子」をググったことです。

doc 拡張子は word2003 まで使われていた拡張子ですが、

docx 拡張子は word2007 以降で使える拡張子です。

 

docx 拡張子の特徴をまとめると、

XML 形式であること(従来まではバイナリ形式)

・doc 拡張子に対する下位互換性が無い

・zip 形式である

などが挙げられます。

 

ここで注目したいのが3つめの「zip 形式である」という部分です。

つまり、拡張子を zip に書き換えると zip ファイルになるという事です。

 

というわけで、先ほど落として四苦八苦した「paper.docx」を「paper.zip」に書き換えます。

f:id:zvub:20150713173007p:plain

すると、いくつかのフォルダとファイルが現れます。

f:id:zvub:20150713173244p:plain

こういったオープンXML形式のドキュメントの本文は通常「document.xml」に保存されているので、word フォルダの中にあるソイツをとりあえず見に行く。

で、中身を見ていると”FLxAG_...”みたいな「いかにも」な部分があったので、邪魔なものだけ弾いて回答フォームに投げると正解でした。

 

 

まとめ

・運も実力のうち(?)

拡張子の深さを垣間見た

・校内のCTF勢の人口と協力できないつらみは反比例する

 

・参考

方法 : Office オープン XML 形式のドキュメントを操作する

 

Hardening 10 MarketPlace に参加して

 

6月20日、21日の二日間、 Hardening 10 MarketPlace - the 1st Event Of Hardening Project に参加してきました。

wasforum.jp

 

友人と2名枠での応募で、同じチームになった他4名は社会人、現役のエンジニアの方々でした。計6名。

結果は惨敗でしたが、色々と得たものは多かった気がします。

所属していたチームでは事前にインフラ側、アプリ側に分かれて対応することが決まっていたので、役割分担という面ではスムーズだったと思います。僕の担当はアプリ側でした。実際の競技中はというと、実力不足を痛感する内容でした。

ミッションがいくつか用意されており、その中の1つを担当する事になりましたが、結局最後までミッションをクリアする事はできませんでした。orz

 

今後の反省・復習の意も込め、競技中等々のWrite Upを少々。

*Day0

・事前に役割分担はできたけれど、競技中に使用したいツール等々の情報共有も出来ていれば良かった

・目grep担当が居ても良かった。笑

 

*Day1

+競技全体を通して感じたのは「エンジニアに求められるマネジメントスキル」

+何よりも「サービスの継続」が重要

+チーム内のコミュニケーション・意思疎通の大切さ

+対応だけでなく、報告も逐一

+想定できる脆弱性に対する攻撃に備えた事前の処置

+対処できないものはさっさと他人の力を借りる

 

 

マルウェアの早期対応

IME に Baidu が

Apache , Tomcat の Config 

・DDoS来た

iptables の設定

・利用しないはずのユーザの存在(競技は user1~6 までなのに user7 が居た)

・管理用アカウント or ユーザの初期パスワード変更

SSH接続できる?

・メモリを占有しているプロセスは無い?

・LBのチューニング

・開放されている不要ポートを確認し、閉じる

WordPressに大量のプラグイン

・WP-FileManager

struts脆弱性

・Fancybox の脆弱性

・MailPort

Windows AD の侵害

DNS の設定は?( キャッシュのTTL長すぎ)

XSS

SQL injection

・あからさまなフィッシングメール

・DBのレスポンス

・テストサイトあるから使え

・nginx ? pound ?

・SPDY の対応

 

*Day2

・他チームのプレゼンから知った攻撃(こんなのやられてたのか)

等々。。。

まあ色々ありましたが、とても貴重な体験が出来たと思います。

継続的に参加できるといいな、という感じです。

 

楽しかった!!