例: 合成メソッドの作成
この例では、合成メソッドの作成方法を示します。この合成メソッドでは、まずクラス・フィールドを汚染します。次に、ユーザーのコード内のメソッドに呼び出しを追加し、最後にこのメソッド呼び出しの結果をシンクに渡します。
- アプリケーション・シナリオ
- 合成メソッドでモデル化される対象
- ステップ 1: 空の合成メソッドの作成
- ステップ 2: クラス・フィールドの汚染のモデル化
- ステップ 3:createUser() メソッドの呼び出しのモデル化
- ステップ 4: クライアントへのデータの戻りのモデル化
アプリケーション・シナリオ
この例では、createUser
は JAX-RS フレームワークに実装された REST API です。ユーザーは、http://host:port/users/createUser
などの URL を使用してこの API を呼び出すことができます。パスが一致すると、フレームワーク・ランタイムは、UserRestService.createUser()
に対するこの呼び出しを代行します。さらに、フレームワーク・ランタイムは、createUser()
を呼び出す前に、クライアント・データの urlInfo
クラス変数を初期化します。最後に、createUser()
によって返されたデータが、ランタイムによってクライアントに送り返されます。
合成メソッドでモデル化される対象
合成メソッドを使用して アプリケーション・シナリオ をキャプチャーするための要素には、以下のものがあります。
UserRestService
のurlInfo
クラス変数の汚染。UserRestService.createUser()
への呼び出し。- クライアントへの戻りデータ。
以下は、createUser()
メソッドのコードです。
import java.io.BufferedWriter;
@Path("users")
public class UserRestService {
@Context
UriInfo urlInfo;
@Path("/createUser")
public User createUser(){
MultivaluedMap<String, String> queryParams =
urlInfo.getQueryParameters();
String name = queryParams.getFirst("name");
User user = new User(name);
return user;
}
}
ステップ 1: 空の合成メソッドの作成
22 public class JAXRSHandler extends F4FHandler{
23 @Override
public void handleApp(F4FApp app, F4FActions actions) {
24 HighLevelSyntheticMethod synthMethod = HighLevelSyntheticMethod.make();
- 合成メソッド・オブジェクトは、行 24 で初期化されます。
ステップ 2: クラス・フィールドの汚染のモデル化
以下のコード・スニペットは、特定のクラス・フィールドを汚染する方法を示しています。この例では、@Context
アノテーションで注釈が付けられたクラス・フィールドを汚染しようとしています。
27 // create a local variable of the appropriate type
28 Local userRestServiceClazzInstance =
synthMethod.newLocal("com.ibm.appscan.UserRestService");
29
30 // get all the class fields
31 for(IField field: app.getIClass
("com.ibm.appscan.UserRestService").getDeclaredInstanceFields()){
32
33 //get all the annotations associated with the field
34 Collection<Annotation> fieldAnnotations = app.getFieldAnnotations(field);
35
36 //for each annotation of the field check if it is an @Context annotation
37 for (Annotation annotation : fieldAnnotations) {
38
39 if (annotation.getType().getName().toString().equals
("Ljavax/ws/rs/core/Context")) {
40
41 // call the F4F API to assign taint to the field
43 synthMethod.addInstanceVariableWrite(
userRestServiceClazzInstance /*Variable representing
class instance*/,
44 field /*field to taint */,
Taint.taint() /* taint */,
null);
45 }
46 }
47 }
Framework for Frameworks API addInstanceVariableWrite
は、4 つの引数を使用します。
- 最初の引数は、汚染するフィールドがあるクラス参照です。以下の例では、ローカル変数
userRestServiceClazzInstance
がこの引数を参照します。 - 2 番目の引数は、汚染するクラス・フィールドです。
- 3 番目の引数は、クラス変数フィールドに割り当てられる新しい値です。この例では、
Taint.taint()
が受け渡されるようにこの変数を汚染しようとしています。 - 最後の引数は
FilePositionInfo
です。この例ではnull
となります。
ステップ 3:createUser()
メソッドの呼び出しのモデル化
このステップでは、合成メソッドでの呼び出しをシミュレートします。
50 // call createUser() and store the returned value to a local variable
51 Local returnObj = synthMethod.addCall(
52 "com.ibm.appscan.UserRestService.createUser():com.ibm.appscan.User"
/* signature of the method to be called */,
null, /* FilePositionInfo */
53 userRestServiceClazzInstance /* Object on which the method
will be called */);
addCall
高位 API は 3 つの引数を使用します。
- 最初の引数は、呼び出すメソッドのシグニチャーです。このケースでは、
User.createUser()
を呼び出すので、そのシグニチャーを使用します。 - 2 番目の引数は
FilePositionInfo
です。これは、この例では必要がないのでnull
として渡されます。 - 最後の引数は、
createUser()
メソッドの呼び出しに必要なパラメーターのリストを表します。
createUser()
では引数を使用しないため、この呼び出しに受け渡される引数は、this
オブジェクト (タイプ User
の Local
変数 (userRestServiceClazzInstance
)) のみです。メソッド createUser()
は、新規に作成された User
を返します。これは、returnedObj
という名前の新しい Local
変数に保管されます (行 51 に表示)。
ステップ 4: クライアントへのデータの戻りのモデル化
この最終ステップでは、クライアントに返されるデータの戻りをモデル化するためのシンクを作成します。
58 // create a PrintWriter object
59 Local printWriterObj = synthMethod.newLocal("java.io.PrintWriter");
60
61 // we want to call the print API on the PrintWriter object.
// The print API takes a single argument of Object type returns void
62
63 // we create a param list of size 2. The first item in this list is always the
// 'this' object and rest are actual method arguments.
64 Param[] printWriterObjParam = new Param[2];
65 printWriterObjParam[0] = printWriterObj; // The "this" object
// the value returned by the call to the createUser method
66 printWriterObjParam[1] = returnObj;
67
68 // Now add a call to the print method
69 synthMethod.addCall("java.io.PrintWriter.print(java.lang.Object):void",
null, printWriterObjParam);
70 }
- 行 59 では、合成メソッドに
PrintWriter
クラスのLocal
オブジェクトを作成します。 - 行 64 から 66 では、
PrintWriter
クラス・インスタンス (printWriterObj
) にprint
メソッドを呼び出すために必要なパラメーター・リストを準備しています。- 最初のパラメーターは、オブジェクト参照 (
printWriterObj
) それ自体です。 - 2 番目のパラメーターは、
print
メソッドに対する引数です。returnObj
ローカル変数に保管されている戻り値を受け渡します。
- 最初のパラメーターは、オブジェクト参照 (
- 行 69 では、呼び出しを
PrintWriter.print
メソッドに追加し、クライアントに返されるデータの戻りをモデル化しています。