API は、呼び出し元と呼び出し先の間のコントラクトです。最も一般的な API の不正使用の形態は、呼び出し元がこのコントラクトの終わりを守らないことによって発生します。たとえば、プログラムが chroot() を呼び出した後に chdir() を呼び出すのに失敗すると、アクティブなルート ディレクトリを安全に変更する方法を指定したコントラクトに違反することになります。ライブラリの悪用のもう 1 つの良い例は、呼び出し先が信頼できる DNS 情報を呼び出し元に返すことを期待することです。この場合、呼び出し元は、呼び出し先の API の動作 (戻り値が認証目的に使用できること) についてある種の仮定をすることで、呼び出し先の API を悪用します。また、相手側から、呼び出し元と呼び出し先のコントラクトを違反することもできます。例えば、コーダーが SecureRandom をサブクラス化し、ランダムではない値を返した場合、コントラクトに違反することになります。
unsecure
属性は、クライアント上で値を設定できる属性のリストを指定します。unsecure
属性によりこのようなリストを指定できます。unsecure
属性内に表示できる属性は、disabled
のみです。この属性を使用して、クライアントはどのコンポーネントを有効または無効にするかを定義できるようになります。本来サーバーでのみ設定可能にする必要がある属性値を、クライアントが制御できるようにするのは良いアイデアではありません。unsecure
属性を使用する inputText
コンポーネントを示しています。
...
<af:inputText id="pwdBox"
label="#{resources.PWD}"
value=""#{userBean.password}
unsecure="disabled"
secret="true"
required="true"/>
...
file://
プロトコルに使用できます。file://
を含む HTTP 以外のプロトコルに対して動作するはずがありません。 それらのプロトコルの動作や適用されるセキュリティ区分化のルールは不明です。 たとえば、インターネットからローカル ディスクにダウンロードされた HTML ファイルは、ローカルにインストールされた HTML コードと同じ cookie を共有するのでしょうか?UseCookiePolicy()
メソッドは、Cookie ポリシー ミドルウェアをミドルウェア パイプラインに追加します。これにより、カスタマイズした Cookie ポリシーが許可されます。ここに示すように、間違った順序で指定されると、プログラマーによって指定された Cookie ポリシーはすべて無視されます。
...
var builder = WebApplication.CreateBuilder(...);
var app = builder.Build(...);
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
...
}
app.UseCookiePolicy();
...
UseHttpsRedirection()
メソッドは、HTTPS リダイレクション ミドルウェアをミドルウェア パイプラインに追加します。これにより、安全でない HTTP リクエストを安全な HTTPS リクエストにリダイレクトすることが可能になります。ここに示すように、間違った順序で指定されると、リダイレクト前にリストされたミドルウェアを介したリクエスト処理の前に、意味のある HTTPS のリダイレクションは行われません。これにより、HTTP リクエストを、安全な HTTPS 接続にリダイレクトされる前にアプリケーションで処理できるようになります。
...
var builder = WebApplication.CreateBuilder(...);
var app = builder.Build(...);
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
...
}
app.UseHttpsRedirection();
...
UseHttpLogging()
メソッドは、HTTP ロギング ミドルウェアをミドルウェア パイプラインに追加します。これにより、ミドルウェア コンポーネントによるログ記録が可能になります。ここに示すように、間違った順序で指定されると、UseHttpLogging()
への呼び出しの前にパイプラインに追加されたミドルウェアはログを記録しません。例 2:
...
var builder = WebApplication.CreateBuilder(...);
var app = builder.Build(...);
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
...
}
app.UseHttpLogging();
...
UseWC3Logging()
メソッドは、W3C ロギング ミドルウェアをミドルウェア パイプラインに追加します。これにより、ミドルウェア コンポーネントによるログ記録が可能になります。ここに示すように、間違った順序で指定されると、UseWC3Logging()
への呼び出しの前にパイプラインに追加されたミドルウェアはログを記録しません。
...
var builder = WebApplication.CreateBuilder(...);
var app = builder.Build(...);
app.UseStaticFiles();
app.UseRouting();
app.UseSession();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
...
}
app.UseWC3Logging();
...
public ActionResult UpdateWidget(Model model)
{
// ... controller logic
}
[Required]
属性でマークされた) プロパティとオプションの ([Required]
属性でマークされていない) プロパティを持つモデルクラスは、攻撃者が想定以上のデータを含む要求を送信した場合に問題を引き起こす可能性があります。[Required]
を含むプロパティと [Required]
を含まないプロパティがあります。
public class MyModel
{
[Required]
public String UserName { get; set; }
[Required]
public String Password { get; set; }
public Boolean IsAdmin { get; set; }
}
[Required]
属性でマークされた) non-nullable プロパティを持つモデルクラスを使用すると、攻撃者から想定より少ないデータを含んでいるリクエストが送信された場合に問題を引き起こす可能性があります。[Required]
検証属性を満たします。この場合、アプリケーションが不測の挙動を起こします。
public enum ArgumentOptions
{
OptionA = 1,
OptionB = 2
}
public class Model
{
[Required]
public String Argument { get; set; }
[Required]
public ArgumentOptions Rounding { get; set; }
}
[Required]
属性なしのプロパティが含まれる場合、攻撃者がそのサブモデルを送信しないと、親プロパティには null
値が与えられ、子モデルの必須フィールドはモデル検証によってアサートされません。これは under-posting 攻撃の 1 つの形態です。
public class ChildModel
{
public ChildModel()
{
}
[Required]
public String RequiredProperty { get; set; }
}
public class ParentModel
{
public ParentModel()
{
}
public ChildModel Child { get; set; }
}
ParentModel.Child
プロパティの値を送信しない場合、ChildModel.RequiredProperty
プロパティにはアサートされない [Required]
が与えられます。この場合、問題となる不測の結果が生じる可能性があります。
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics localizedReason:nil
reply:^(BOOL success, NSError *error) {
if (success) {
NSLog(@"Auth was OK");
}
}];
context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: "", reply: { (success, error) -> Void in
if (success) {
print("Auth was OK");
}
else {
print("Error received: %d", error!);
}
})
SHARED
に指定されており、読み取りアクセスと書き込みアクセスの両方が許可されています。
results = query.execute(Database.SHARED);
results = query.execute(); //missing query mode
GC.Collect()
のコールを挿入することで問題が解消するかのように思える場合があります。GC.Collect()
をコールするという方法は間違っていることがほとんどです。なぜなら、GC.Collect()
のコールを頻繁に呼び出すと、性能の問題が引き起こされる可能性があるからです。System.gc()
のコールを挿入することで問題が解消するかのように思える場合があります。System.gc()
をコールするという方法は間違っていることがほとんどです。なぜなら、System.gc()
のコールを頻繁に呼び出すと、性能の問題が引き起こされる可能性があるからです。Equals()
が Equals()
を実装しないオブジェクトでコールされています。Equals()
を実装していないクラス (あるいは任意のスーパークラス/インターフェイス) で Equals()
をコールすると、System.Object
から継承した Equals()
メソッドがコールされる結果となります。Object.Equals()
はオブジェクトのメンバー フィールドやその他のプロパティを比較する代わりに、2 つのオブジェクト インスタンスを比較してその 2 つが同一のものであるかを確認します。Object.Equals()
の正規の利用法も存在しますが、通常はコードにバグがあることを示しています。
public class AccountGroup
{
private int gid;
public int Gid
{
get { return gid; }
set { gid = value; }
}
}
...
public class CompareGroup
{
public bool compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.Equals(group2); //Equals() is not implemented in AccountGroup
}
}
equals()
メソッドが、equals()
を実装しないオブジェクトでコールされています。equals()
を実装していないクラス (あるいは任意のスーパークラス/インターフェイス) で equals()
をコールすると、java.lang.Object
から継承した equals()
メソッドがコールされる結果となります。Object.equals()
はオブジェクトのメンバーフィールドやその他のプロパティを比較する代わりに、2 つのオブジェクトインスタンスを比較してその 2 つが同一のものであるかを確認します。Object.equals()
の正規の利用法も存在しますが、通常はコードにバグがあることを示しています。
public class AccountGroup
{
private int gid;
public int getGid()
{
return gid;
}
public void setGid(int newGid)
{
gid = newGid;
}
}
...
public class CompareGroup
{
public boolean compareGroups(AccountGroup group1, AccountGroup group2)
{
return group1.equals(group2); //equals() is not implemented in AccountGroup
}
}
finalize()
メソッドは super.finalize()
をコールします。finalize()
メソッドで super.finalize()
のコールを行うことは適切な方法であるとしています [1]。super.finalize()
のコールを省略しています。
protected void finalize() {
discardNative();
}
private void writeObject(java.io.ObjectOutputStream out) throws IOException;
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
private void readObjectNoData() throws ObjectStreamException;
getOutputStream
をコールした後に、getWriter()
をコールする場合もエラーが発生しやすくなります。HttpServletRequest
の転送、HttpServletResponse
のリダイレクト、またはサーブレットの出力ストリームバッファーのフラッシュによって、関連ストリームがコミットされます。後続のバッファーがストリームをリセットまたはコミットすると (追加のフラッシュまたはリダイレクトなど)、IllegalStateException
となります。ServletOutputStream
または PrintWriter
のいずれか (両方ではありません) を使用して、レスポンスストリームへのデータの書き込みが許可されます。getOutputStream()
をコールした後に、getWriter()
をコールする、また逆の処理を行った場合、IllegalStateException
となります。IllegalStateException
によって、レスポンスハンドラの実行が防止され、レスポンスがドロップすることになります。これによりサーバーの動作が不安定になります。また、サーブレットが適切に実装されていないことを示します。例 2: 逆に、次のコードは、リクエストが転送された後に、書き込みを行い、
public class RedirectServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
OutputStream out = res.getOutputStream();
...
// flushes, and thereby commits, the output stream
out.flush();
out.close(); // redirecting the response causes an IllegalStateException
res.sendRedirect("http://www.acme.com");
}
}
PrintWriter
のバッファーをフラッシュしようとしています。
public class FlushServlet extends HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException {
...
// forwards the request, implicitly committing the stream
getServletConfig().getServletContext().getRequestDispatcher("/jsp/boom.jsp").forward(req, res);
...
// IllegalStateException; cannot redirect after forwarding
res.sendRedirect("http://www.acme.com/jsp/boomboom.jsp");
PrintWriter out = res.getWriter();
// writing to an already-committed stream will not cause an exception,
// but will not apply these changes to the final output, either
out.print("Writing here does nothing");
// IllegalStateException; cannot flush a response's buffer after forwarding the request
out.flush();
out.close();
}
}
Content-Length
ヘッダーには負の数が設定されています。Content-Length
ヘッダーを設定した開発者は、0
または正の数をContent-Length
を設定することになります。
URL url = new URL("http://www.example.com");
HttpURLConnection huc = (HttpURLConnection)url.openConnection();
huc.setRequestProperty("Content-Length", "-1000");
Content-Length
ヘッダーには負の数が設定されています。Content-Length
ヘッダーを設定した開発者は、0
または正の数をContent-Length
ヘッダーに誤って負の数を設定しています。
xhr.setRequestHeader("Content-Length", "-1000");
ToString()
は配列でコールされます。ToString()
がコールされているということは、開発者が配列の内容を文字列として返そうとしていることを意味します。しかし、配列で ToString()
を直接コールすると、その配列のタイプを含んだ文字列値が返されます。System.String[]
を出力します。
String[] stringArray = { "element 1", "element 2", "element 3", "element 4" };
System.Diagnostics.Debug.WriteLine(stringArray.ToString());
toString()
は配列でコールされます。toString()
がコールされているということは、開発者が配列の内容を文字列として返そうとしていることを意味します。しかし、配列で toString()
を直接コールすると、その配列のタイプおよびメモリのハッシュコードを含んだ文字列値が返されます。[Ljava.lang.String;@1232121
を出力します。
String[] strList = new String[5];
...
System.out.println(strList);