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
組態設定檔案的適當設定來修改策略。但是,決定誰可以影響設定時應特別小心,因為過度允許的跨網域策略會允許惡意應用程式以不適當的方式與受害者應用程式通訊,導致欺騙、資料遭竊取、傳遞和其他攻擊。Policy restrictions bypass 弱點會在以下情況中出現:範例 2:以下程式碼對載入的 SWF 檔案使用其中一個參數的值,以定義可信任網域的清單。
...
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 載入的 SWF 應用程式容易遭到 man-in-the-middle 攻擊,因此不應該受信賴。allowInsecureDomain()
,它會關閉以下限制:防止 HTTP 載入的 SWF 應用程式存取 HTTPS 載入之 SWF 應用程式的資料。
flash.system.Security.allowInsecureDomain("*");
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);
...
}
...
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
以便取得其帳戶的進一步資訊。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)
}
}
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)
...
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()
方法中將其釋放,導致記憶體洩露:
- (void)init
{
myVar = [NSString alloc] init];
...
}
- (void)dealloc
{
[otherVar release];
}
realloc()
調整原始分配大小失敗時,洩露了分配記憶體區塊。
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()
的呼叫未能調整原始配置的大小,則以下 Micro Focus COBOL 程式就會洩漏配置的記憶體區塊。
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
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
值都沒有關係。