独学!Webサイト構築日誌

35日目:昨晩は暖かかったね。

8:00

昨晩は少し暖かかったので、ぐっすり寝れました。
目標は故知覧。
  1. phpセキュリティを再度考える。
  2. お問い合わせフォームに画像認証追加。

11:00

ザックリと2回通り読んだので、昼飯食ってから頑張る。

余談ですが、冗長な防衛対策が多重防御になるというのは、面白い表現だな~と。



12:30

1.phpセキュリティを再度考える。

現在は画面にエラー内容が直接表示される状態で、攻撃者から中身がどうなっているのか推測されやすい。
php本体で設定することも可能ですが、サイト自体大きくなく、個人で管理しているので.htaccessで設定しようと思います。
参考サイトはコチラコチラ



...が、下記のように記述したところ、全くダメでした。
            
.htaccess ※一部抜粋。
php_flag display_errors Off ←画面上のエラー無し。
php_value error_reporting 32767 ←全部のエラー表示してね。
php_flag log_errors On ←エラーのログ要る。
php_value error_log "◆◆◆" ←エラーの保存先。
            
        

ココに「httpd.conf でAllowOverrideの設定を忘れないように 設定しないと.htaccessでphp_flagとphp_valueが使えません。」との記述があるように、別途設定が必要なんでしょう...。

...が、複雑過ぎて脳とスキルが追いついていかないので、ひとまずphpファイルへ個別に設定していきます。

            
ini_set('display_errors', 'Off'); //エラー画面非表示
ini_set('error_reporting', E_ALL); //エラーレポート全種類
ini_set('log_errors', 'On'); //ログ要る。
ini_set('error_log', '◆◆◆'); //保存先
            
        



14:00

普通にエラー表示されるし、データは保存されないんだけど、どういうこと???w

もう分かんないよ、パトラッシュ...



先に別の部分を修正。
php内部を見せない仕様にしました。
            
.htaccess 一部抜粋。
<Files ~ "^\.ht">
deny from all
</Files>
<Files ~ "\.php$">
deny from all
</Files>
            
        



14:30

ミツケタァアアアアアアアアアアアアアアン!!
display_startup_errors と display_errors は別物みたいですね。
            
php ※一部抜粋。
ini_set('display_startup_errors', 'Off'); //エラー画面非表示
            
        



出来たと思ったらやっぱり出来てなかったという罠。



え、本当に分からん。
何で?普通にエラー表示されるし、保存はされないし。
いじけて先に画像認証やっちゃう。

2.お問い合わせフォームに画像認証追加。

現在は文字列さえ入っていればデータ送信できるので、大量のスパムが届く可能性がある。
また、画像認証の試行回数/時間制限を加えることで、総当たり攻撃を回避する。

17:00




phpが更新されねぇじゃねぇかぁあああああああああああああああああ!!!



...と、あと一歩の所でPCを破壊するところでしたが、opcache_reset()見つけました。

18:00

ひとまず画像の表示は出来た。

↓ 実装例 ↓
check
※画面を再読み込み(F5)すると画像が自動的に変わります。

ここまで来れば、「return $textBody;」で値を返しているので、これと合致しているか確認するだけです。
...とでも思ったかー!て言われてるぐらいエラー吐く。



hidden使って実装しようと思いましたが、セキュリティ的に弱いらしいので、sessionを使いたいのですが、上手く行かない。
ひとまず夕飯食べてから考える。



20:00

今度こそ出来た!
            
html ※contact.html 追加分
<?php include("../php/hiraganaCheck.php"); ?>
<input class="messageInput" id="mHiragana" type="text" name="mHiragana" placeholder="ひらがなで入力" onchange="reCheck()"><br>


php ※確認用画像の作成。
<?php
    $im = imagecreatefromjpeg('../img/passBack.jpg');//ベース画像設定
    $textColor= imagecolorallocate( $im, 0, 0, 0);
    $font = '../php/HGRSMP.TTF';
    $textHiragana='あいうえおかがきぎくぐけげこごさざしじすずせぜそぞただちぢつづてでとどなにぬねのはばぱひびぴふぶぷへべぺほぼぽまみむめもやゆよらりるれろわをん';
    $textPart = '';
    $textBody = '';
    for($i=0; $i<5; $i++){ //5文字入れる
        $textPart = mb_substr($textHiragana, mt_rand(0, mb_strlen($textHiragana) - 1), 1,"UTF-8");
        $kakudo = mt_rand(-15, 15);
        imagettftext($im, 25, $kakudo, 25+(40*$i), 35, $textColor, $font, $textPart);
        $textBody = $textBody. $textPart;
    }

    // Content-Type を設定して、画像データを出力
    imagejpeg($im, '../img/passText.jpg');
    echo '<img class="testttttttt" src="../img/passText.jpg" alt="">';
    file_put_contents('../other/pass.txt', $passText, LOCK_EX); //判定用
    echo '<img class="passText" src="../img/passText.jpg" alt="">';

    imagedestroy( $im ); // 後始末
    opcache_reset();//リセット これ無いと上手く更新されない。
?>


php ※contact追加分
$mHiragana = htmlspecialchars($_POST['mHiragana'],ENT_QUOTES);
$passText = htmlspecialchars(file_get_contents('../other/pass.txt'),ENT_QUOTES);

if ($mHiragana !== $passText) {
    $error = $error.'認証文字が違います。\nお手数ですが、最初から入力してください。';
}


css
/*お問い合わせフォーム*/
#contactForm .messageInfo{
  float: left;
  width: 20%;
  padding: 0.5rem;
  margin: 0 20px;
}
#contactForm .messageInput{
  width: 30%;
  padding: 0.5rem;
}
#contactForm .messageText{
  width: 50%;
  height: 10rem;
  padding: 0.5rem;
}
#contactForm .checkArea{
  padding: 0.5rem;
  margin: 0 20px;
}
#contactForm img.passText{
  height: 2rem;
  vertical-align: bottom;
}
#contactForm #mHiragana{
  width: 7rem;
  padding: 0.5rem;    
}
#contactForm .btnArea{
  text-align: center;
}
#contactForm .messageBtn{
  margin: 2rem 1rem;
  padding: 0.5rem 1rem;
  font-size: 100%;
}
            
        

21:00

cssも含め、予定通りのモノが出来て満足w
総当たり攻撃回避のやつも作っていく。

22:30

出来た...と思う。というのも、自力で総当たりを実行するのが難しいので...作るか。

検証用システム作った。
控えめに言って凄い迷惑なRPAなので、作り方は省略しますが、使ったソフトはコレです。
検証の結果、下記で期待通りの動きをしました。
            
php ※contact.phpの変更点抜粋。
$passText = htmlspecialchars(file_get_contents('../◆◆◆/pass.txt'),ENT_QUOTES);
$fTime = htmlspecialchars(file_get_contents('../◆◆◆/failureTime.txt'),ENT_QUOTES);
$ipAd = ip2long($_SERVER['REMOTE_ADDR']);
$fIP = htmlspecialchars(file_get_contents('../◆◆◆/ipAdress.txt'),ENT_QUOTES);

if($ipAd == $fIP){//IPアドレスと時間チェック
    if(time()-$fTime < 任意の制限時間 ){
        file_put_contents('../◆◆◆/ipAdress.txt', $ipAd, LOCK_EX); //判定用
        file_put_contents('../◆◆◆/failureTime.txt', time(), LOCK_EX); //判定用
        $error = '現在送信機能を制限させていただいております。\n時間を置いて再度お試しください。';
        echo '<script> alert("'. $error. '"); location.href="https://ki-luck.info/"; </script>';
    }else{
        goto mainMove;
    }
}
mainMove:
if ($error != '') {
    file_put_contents('../◆◆◆/ipAdress.txt', $ipAd, LOCK_EX); //判定用
    file_put_contents('../◆◆◆/failureTime.txt', time(), LOCK_EX); //判定用
    $error = $error. '\nお手数ですが、最初から入力してください。';
    echo '<script> alert("'. $error. '"); location.href="https://ki-luck.info/other/contact.html"; </script>';
            
        



23:00

既に判明している問題点として、「保存されている文字列は更新されているが、認証画像が更新されない時がある。」
中々問題だが、1時間程度頑張ったものの解決策が見つからなかったので、明日の課題とする。



作成日:2021/01/16 - 更新日:2021/01/26

≪ 34日目≪ 一覧に戻る ≫36日目 ≫

HOME > 日誌一覧 > 35日目:昨晩は温かかったね。