分布式计算是关于时间和状态的。也就是说,为了让多个组件相互通信,必须共享状态,所有这些都需要时间。
大多数程序员都会将其工作拟人化。他们会让一个控制线程以同样的方式(他们必须自己完成工作时采取的方式)执行整个程序。然而,现代计算机不同任务之间切换得非常快,在多核、多 CPU 或分布式系统中,两个事件可能完全同时发生。程序员预期的程序执行过程与实际情况之间存在差距,即存在缺陷。这些缺陷与线程、流程、时间和信息之间的意外交互有关。这些交互是通过共享状态发生的:信号量、变量、文件系统,以及总而言之,可以存储信息的任何内容。
HttpSession
属性来储存会破坏应用程序的可靠性。HttpSession
对象,所以当一个 JVM 不可用时,另一个 JVM 可以在不中断应用程序流程的情况下接替步骤的执行。Serializable
接口。
public class DataGlob {
String globName;
String globValue;
public void addToSession(HttpSession session) {
session.setAttribute("glob", this);
}
}
block.timestamp
或 block.number
作为代理的时间。block.timestamp
或 block.number
关联的值通常由开发人员用于触发与时间相关的事件,但是,这些值通常给人以一种此类时间使用起来不太安全的感觉。block.timestamp
说的好听点是不可靠,在最坏的情况下,恶意矿工如果看到这样做的好处,则会改变其区块的时间戳。block.number
,即使可以预测区块之间的时间(大约 14 秒),区块时间也不恒定,可能会随着网络活动而发生变化。这使得 block.number
对于与时间相关的计算来说变得不可靠。block.number
在一定时间后解锁资金。
function withdraw() public {
require(users[msg.sender].amount > 0, 'no amount locked');
require(block.number >= users[msg.sender].unlockBlock, 'lock period not over');
uint amount = users[msg.sender].amount;
users[msg.sender].amount = 0;
(bool success, ) = msg.sender.call.value(amount)("");
require(success, 'transfer failed');
}
...
var authenticated = true;
...
database_connect.query('SELECT * FROM users WHERE name == ? AND password = ? LIMIT 1', userNameFromUser, passwordFromUser, function(err, results){
if (!err && results.length > 0){
authenticated = true;
}else{
authenticated = false;
}
});
if (authenticated){
//do something privileged stuff
authenticatedActions();
}else{
sendUnathenticatedMessage();
}
true
,否则设置为 false
。令人遗憾的是,由于回调被 IO 阻止,它将异步运行且可能在检查 if (authenticated)
之后运行,由于默认值为 true,它将进入 if-statement,确认用户实际上是否已经过身份验证。
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(new File(Environment.getExternalStorageDirectory() + "/download/" + "app.apk")), "application/vnd.android.package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
setuid root
的程序。该程序代表非特权用户执行某些文件操作,并使用访问检查来确保它不会使用其 root 权限执行当前用户不应该执行的操作。该程序使用 access()
系统调用来检查运行该程序的人员是否有权访问指定的文件,然后再打开该文件并执行必要的操作。
if (!access(file,W_OK)) {
f = fopen(file,"w+");
operate(f);
...
}
else {
fprintf(stderr,"Unable to open file %s.\n",file);
}
access()
的调用按照预期计划的那样执行,而且如果运行程序的用户具有编辑文件的必要权限,则会返回 0
,反之则会返回 -1。然而,因为 access()
和 fopen()
都是对文件名进行操作,而不是文件句柄,所以当 file
变量传递到 fopen()
时,就无法保证该变量仍能像传递到 access()
时那样引用磁盘上相同的文件。如果攻击者在调用 access()
之后,用指向其他文件的象征性链接来取代 file
,程序就会使用根权限对文件进行操作,即便这个文件是攻击者在其他情况下无法进行更改的。通过欺骗程序去运行其他情况下不允许执行的操作,从而使攻击者获得更高的权限。root
权限的程序。如果应用程序能够执行本不允许攻击者执行的操作,那么有可能就会成为攻击目标。
fd = creat(FILE, 0644); /* Create file */
if (fd == -1)
return;
if (chown(FILE, UID, -1) < 0) { /* Change file owner */
...
}
chown()
操作的文件与通过调用 creat()
创建的文件是一样的,但事实未必如此。因为 chown()
根据文件名而不是文件句柄操作,攻击者可以将该文件替换为指向不归他所有的文件的链接。调用 chown()
将给予攻击者链接文件的所有权。CBL_CHECK_FILE_EXIST
例程在创建文件之前检查该文件是否存在,并执行所需的操作。
CALL "CBL_CHECK_FILE_EXIST" USING
filename
file-details
RETURNING status-code
END-CALL
IF status-code NOT = 0
MOVE 3 to access-mode
MOVE 0 to deny-mode
MOVE 0 to device
CALL "CBL_CREATE_FILE" USING
filename
access-mode
deny-mode
device
file-handle
RETURNING status-code
END-CALL
END-IF
CBL_CHECK_FILE_EXIST
的调用按预期正常运行并返回非零值,表明文件不存在。然而,由于 CBL_CHECK_FILE_EXIST
和 CBL_CREATE_FILE
均作用于文件名而非文件句柄,因此无法保证 filename
变量仍然引用传递到 CBL_CREATE_FILE
(当该变量传递到 CBL_CHECK_FILE_EXIST
时其引用的文件)时磁盘上的同一文件。如果攻击者在调用 CBL_CHECK_FILE_EXIST
后创建 filename
,则对 CBL_CREATE_FILE
的调用将会失败,致使程序相信文件为空,而事实上该文件包含攻击者控制的数据。root
权限的程序,该程序可代表非特权用户执行某些文件操作,并使用访问检查来确保它不会使用其 root 权限执行不应被当前用户访问的操作。通过欺骗程序执行原本不允许的操作,攻击者可能会获得提升的权限。java.text.Format
中的 parse()
和 format()
方法包含一个可导致用户看到其他用户数据的设计缺陷。java.text.Format
中的 parse()
和 format()
方法包含一个可导致用户看到其他用户数据的 race condition。
public class Common {
private static SimpleDateFormat dateFormat;
...
public String format(Date date) {
return dateFormat.format(date);
}
...
final OtherClass dateFormatAccess=new OtherClass();
...
public void function_running_in_thread1(){
System.out.println("Time in thread 1 should be 12/31/69 4:00 PM, found: "+ dateFormatAccess.format(new Date(0)));
}
public void function_running_in_thread2(){
System.out.println("Time in thread 2 should be around 12/29/09 6:26 AM, found: "+ dateFormatAccess.format(new Date(System.currentTimeMillis())));
}
}
format()
中存在 race condition。