2024/12 CTOへの日報まとめ

日報




2024-12-2 ①

FuelPHPのInputクラスが持つ静的変数$inputについて知見を深めることができました。

  • データを一時的に保存するキャッシュ領域として機能する
  • この変数は、リクエストデータを効率的に扱うための内部的なデータ保存領域であり、リクエストデータが初めて取得されるタイミングで初期化される

以下、$input変数の役割と動作

(役割)

1、データ保存領域

  • Input::all, Input::param, あるいはその他のリクエストデータ取得メソッドが呼び出された際、初めて$inputが初期化される
  • 初期化後は、リクエストデータ(GET, POST, PUTなど)を統合したデータが格納される

2、効率的なアクセス

初回アクセス時にデータを構築し、以降のアクセスでは同じデータを再利用することで、パフォーマンスを最適化する

(動作)
// 初回アクセス時
$data = Input::all(); // この時点でstatic::$inputが初期化される

// 再アクセス時
$keyValue = Input::get(‘key1’); // 初期化済みのstatic::$inputを参照する

  • アクセス処理が効率化する
  • 複数の取得メソッド(Input::get, Input::param, Input::all)が、同じデータセット(static::$input)を参照することで、一貫性のあるデータを取得できる
2024-12-2 ②

\Input::getと$_GETのフィルタリングの有無について知ることができました。

\Input::get

  • FuelPHPが提供するセキュリティ機能を利用して、入力データに対するサニタイズやエスケープ処理を行う
  • これにより、XSSなどの攻撃から保護されやすくなる

$_GET

  • PHPのスーパグローバル変数であり、ユーザーが送信したデータをそのまま返す
  • フィルタリングやエスケープ処理は行われないため、未加工のデータが取得される
2024-12-3 ①

メールのスロットリングについて知ることができました

  • スロットリングとは、ISPがネットワーク上でのデータ流量を制御するために、メール送信速度や量を一時的に制限するプロセスのこと
  • 多くのISPは、一定時間内に受信できるメールの数に制限を設けている
  • 基準を上回る数のメールを配信するとスロットリング(受信制限)が発生する
2024-12-2 ②

fuel/core以下のInputクラスで定義されている静的変数 $php_input の役割について理解することができました。

  • 前提として、php://input はHTTPリクエストボディの生データにアクセスするために PHP が提供するストリームだが、このストリームは一度しか読み取れない
  • そのため、FuelPHP はこのデータを $php_input にキャッシュし、複数回アクセスできるようにしている
  • HTTP メソッドが POST, PUT, または DELETE の場合や、jsonやxmlなどの非フォームデータが送信された場合に、php://inputでデータ取得する
2024-12-4 ①

fuel/core/config/config.php 内の security.form-double-urlencoded がどういった設定なのか理解することができました。

  • form-double-urlencoded 設定は、二重エンコードされているかどうかを示すフラグとして機能する
  • trueの場合は、二重エンコードされているため、開発者は1回のデコードによりurlencodeされたデータを取得する。また2回のデコードにより元データを取得する
  • falseの場合は、一重エンコードのため、何もせずurlencodeされたデータを取得でき、また1回のデコードにより元データを取得することができる(追加のデコードが不要)

二重エンコードが発生するケース
・古いブラウザや特定のサードパーティ製ツールが送信するデータ

2024-12-4 ②

JSのlocation.searchについて理解することができました

  • location.search とは、JavaScript で現在の URL のクエリパラメータ部分を取得するプロパティ
  • クエリパラメータを処理する際に頻繁に使用される
  • クエリパラメータがない場合は、空文字を返す

https://example.com/page?name=John&age=30
console.log(location.search); // 出力:”?name=John&age=30″

2024-12-5

クエリパラメータの解析例や、追加,編集例について知ることができました。

(解析)
クエリパラメータをキーと値のペアに分解する際には、URLSearchParams を使用するのが一般的

const queryString = location.search; // “?name=John&age=30”
const params = new URLSearchParams(queryString);
console.log(params.get(‘name’)); // “John”
console.log(params.get(‘age’)); // “30”

URLSearchParams を使うと以下の操作が可能
・.get(key):指定したキーの値を取得
・.has(key):指定したキーが存在するか確認
・.forEach(callback):すべてのキーと値をループ処理
・.append(key, value):新しいキーと値を追加

(追加、編集)
const queryString = location.search; // “?name=John&age=30”
const params = new URLSearchParams(queryString);
params.set(‘name’, ‘Doe’); // 編集
params.append(‘city’, ‘Tokyo’); // 追加
console.log(params.toString()); // “name=Doe&age=30&city=Tokyo”

2024-12-6

リプレイ攻撃について知ることができました。

  • リプレイ攻撃とは、通信のセキュリティを脅かす攻撃の一種
  • 正規の通信を盗聴し、その内容を後から再送信することで、不正アクセスや悪意のある操作を試みる攻撃手法
  • この攻撃では、攻撃者は認証情報やトランザクションデータを再利用し、システムに対して正当なユーザーになりすましたり、不正なリクエストを行ったりする

リプレイ攻撃の流れ

1、通信の盗聴:攻撃者が通信を盗聴し、認証トークンやセッション情報、その他の重要なデータを取得する

2、再送信:盗聴したデータを再送信して、システムが再びその通信を正規のリクエストとして受け入れることを試みる

リプレイ攻撃のリスク

  • 認証の不正利用:攻撃者が取得した認証トークンを使い、正当なユーザーになりすます可能性がある
  • 取引や操作の再実行:攻撃者が既に実行されたトランザクションを繰り返し実行させ、システムやユーザーに損害を与える可能性がある
  • セキュリティの破壊:攻撃者が正規通信を再利用することで、セキュリティの信頼性が損なわれる

リプレイ攻撃の対策
リプレイ攻撃を防ぐためには、通信内容の再利用を防ぐ仕組みが必要。以下、一般的な対策

1、タイムスタンプ
 ・各リクエストにタイムスタンプを付与し、一定期間を過ぎたリクエストを拒否することで、古いリクエストの再利用を防ぐ

2、Nonce(ナンス)の利用
 ・リクエストごとに一意のランダム値(Nonce)を付加し、その値が再度使用されないことを確認する。これにより、同じリクエストが再送信されても拒否される

3、セッション管理
 ・セッションIDを利用して、正当なリクエストと不正なリクエストを区別する
 ・セッションごとに一意のIDを発行し、有効期限を設定することが重要

4、暗号化
 ・通信内容を暗号化することで、攻撃者がデータを盗聴できないようにする(HTTPSを利用する)

5、HMAC(ハッシュベースのメッセージ認証コード)
 ・各リクエストにメッセージ認証コードを付与し、そのコードを検証することで改ざんや再利用を防ぐ

6、CAPTCHA
 ・ユーザーが人間であることを確認するために、CAPTCHAを利用することで自動化されたリクエストを防ぐ

リプレイ攻撃の具体例

  • 認証APIへの攻撃:攻撃者が認証トークンを盗聴し、それを再送信してシステムに不正アクセスを試みる
  • オンライン決済の攻撃:支払いリクエストを再送信して、二重に決済を実行させる
2024-12-9 ①

AWSのNATゲートウェイは通常、Elastic IP (EIP) と一緒に設定されることが多いと思いますが、Elastic IPを指定しないケースも存在することを知りました。

Elastic IPを指定せずにNATゲートウェイを作成した場合、AWSは自動的にパブリックIPを割り当てる。この場合の動作は以下の通り。

  • 動的パブリックIPアドレスが割り当てられるため、NATゲートウェイが再作成されたり、障害で再配置された場合には、異なるパブリックIPが割り当てられる可能性がある
  • Privateサブネットのインスタンスからインターネットへ出ていくリクエストは、この動的なパブリックIPを通じて行われる

Elastic IPを使わない設定が利用されるケースは以下のような場合

  • 固定IPが必要なく、外部システムとのIP制限が不要な場合
  • コスト削減を目的とした場合

Privateサブネットからのリクエスト動作

  • Elastic IPを使わない場合でも、Privateサブネット内のリソースがNATゲートウェイを通じてインターネットにアクセスできる点は同じ
  • ただし、この場合はAWSが提供する動的なパブリックIPを使用して、NATゲートウェイが通信を肩代わりする
  • 動的IPが頻繁に変更されるリスクを許容できる場合、Elastic IPを割り当てない構成が有効な場合もある
2024-12-9 ②

イングレスとエグレスという用語について知りました。

  • イングレス(ingress):通信回線の方向性を表す概念の一つ。ある機器やシステム、ファイアウォールの外から内に向かう通信のこと
  • エグレス(egress):通信回線の方向性を表す概念の一つ。ある機器やシステム、ファイアウォール内のネットワークから外に向かう通信のこと
2024-12-10 ①

cloudformationテンプレートにて、Type: “AWS::EC2::Subnet”にて定義するサブネット定義において、MapPublicIpOnLaunchプロパティにtrue, falseを設定した際の挙動について理解することができました。

MapPublicIpOnLaunch: true

  • サブネット内に作成されるEC2インスタンスやその他のリソース(NAT Gatewayなど)が自動的にパブリックIPを割り当てられる
  • この設定により、インスタンスはインターネットに直接アクセスできる
  • 通常、パブリックサブネットとして構成されます

MapPublicIpOnLaunch: false

  • サブネット内のリソースには自動的にパブリックIPが割り当てられない
  • インターネットに直接アクセスできないため、インターネット接続が必要な場合は、NAT Gatewayやプロキシを利用する必要がある
  • 通常、プライベートサブネットとして構成される
2024-12-10 ②

検索URLに「&lr=-lang_ja」をクエリパラメータとして追加することで、日本語以外のサイトだけが検索結果として表示されることを知りました。日本語情報が少なく、英語情報にアクセスしたい際に、活用したいと思います。

2024-12-11 ①

rpmコマンドがどのようなコマンドか知ることができました。

  • rpmコマンドは、Red Hat系Linuxディストリビューション(RHEL、CentOS、Fedoraなど)で使用されるRPMパッケージ管理システムのコマンドラインツール
  • RPMは「Red Hat Package Manager」の略で、ソフトウェアパッケージを管理するためのツール
2024-12-11 ②

DBの接続上限数を示すmax_connectionsの設定を確認するコマンドを知ることができました。

SHOW VARIABLES LIKE ‘max_connections’;

2024-12-12

CORS(Cross-Origin Resource Sharing)プリフライトリクエスト(OPTIONS)について知ることができました。

  • CORS(Cross-Origin Resource Sharing)プリフライトリクエスト(OPTIONS)とは、Webブラウザがクロスオリジンリクエストを送信する前に、安全性を確認するために送信するリクエスト
  • この仕組みは、サーバーがリクエストの内容を許可するかどうかを判断するために利用される

プリフライトリクエストの特徴

1、HTTPメソッド:OPTIONS

  • プリフライトリクエストは、HTTPメソッドとしてOPTIONSを使用する
  • サーバーに、実際のリクエストが許可されるかどうかを尋ねる

2、リクエストヘッダー
プリフライトリクエストには以下のヘッダーが含まれる

  • Origin:リクエスト元のオリジン(スキーム、ホスト、ポート)
  • Access-Control-Request-Method:実際に実行するリクエストのHTTPメソッド
  • Access-Control-Request-Headers:実際に送信するカスタムヘッダー(必要な場合)

3、レスポンスヘッダー
サーバーがプリフライトリクエストを受け取ると、以下のヘッダーを含めて応答する

  • Access-Control-Allow-Origin:許可するオリジン
  • Access-Control-Allow-Methods:許可するHTTPメソッド
  • Access-Control-Allow-Headers:許可するカスタムヘッダー(必要な場合)
  • Access-Control-Max-Age:キャッシュの有効期間(秒)
2024-12-13

ALBのリスナールールでは、一つのルールに最大5つの条件しか設定できないことを知りました。そのため、特定のパスへのアクセスを7つのIPアドレスからのみ許可したい場合は、以下のように複数のルールに分割する必要があることを知りました。

ルール1
条件:4つのIPアドレス かつ 特定のパス

ルール2
条件:残りの3つのIPアドレス かつ 同じ特定のパス

2024-12-17

Reduxについて理解することができました。

  • Reduxは、状態管理のためのライブラリ
  • 主にReactなどのフロントエンドアプリケーションで利用され、アプリケーションの状態(データやUIの状態)を一元管理する役割を担う

Redux の基本概念

状態(State)
・アプリケーション全体のデータやUIの状態を表す
・Reduxでは1つの大きなオブジェクトとして管理される

アクション(Action)
・状態を変更するための「命令書」のようなもの
・単なるJavaScriptオブジェクトであり、何を行うかを示すtypeプロパティと、追加データを持つことが一般的。(例){ type: ‘INCREMENT’, payload: { value: 1 } }

リデューサー(Reducer)
・状態(State)とアクション(Action)を受け取り、新しい状態を返す「関数」
・状態をどのように変更するかを定義する
(例)
function counterReducer(state = 0, action) {
switch (action.type) {
case ‘INCREMENT’:
return state + action.payload.value;
case ‘DECREMENT’:
return state – action.payload.value;
default:
return state;
}
}

ストア(Store)
・状態(State)を保存し、アプリ全体に公開する中心的な場所
・ストアは以下の機能を持つ
 1. 現在の状態を取得する(getState)
 2. 状態を変更するためのアクションをディスパッチする(dispatch)
 3. 状態の変更を購読する(subscribe)

ディスパッチ(Dispatch)
・アクションをリデューサーに送るための仕組み
・ストアに対してアクションをディスパッチすると、リデューサーが実行されて状態が更新される

Reduxの流れ
1、UIやユーザー操作からアクションが発生する
2、アクションがディスパッチされ、リデューサーが呼び出される
3、リデューサーが現在の状態とアクションを元に新しい状態を計算して返す
4、ストアが新しい状態を保持し、状態の変更を購読しているUIに通知する
5、UIが自動的に再レンダリングされる

Reduxのメリット

  • 状態の一元管理:アプリケーションの状態を1つのストアで管理するため、状態の追跡やデバッグが容易になる
  • 予測可能な状態管理:状態の変更はアクション → リデューサーの流れで行われるため、状態の変化が予測しやすくなる
  • デバッグが容易:Redux DevTools などのツールを使って状態の変化やアクションを簡単に追跡できる
  • UIの再利用性向上:コンポーネント間で状態を共有しやすく、UIコンポーネントをより独立させることができる

Reduxの課題と解決策
ボイラープレートコードが多い
・アクション、リデューサー、ストアの設定に多くのコードが必要(→ Redux Toolkit を使用することで、よりシンプルに記述できる)

学習コストが高い
・シンプルな状態管理ならContext APIなどの代替手段もある

Redux Toolkit
Redux Toolkit は Redux の公式推奨ツールで、ボイラープレートコードを減らし、より使いやすくしたもの
RTK Query:データフェッチやキャッシュ管理を簡単に行う機能
createSlice:アクションとリデューサーをまとめて定義できる

まとめ
Redux とは、アプリケーションの状態を一元管理するためのライブラリ。状態管理が複雑になりやすい中規模〜大規模なアプリケーションでよく使われる。

Reduxの流れ
アクション → ディスパッチ → リデューサー → 新しい状態 → UI更新

2024-12-18

Reduxは、Reactの機能ではなく、独立した状態管理ライブラリであることを知りました。(したがって、React以外のフレームワークやライブラリでも使用可能)

Reduxの独立性
・Reduxはフロントエンドにおけるアプリケーション状態を一元管理するために設計されたライブラリであり、UIライブラリやフレームワーク(例: React、Angular、Vue)に依存しない

Redux の特徴

  • 純粋な JavaScript ライブラリ であり、UIライブラリに依存しない
  • 状態を管理し、アクションとリデューサーの仕組みで状態変更を行うアーキテクチャを提供
  • React では Redux と一緒に使う場合が多いが、Vue.js,Angular、さらにはVanilla JS のアプリケーションでも使える

React と Redux が結びついている理由

React 自体は状態管理に特化していない

  • React は UIライブラリ であり、コンポーネント内のローカル状態管理には強いが、アプリケーション全体の状態を管理する機能は提供していない
  • そのため、Redux のようなライブラリが必要とされる

Redux Toolkit と React-Redux

  • Redux を React で使いやすくするために公式ライブラリ react-redux が提供されている
  • React コンポーネントに状態やディスパッチを簡単に接続できる

React のコンポーネント指向との親和性

  • Redux で管理する状態を React コンポーネント間で効率よく共有できるため、親和性が高い
2024-12-19 ①

useLazyQueryについて理解することができました。

  • useLazyQueryとは、RTK Queryにおいてデータの取得(クエリ実行)を遅延させるためのフック
  • 通常のuseQueryフックはコンポーネントのマウント時に自動的にリクエストを実行するが、useLazyQueryを使用すると、任意のタイミングで手動でクエリを実行できる

useLazyQueryの特徴

1、遅延実行
・コンポーネントのマウント時にはクエリを実行せず、必要なタイミング(ボタンのクリックやイベント発生時など)でリクエストを送信する

2、トリガー関数
・useLazyQueryはトリガー関数を提供し、この関数を呼び出すことでクエリが実行される

3、状態管理
・データの取得状態(isLoading、isFetching、dataなど)もuseQueryと同様に管理できる

2024-12-19 ②

X-XSS-Protectionヘッダーについて知ることができました。

  • X-XSS-Protectionヘッダーは、ブラウザの組み込みXSS保護機能を制御するための HTTP ヘッダー
  • このヘッダーを利用すると、XSS 攻撃に対するブラウザ側のフィルタリング機能を有効にしたり、無効にしたりすることができる
  • ただし、近年のブラウザではこのヘッダーが非推奨とされる場合があり、最新のブラウザでは無視される可能性がある

一般的な設定値
・X-XSS-Protection: 1; mode=block
 ・XSS フィルタを有効にし、攻撃が検出された場合にページの表示をブロックする

・X-XSS-Protection: 0
 ・XSS フィルタを無効化する

2024-12-23 ①

Content Security Policy(CSP)について理解することができました。

CSPとは、ウェブアプリケーションで発生する可能性のあるXSS攻撃やその他のコードインジェクション攻撃を防ぐために、ウェブサイトやアプリケーションがブラウザに適用するセキュリティ機能の一つ。CSPはHTTPヘッダーやHTML内のmetaタグを使用して設定する。

CSPの基本的な仕組み
CSPを利用することで、ブラウザに対して次のような指示を与えられる

  • どのソースからスクリプトを読み込むことが許可されているか(例: 自サイトのスクリプトのみ許可する)
  • 画像やフォント、CSSなどのリソースをどこから読み込むことができるか
  • インラインスクリプトやインラインCSSを許可するかどうか

CSPを設定することで、外部の攻撃者が意図的に仕込んだスクリプトが実行されるのを防ぐことなどができる

(Laravelのミドルウェアにて、レスポンスにCSPヘッダーを追加する例)
namespace App\Http\Middleware;
use Closure;
class ContentSecurityPolicyMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);

$csp = “default-src ‘self’; script-src ‘self’ https://trustedscripts.example.com; style-src ‘self’;”;

$response->headers->set(‘Content-Security-Policy’, $csp);

return $response;
}
}

2024-12-23 ②

Promise.raceについて知ることができました。

Promise.race
・複数のPromiseのうち、最初に解決または拒否されたものの結果を返す

const promise1 = new Promise(resolve => setTimeout(() => resolve(1), 1000));
const promise2 = new Promise(resolve => setTimeout(() => resolve(2), 500));

Promise.race([promise1, promise2]).then(result => {
console.log(result); // 2
});

2024-12-25 ①

Promise.allSettledについて知ることができました

・成功・失敗に関係なく、すべてのPromiseの結果を配列で返す。

const promise1 = Promise.resolve(1);
const promise2 = Promise.reject(“エラー”);

Promise.allSettled([promise1, promise2]).then(results => {
console.log(results);
});

// [
// { status: “fulfilled”, value: 1 },
// { status: “rejected”, reason: “エラー” }
// ]

2024-12-25 ②

JSの下記構文を知ることができました。
(error.detail && { detail: error.detail })

簡潔な条件式
・error.detail がtruthyの場合、オブジェクト { detail: error.detail } を生成する
・error.detail がfalsyの場合、式全体がfalseを返す
・error.detail が undefined または null でもエラーを起こさずに処理できる

const error = { detail: “Some error occurred” };
const result = error.detail && { detail: error.detail };
console.log(result);
// => { detail: “Some error occurred” }

const noError = {};
const result2 = noError.detail && { detail: noError.detail };
console.log(result2);
// => false