html配下のJavaScriptファイルからcgi-bin配下のPythonファイルを呼び出そうとしたら何重にも罠にハマったので記録。
構成とかソースはだいぶ簡略化してるけどこんな感じです。
環境
CentOS 7.4
Apache 2.4.6
構成
┣cgi-bin
┃ ┣main.py←これを呼び出したい
┣html
┃ ┣index.html
┃ ┣index.js←呼び出し元
ソースコード
index.js
$.ajax('/cgi-bin/01/main.py', { type: 'post', dataType: 'json', data: semdData }) .done(function (data) { //成功した場合の処理 .fail(function () { //失敗した場合の処理 });
main.py
#!/home/developer/anaconda3/ … /python3 import json import cgi import sys recieve_data = sys.stdin.readline() recieve_json = json.loads(recieve_data) …これを実行したら下記エラーが出た
[cgi:error] [pid 18656] [client xx.xx.xx.xx:50947] AH01215: (13)Permission denied: exec of '/var/www/cgi-bin/main.py' failed, referer: http://yy.yy.yy.yy/01/
犯人捜しへ
容疑者① ファイルのパーミッション
読んで字の如く、パーミッションが足りないのかな?と思い確認
-rwxr-sr-x. 1 apache apache 4041 Apr 17 16:11 main.py
⇒所有者apache、権限2775で問題なさそう!無罪!
しかし実はこいつも犯人グループのうちの一人だということが後々判明する。
容疑者② SELinux
調べてると①の次によく出てくるのがこれ。
試しにSELinuxを一時的に無効化して、呼び出せるか確認。
setenforce 0⇒変わらず。そもそもCGIスクリプトの置き場所をデフォルトにしていれば基本問題ない。
上記エラーで検索して出てくるのは①か②で、同様のエラーが出ていた人も皆これで解決している。
詰んだ・・・・・・・?
容疑者③ Python本体の権限 ←主犯
そこから数時間、ウンウン悩んだ末にふと気づいた。呼び出し先コード1行目↓
#!/home/developer/anaconda3/ … /python3このパスのPythonで実行してね、を示す記述なのだが
…これ、apacheユーザ実行権限あったっけ…?
なかった。これは怪しい。
Pythonのパーミッションを変更する
ということでPythonがapacheユーザで利用可能なように権限を変えてみる。今回はdeveloperというユーザのホームディレクトリ配下にAnacondaを入れていたので、Anacondaディレクトリ内にあるPythonに対して、他のユーザは実行権限がなかった。
そのため、その他ユーザーの実行権限を付与。
lrwxrwxrwx. 1 developer developer 9 Apr 11 19:14 python3 -> python3.8※ちなみに、権限付与したいファイルの上位ディレクトリにも実行権限が付いている必要がある。
付与したい権限が実行だろうと読み取りだろうと編集だろうと、親やその親には実行権限さえついていればOK。
さてこれで行けるのでは?実行!
⇒ダメでした。
PythonにもSELinuxの設定をする
いい加減絶望してきたが、ここでもう一度SELinuxを無効化して実行してみたら、いけた。
ここさえクリアできればゴールということが分かって、ちょっと元気が出てきた。
で、このSELinux、無効化してしまえば楽だしそれを勧めているサイトもある。
ただ一応公開サーバだし、個人サイトとはいえ乗っ取られて荒らされたら嫌な気分だし打てる手は打っておきたい。タダだし。
ということで、パーミッション変更したPython本体に対して、同様にSELinuxの権限も設定してみた。
SELinuxについては大御所が分かりやすく情報をまとめてくれているので、詳しい話はそちらで。
監査ログ(/var/log/audit/audit.log)に原因となっているファイルなどが書かれているので参考にします。
とりあえず私は以下のように設定しました。
ls -Z lrwxrwxrwx. developer developer unconfined_u:object_r:httpd_sys_script_exec_t:s0 python3 -> python3.8 -rwxrwxr-x. developer developer unconfined_u:object_r:httpd_sys_script_exec_t:s0 python3.8
※こちらもパーミッション同様に上位ディレクトリにも権限が要るようです。
また、今回はPythonスクリプトファイルの中で外部APIの呼び出しを行っており、これもSELinuxの初期設定だと引っ掛かります。
setsebool -P httpd_can_network_connect=1
で外部ネットワークとの接続を許可しておきます。
ここまで設定したところ、無事成功!スッキリ。
0 件のコメント:
コメントを投稿