質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.37%
PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

XSS

XSS【クロスサイトスクリプティング】は、 ソフトウェアのセキュリティホールの一つで、Webサイトに脆弱性が あることからその脆弱性を利用し攻撃する手法です。 主に、入力フォームなどから悪意あるスクリプトを挿入し 該当ページを閲覧したブラウザ上でそのスクリプトを実行します。

CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

Q&A

解決済

3回答

8530閲覧

【PHP】簡易掲示板の作成② 記述法、セキュリティについてアドバイス頂けないでしょうか。

tnk_fuku

総合スコア42

PDO

PDO(PHP Data Objects)はPHPのデータベース抽象化レイヤーです。

セキュリティー

このタグは、コンピューターシステムの安全性やデータの機密性に関連したトピックの為に使われます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

XSS

XSS【クロスサイトスクリプティング】は、 ソフトウェアのセキュリティホールの一つで、Webサイトに脆弱性が あることからその脆弱性を利用し攻撃する手法です。 主に、入力フォームなどから悪意あるスクリプトを挿入し 該当ページを閲覧したブラウザ上でそのスクリプトを実行します。

CSRF

クロスサイトリクエストフォージェリ (Cross site request forgeries、CSRF)は、 外部Webページから、HTTPリクエストによって、 Webサイトの機能の一部が実行されてしまうWWWにおける攻撃手法です。

3グッド

2クリップ

投稿2017/04/29 10:12

簡易掲示板をつくる中でうまく動作せず先日質問し、その後も構成を変えるなどしてとりあえず自分が思ったように動くものにはなりました。
過去の質問はこちら

そこで完成したものをご確認頂き、下記の点についてアドバイスを頂ければと思います。

  • 記述方法に誤りはないか
  • セキュリティ対策は十分か

---バージョン---
MariaDB 10.1.21
PHP 7.0.15

---ファイル構成・機能---
index.php(投稿一覧表示、新規投稿フォーム)
confirm.php(投稿内容確認画面)
complete.php(書き込み完了画面)
db_info.php(データベース接続情報)
encode.php(エスケープ処理)
error.php(エラー表示)

---テーブル定義---
テーブル名:bbsdata
カラム構成:

nametitledaymsg
varchar(255)varchar(255)datetimetext
投稿者名投稿タイトル投稿日時投稿内容

---実装したセキュリティ対策---
XSS対策(エスケープ処理)
CSRF対策(トークンの使用)
SQLインジェクション対策(PDOの使用)
(セキュリティ対策についてはしっかりと知識をつけたいと思っています)

以下、ファイルです。

db_info.php

PHP

1<?php 2$dsn = 'mysql:host=localhost; dbname=bbs;charset=utf8'; 3$user = 'bbsuser'; 4$pass = 'bbspass';

encode.php

PHP

1<?php 2function h($str){ 3 return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); 4}

error.php

PHP

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>エラー表示</title> 6</head> 7<body> 8 <p> 9 <?php echo $error; ?> 10 </p> 11</body> 12</html>

index.php

PHP

1<?php 2session_start(); 3$_SESSION['token'] = bin2hex(random_bytes(32)); 4require_once('db_info.php'); 5require_once('encode.php'); 6 7try { 8 $pdo = new PDO($dsn, $user, $pass); 9 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 10 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 11} catch (PDOExeption $e){ 12 $error = 'データベース接続に失敗しました: ' . $e->getMessage(); 13 include 'error.php'; 14 exit(); 15} 16try { 17 $sql = "select * from bbsdata order by day desc"; 18 $result = $pdo->query($sql); 19} catch (PDOExeption $e) { 20 $error = 'データの取得に失敗しました:' . $e->getMessage(); 21 include 'error.php'; 22 exit(); 23} 24?> 25<!DOCTYPE html> 26<html lang="ja"> 27<head> 28 <meta charset="UTF-8"> 29 <title>簡易掲示板</title> 30 <style type="text/css"> 31 body { 32 background-color: #E1EDFF; 33 line-height: 1.5rem; 34 } 35 </style> 36</head> 37<body> 38<h1>簡易掲示板</h1> 39<!-- 投稿フォーム 40こちらからconfirm.phpにポストしたものをconfirm.php内ではセッションに格納しており、未入力欄があった場合にindex.phpに戻っても入力していた項目は保持されるよう、valueにセッションを入れました 41--> 42<form action="confirm.php" method="post"> 43 名前:<input type="text" name="name" value="<?php if(isset($_SESSION['name'])){ echo h($_SESSION['name']); } ?>"><br> 44 タイトル:<input type="text" name="title" value="<?php if(isset($_SESSION['title'])){ echo h($_SESSION['title']); } ?>"><br> 45 メッセージ:<br> 46 <textarea name="msg" rows="10" cols="30"><?php if(isset($_SESSION['msg'])){ echo h($_SESSION['msg']); } ?></textarea><br> 47 <input type="hidden" name="token" value="<?php echo h($_SESSION['token'])?>"> 48 <input type="submit" value="確認画面へ" name="trans"> 49</form> 50<!-- 投稿フォーム終了 --> 51<hr> 52<?php 53$i = 1; 54//投稿一覧表示 55foreach($result as $row) { 56 $s = "<p>($i)タイトル: <strong>%s</strong><br>投稿者: %s 投稿日: %s<br>内容:<br>%s</p>"; 57 printf ($s,h($row['title']), h($row['name']), h($row['day']), nl2br(h($row['msg']))); 58 $i++; 59} 60//投稿一覧終了 61?> 62</body> 63</html>

confirm.php

PHP

1<?php 2session_start(); 3require_once('encode.php'); 4 5//index.phpでのトークンがセットされていなかったら不正アクセスとみなす 6if (!isset($_SESSION['token']) || $_SESSION['token'] === '') { 7 echo '不正なアクセスです。'; 8} 9//トークンなど諸々が正しくセットされていたら 10elseif (isset($_POST['trans'], $_SESSION['token'], $_POST['token']) && $_SESSION['token'] === $_POST['token']) { 11//フォームでポストされたデータをセッションに格納し 12$_SESSION['name'] = $_POST['name']; 13$_SESSION['title'] = $_POST['title']; 14$_SESSION['msg'] = $_POST['msg']; 15?> 16<!DOCTYPE html> 17<html lang="ja"> 18<head> 19 <meta charset="UTF-8"> 20 <title>確認画面</title> 21 <style type="text/css"> 22 body { 23 background-color: #E1EDFF; 24 line-height: 1.5rem; 25 } 26 </style> 27</head> 28<body> 29 <h1>確認画面</h1> 30<?php 31//フォームに未入力項目があればその旨とindex.phpに戻るボタンを表示 32 if ($_SESSION['name'] == "" || $_SESSION['title'] == "" || $_SESSION['msg'] == ""){ 33 if ($_SESSION['name'] == "") { 34 echo "名前を入力して下さい<br>"; 35 } 36 if ($_SESSION['title'] == "") { 37 echo "タイトルを入力して下さい<br>"; 38 } 39 if ($_SESSION['msg'] == "") { 40 echo "メッセージを入力して下さい<br>"; 41 } 42 ?> 43 <a href="index.php">入力画面に戻る</a> 44 </body> 45 </html> 46 <?php 47 } else { 48 //フォームに未入力項目がなければ内容を確認表示しsubmitボタンを押すと再度confirm.php自身にセッションでデータを渡す 49 ?> 50 タイトル: <?php echo h($_SESSION['title']); ?> 51 投稿者: <?php echo h($_SESSION['name']); ?><br> 52 内容:<?php echo nl2br(h($_SESSION['msg'])); ?> 53 <form action="confirm.php" method="post"> 54 <input type="hidden" name="token" value="<?php echo h($_SESSION['token']); ?>"> 55 <input type="submit" value="送信する" name="regist"> 56 </form> 57 </body> 58 </html> 59 <?php 60 } 61} 62//confirm.php自身からポストやセッションが正しく渡されていたらDBにデータをinsertしcomplete.phpへ遷移 63elseif (isset($_POST['regist'], $_SESSION['token'], $_POST['token']) && $_SESSION['token'] === $_POST['token']) { 64 require_once('db_info.php'); 65 66 try { 67 $pdo = new PDO($dsn, $user, $pass); 68 $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 69 $pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 70 } catch (PDOExeption $e){ 71 $error = 'データベース接続に失敗しました: ' . $e->getMessage(); 72 include 'error.php'; 73 exit(); 74 } 75 try { 76 $sql = "insert into bbsdata (name, day, title, msg) values (:name, now(), :title, :msg)"; 77 $s = $pdo->prepare($sql); 78 $s->bindValue(':name', $_SESSION['name']); 79 $s->bindValue(':title', $_SESSION['title']); 80 $s->bindValue(':msg', $_SESSION['msg']); 81 $s->execute(); 82 } catch(PDOExeption $e) { 83 $error = 'データの書き込みに失敗しました: ' . $e->getMessage(); 84 include 'error.php'; 85 exit(); 86 } 87 88 $_SESSION = array(); 89 if (isset($_COOKIE[session_name()])){ 90 setcookie(session_name(), '', time() -3600, '/'); 91 } 92 session_destroy(); 93 header("Location: http://localhost/complete.php/", true, 303); 94 exit(); 95} else { 96//confirm.php自身からポストやセッションが正しく渡されていなかったら不正アクセスとみなす 97 echo '不正なアクセスです。'; 98}

complete.php

PHP

1<!DOCTYPE html> 2<html lang="ja"> 3<head> 4 <meta charset="UTF-8"> 5 <title>完了画面</title> 6 <style type="text/css"> 7 body { 8 background-color: #E1EDFF; 9 line-height: 1.5rem; 10 } 11 </style> 12</head> 13<body> 14 <h1>書き込みが完了しました</h1> 15 <a href="http://localhost/index.php">トップページへ戻る</a> 16</body> 17</html>

以上、

  • 記述方法に誤りはないか
  • セキュリティ対策は十分か

といった点についてアドバイスの程よろしくお願い致します。

ockeghem, mhashi, 7968👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

このスクリプトで匿名掲示板を運営するのであれば、
・記述方法に誤りはないか
・セキュリティ対策は十分か
のいずれも十分ではありません。

多分、入門用のサンプルソースから改変を加えて今の形にしたため、本来行うべき設計作業をしていないためだと思います。

一般的にアプリケーションを作成するには
・どんな機能を実装するか?
・その機能実装で、どのような攻撃が考えられるか?
・その攻撃をどのように防ぐか?また、それを検知する手段はどのように準備するか?
といった分析を行った上で、各種の情報を集め、セキュリティに対する要件を設計します。

例えば匿名掲示板を運営するのであれば、コメントの投稿が必須となるので
・不適切投稿の除外(詐欺サイトへの誘導等)
・荒らし対策
・連続投稿の阻止
等々の考慮が必要となりますが、それぞれがどのような方法で実施され、それに対してどのような方法が取れるかを検討することが必要となります。

その検討結果から、金銭や時間的なコストを考慮して、どこまでどのような実装を行うか決め、セキュリティ要件の定義を行うことになりますが、今回のスクリプトにはそういった事を行った形跡がありません。

これがなされていないと、
・CSRF対策を行っているのに、投稿ログの記録がない
・リファラの確認や連続投稿への対策といった基本事項の実装がない
といったチグハグなコードになってしまいます。

実際に運用するサイトを検討しているのであれば、再度設計から見直してはいかがでしょうか?
記述方法に関しては、正直細かくみていない上、私自身も勉強中なので適切なコメントが付けられませんが、設計と同じくチグハグさが見られます。
こちらは詳しい方のコメントがあるとイイのですが^^;

投稿2017/04/29 11:15

編集2017/04/29 11:16
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tnk_fuku

2017/04/29 13:52

te2jiさん、アドバイスありがとうございます。 自学用にとりあえず動くものを作ってPHP、セキュリティ対策について知識を付けていきたいと思い作成しました。 初心者ではありますが、最終的には一般公開するアプリを作れるようになりたいと思っていますので、ご指摘頂いた点を考慮出来ていなかったのは浅はかでした。 「わからないことがわからない」というのが本音で、それも基礎知識のなさのせいなのでしょうね。 それにしても正直、-3の評価をもらって少し凹みましたf(^^;) te2jiさんから具体的なポイントをご提示頂いてますので、一つ一つ調べながら知識をつけていきたいと思います! 記述方法についても何かしらコメントを頂けるとありがたいですね。。
退会済みユーザー

退会済みユーザー

2017/04/29 14:32

ちゃんとアプリの設計をしないのは、入門書にあるサンプルから発展させる弊害なんで、だいたいの人が一度は通る道かと^^; ちなみにですが、記述した例は、ザクッと思いつくままに書いたので重要ではありますが、網羅性はありません。注意して下さい。 > 記述方法についても何かしらコメントを頂けるとありがたいですね。 これは、実際にコードをたくさん見たり書いている人にコメントしてほしいです。私はエンジニア活動はじめて2年目なので、人のコードをざっと見て的確なコメントができるほどのスキルはありません。結構注目を集めた質問になっているので、レビュー慣れしてる人がコメントくれるとイイのですけど。 以下、余談w > それにしても正直、-3の評価をもらって少し凹みましたf(^^;) 私は、ちょっと煽りすぎて最高-7まで行きました!まぁ、お互いがんばりましょう^^
tnk_fuku

2017/04/29 15:02

>ちなみにですが、記述した例は、ザクッと思いつくままに書いたので重要ではありますが、網羅性はありません。注意して下さい。 それでもこうやってコメントを頂いたのは本当にありがたいです。 独学していると道しるべを見つけるのもなかなか大変で・・・。(自分が下手クソなだけでしょうけど) >結構注目を集めた質問になっているので、レビュー慣れしてる人がコメントくれるとイイのですけど。 頂ければありがたいですが、今回の質問が他人任せなスタンスになってしまったようですので、期待しないほうが良さそうですね。。 >私は、ちょっと煽りすぎて最高-7まで行きました! 勇気が湧いてきました(笑) 凹んでもしょうがないので頑張ります!
tnk_fuku

2017/04/30 09:13

基礎的なところからわかっていないので、まずは下記のページを読み込んで知識を深めたいと思います。 安全なウェブサイトの作り方 https://www.ipa.go.jp/files/000017316.pdf 【PHP超入門】Cookieとセッションについて http://qiita.com/7968/items/ce03feb17c8eaa6e4672 【PHP超入門】HTTP(GET・POST)について http://qiita.com/7968/items/4bf4d6f28284146c288f $_GET, $_POSTなどを受け取る際の処理 http://qiita.com/mpyw/items/2f9955db1c02eeef43ea
退会済みユーザー

退会済みユーザー

2017/04/30 13:17

記述されているのはいずれもコード寄りのページですね。 一般用語か不明ですが、セキュリティバグ対応とよばれるものです。 私が記述している内容は、セキュリティ要件だとか設計だとかそういったものなので、区別して考える必要があります。 セキュリティバグの対応は、基本的にやることや気にすべき内容はほぼ同じなので、本やブログで紹介されやすいのですが、要件だとか設計だとかは、事例調査や経験の上で検討がなされるため、独学が難しいです。 企業の担当者であれば、RFI等で情報をあつめるとかできるのですが、個人だとなかなか情報の入手ができません。厳しいところですね。。。 古典的な事例を潰していくとか、セミナーとかでトレンドを追うとかが精一杯かもしれないですが、アンテナ広げてお互いにがんばりましょう!
tnk_fuku

2017/05/01 04:45

アドバイスありがとうございます。 やはり個人では限界があるんですね。 ただ、まだ個人の限界を感じれるほど知識もついてないので出来る事からコツコツやっていきます!
guest

0

ベストアンサー

仕様はおいておくとして
「エラーメッセージによる不必要な内部情報の開示」
はよくあるセキュリティ問題の1つです。

php

1 $error = 'データベース接続に失敗しました: ' . $e->getMessage(); 2 include 'error.php'; 3

基本的にはシステム/関数などのエラーはそのまま表示すべきではありません。

また、エラーメッセージにはユーザー入力が含まれる場合もあり、エスケープ無しでの出力はNGです。

php

1 <?php echo $error; ?>

体系的に情報セキュリティを学ぶなら、まず一度ISO 27000を読むと良いです。オンラインなら無償でJIS Q 27000が参照できます。

https://blog.ohgaki.net/iso-27000-and-secure-programining

(オンラインで検索するにはちょっとしたコツと環境が必要なのでコレを参照。 今のISO 27000のセキュリティ要素はCIA - Confidentiality, Integrity, Avairability、のみではありません。ISO 13335に記載されていたReliability、Authenticity、Accountabilityも要素に加えられています。ログの必要性はAccountability - Non-repudiationとも言われる、に必要とされる要素です。)

セキュアコーディング/セキュアプログラミングの基本概念を理解してから取り組むのが近道です。

https://blog.ohgaki.net/cert-top-10-secure-coding-standard
https://blog.ohgaki.net/owasp-secure-coding-practices-quick-reference-guide

その上で契約プログラミングの概念を理解すると良いでしょう。

https://blog.ohgaki.net/design-by-contract-and-trust-boundary

契約プログラミングを行う場合、正しい信頼境界の概念が重要です。プログラム中には信頼できないデータが多数存在します。信頼境界を考える場合、コンテクストが重要になります。

https://blog.ohgaki.net/how-to-draw-and-protect-trust-boundary

また契約プログラミングの論理的背景である、必要十分条件がよく理解されていないケースが散見されるので「正しくコードが動作する必要十分条件」の再確認もオススメします。

https://blog.ohgaki.net/necessary-and-sufficient-condition-for-programs

コンテクストは出力のセキュリティ対策でも重要です。HTTPやHTML、SQLといったコンテクストも重要ですが、HTMLやSQLなど複雑な処理系の場合、HTML/SQLのどのコンテクストに出力しているのか、正確に把握する必要があります。

https://blog.ohgaki.net/text-interface-processing-basics
https://blog.ohgaki.net/complete-sql-injection-counter-measure

セキュアコーディングや契約プログラミング、信頼境界やコンテクストを理解したら、個別の脆弱性がどのように生まれるのか?自分で理解できるようになりますが、よくあるリスクの一覧と対策はガイドラインを参照するとよいでしょう。

https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

現在は今年リリース予定のOWASP TOP 10の2017年版のRCが参照できます。こちらは以前の物より改善されているので、現行版でなくRC版を参照すると良いと思います。

OWASP TOP 10で一番目の問題とされているのはInjectionです。私のブログでもほとんどのセキュリティ問題はインジェクションであると書いています。

https://blog.ohgaki.net/almost-all-security-issues-are-injections

記載されているコードには入力バリデーションが一切ありません。

2017年版RCのOWASP TOP 10のA1-Injectionの"How Do I Prevent Injection?"の対策3では、以下のように書かれています。

Positive or “white list” input validation is also
recommended, but is not a complete defense as many
situations require special characters be allowed. If special
characters are required, only approaches (1) and (2)
above will make their use safe. OWASP’s ESAPI has an
extensible library of white list input validation routines.

ISO 27000で要求されている入力バリデーションは以下のような物になります。

https://blog.ohgaki.net/iso27000-and-input-validation

2017年版RCのOWASP TOP 10のA7-Insufficient Attack Protectionは以下のような対策を求めています。

  1. Detect Attacks. Did something occur that is impossible

for legitimate users to cause (e.g., an input a legitimate
client can’t generate)? Is the application being used in a
way that an ordinary user would never do (e.g., tempo
too high, atypical input, unusual usage patterns,
repeated requests)?
2. Respond to Attacks. Logs and notifications are critical to
timely response. Decide whether to automatically block
requests, IP addresses, or IP ranges. Consider disabling or
monitoring misbehaving user accounts.

いろいろあるので書ききれませんが、今のところ一般的なCSRF対策としては記載の方法でも十分とされる、と思います。しかし、もっと良い方法もあります。

https://blog.ohgaki.net/advanced-csrf-token-by-hmac-hash

不必要に$_SESSIONへユーザー入力を保存するのは良くないです。今のPHPは私が実装したLazy Writeが有効です。$_SESSIONに変更がなければ、セッションデータのアクセスタイムスタンプのみが更新され、セッション管理の性能が大幅に向上します。(対応セーブハンドラのみ。ネットワーク経由のストレージを利用する場合に顕著)ユーザー名を$_SESSIONへ保存するのは良いですが、投稿の内容まで保存するのは性能面で良くありません。更新用のデータを$_SESSIONに保存すると”複数タブ”を利用した場合などに競合問題も発生します。

投稿2017/04/30 21:06

YasuoOhgaki

総合スコア51

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tnk_fuku

2017/05/01 04:55

YasuoOhgakiさん、コメントありがとうございます。 実は昨日いろいろと調べていたところ、YasuoOhgakiさんのブログを拝見しました。 重要なことをたくさん書かれているということはわかりましたが、知識不足でどこから手をつけていけばいいのかわからなかったので、今回このように順を追って解説して頂けて道筋が出来ました。 ブログにも今回のコメント内容に加筆して記載されているので、しっかり読み込んでみます! >不必要に$_SESSIONへユーザー入力を保存するのは良くないです。 $_SESSIONにデータを保存すると便利だなと思い使っていましたが、複数タブでの競合などが生じるのですね。 駆け出しで学ぶことばかりですが、知識を獲得することの楽しさを味わいながら頑張っていきます!
退会済みユーザー

退会済みユーザー

2017/05/01 13:54

徳丸先生のみならず、大垣先生まで参入してきたteratailすげぇ。 重鎮が自ら答えてくれるとか少なくとも数万円以上の価値がある。
guest

0

簡単にまとめると、
「セキュリティの最終チェック、ぜーんぶ丸投げでお願いします!」
というご質問ですね。

そういうのは専門の会社に依頼すればいいと思います。
最低でも数十万円くらいかかるでしょうけど。

投稿2017/04/29 13:49

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tnk_fuku

2017/04/29 14:18

前回の質問時に頂いた回答から自分なりに調べてまとめたつもりでしたが、zico_teratailさんのご回答で自分がずれていることがわかりました。 これからはもっとポイントを絞って質問していきたいと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.37%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問