var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
if (ctl == "Add) {
ao = new AddCommand();
} else if (ctl == "Modify") {
ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
ao.doAction(params);
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
var cmdClass:Class = getDefinitionByName(ctl + "Command") as Class;
ao = new cmdClass();
ao.doAction(params);
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
接口的对象实例化。如果命令发送器仍对 access control 负责,那么只要程序员创建实现 Worker
接口的新类,就务必要修改发送器的 access control 代码。如果未修改 access control 代码,那么一些 Worker
类就没有任何 access control 权限。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
var params:Object = LoaderInfo(this.root.loaderInfo).parameters;
var ctl:String = String(params["ctl"]);
var ao:Worker;
var cmdClass:Class = getDefinitionByName(ctl + "Command") as Class;
ao = new cmdClass();
ao.checkAccessControl(params);
ao.doAction(params);
Continuation
对象的回调方法可能使攻击者能够通过应用程序创建意外的控制流路径,从而有可能绕过安全检查。continuationMethod
属性,该属性用于确定接收响应时要调用的方法的名称。
public Object startRequest() {
Continuation con = new Continuation(40);
Map<String,String> params = ApexPages.currentPage().getParameters();
if (params.containsKey('contMethod')) {
con.continuationMethod = params.get('contMethod');
} else {
con.continuationMethod = 'processResponse';
}
HttpRequest req = new HttpRequest();
req.setMethod('GET');
req.setEndpoint(LONG_RUNNING_SERVICE_URL);
this.requestLabel = con.addHttpRequest(req);
return con;
}
continuationMethod
属性,这使得攻击者能够调用与名称匹配的任何函数。
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
If (String.Compare(ctl,"Add") = 0) Then
ao.DoAddCommand(Request)
Else If (String.Compare(ctl,"Modify") = 0) Then
ao.DoModifyCommand(Request)
Else
App.EventLog("No Action Found", 4)
End If
...
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
CallByName(ao, ctl, vbMethod, Request)
...
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
对象的方法。如果命令发送器对 access control 负责,那么,只要程序员在 Worker
类中创建了新方法,就必须修改发送器的 access control 逻辑。如果 access control 逻辑过期,那么某些 Worker
方法将不具有任何 access control。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
...
Dim ctl As String
Dim ao As New Worker()
ctl = Request.Form("ctl")
If (ao.checkAccessControl(ctl,Request) = True) Then
CallByName(ao, "Do" & ctl & "Command", vbMethod, Request)
End If
...
clazz
中定义的所有函数。
char* ctl = getenv("ctl");
...
jmethodID mid = GetMethodID(clazz, ctl, sig);
status = CallIntMethod(env, clazz, mid, JAVA_ARGS);
...
示例 2:与之前的示例类似,应用程序使用
...
func beforeExampleCallback(scope *Scope){
input := os.Args[1]
if input{
scope.CallMethod(input)
}
}
...
reflect
程序包从命令行参数中检索要调用的函数的名称。
...
input := os.Args[1]
var worker WokerType
reflect.ValueOf(&worker).MethodByName(input).Call([]reflect.Value{})
...
String ctl = request.getParameter("ctl");
Worker ao = null;
if (ctl.equals("Add")) {
ao = new AddCommand();
} else if (ctl.equals("Modify")) {
ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
ao.doAction(request);
String ctl = request.getParameter("ctl");
Class cmdClass = Class.forName(ctl + "Command");
Worker ao = (Worker) cmdClass.newInstance();
ao.doAction(request);
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
接口的对象实例化。如果命令发送器仍对 access control 负责,那么只要程序员创建实现 Worker
接口的新类,就务必要修改发送器的 access control 代码。如果未修改 access control 代码,那么一些 Worker
类就没有任何 access control 权限。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
String ctl = request.getParameter("ctl");
Class cmdClass = Class.forName(ctl + "Command");
Worker ao = (Worker) cmdClass.newInstance();
ao.checkAccessControl(request);
ao.doAction(request);
Worker
接口的对象;系统中所有对象的默认构造函数都可以调用。如果对象没有实现 Worker
接口,则会在分配到 ao
前抛出 ClassCastException
。但如果构造函数执行了一些有利于攻击者的操作,则说明已经造成损害。对于简单的应用程序来说,这种情况的影响并不大,但是对于日趋复杂的大型应用程序来说,攻击者利用构造函数发动攻击并非没有可能。performSelector
方法所使用的参数,通过此种方式创建一个意想不到且贯穿于整个应用程序的控制流路径,从而避开潜在的安全检查。UIApplicationDelegate
类中定义的方法签名匹配的任何函数。
...
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
NSString *query = [url query];
NSString *pathExt = [url pathExtension];
[self performSelector:NSSelectorFromString(pathExt) withObject:query];
...
$ctl = $_GET["ctl"];
$ao = null;
if (ctl->equals("Add")) {
$ao = new AddCommand();
} else if ($ctl.equals("Modify")) {
$ao = new ModifyCommand();
} else {
throw new UnknownActionError();
}
$ao->doAction(request);
$ctl = $_GET["ctl"];
$args = $_GET["args"];
$cmdClass = new ReflectionClass(ctl . "Command");
$ao = $cmdClass->newInstance($args);
$ao->doAction(request);
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
接口的对象实例化。如果命令发送器仍对 access control 负责,那么只要程序员创建实现 Worker
接口的新类,就务必要修改发送器的 access control 代码。如果未修改 access control 代码,那么一些 Worker
类就没有任何 access control 权限。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
$ctl = $_GET["ctl"];
$args = $_GET["args"];
$cmdClass = new ReflectionClass(ctl . "Command");
$ao = $cmdClass->newInstance($args);
$ao->checkAccessControl(request);
ao->doAction(request);
Worker
接口的对象;系统中所有对象的默认构造函数都可以调用。如果对象没有实现 Worker
接口,则会在分配到 $ao
前抛出 ClassCastException
。但如果构造函数执行了一些有利于攻击者的操作,则说明已经造成损害。对于简单的应用程序来说,这种情况的影响并不大,但是对于日趋复杂的大型应用程序来说,攻击者利用构造函数发动攻击并非没有可能。
ctl = req['ctl']
if ctl=='add'
addCommand(req)
elsif ctl=='modify'
modifyCommand(req)
else
raise UnknownCommandError.new
end
ctl = req['ctl']
ctl << "Command"
send(ctl)
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。define_method()
动态创建方法,或者通过覆盖 missing_method()
来调用方法。审计和跟踪这些方法以及访问控制代码在这些方法中的使用方式是非常困难的,当考虑到这一点还将取决于所加载的其他库代码时,可能会使这个近乎不可完成的任务能够以这种方式正确地完成。
def exec(ctl: String) = Action { request =>
val cmdClass = Platform.getClassForName(ctl + "Command")
Worker ao = (Worker) cmdClass.newInstance()
ao.doAction(request)
...
}
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
接口的对象实例化。如果命令发送器仍对 access control 负责,那么只要程序员创建实现 Worker
接口的新类,就务必要修改发送器的 access control 代码。如果未修改 access control 代码,那么一些 Worker
类就没有任何 access control 权限。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
def exec(ctl: String) = Action { request =>
val cmdClass = Platform.getClassForName(ctl + "Command")
Worker ao = (Worker) cmdClass.newInstance()
ao.checkAccessControl(request);
ao.doAction(request)
...
}
Worker
接口的对象;系统中所有对象的默认构造函数都可以调用。如果对象没有实现 Worker
接口,则会在分配到 ao
前抛出 ClassCastException
。但如果构造函数执行了一些有利于攻击者的操作,则说明已经造成损害。对于简单的应用程序来说,这种情况的影响并不大,但是对于日趋复杂的大型应用程序来说,攻击者利用构造函数发动攻击并非没有可能。performSelector
方法所使用的参数,通过此种方式创建一个意想不到且贯穿于整个应用程序的控制流路径,从而避开潜在的安全检查。UIApplicationDelegate
类中定义的方法签名匹配的任何函数。
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
...
let query = url.query
let pathExt = url.pathExtension
let selector = NSSelectorFromString(pathExt!)
performSelector(selector, withObject:query)
...
}
...
Dim ctl As String
Dim ao As new Worker
ctl = Request.Form("ctl")
If String.Compare(ctl,"Add") = 0 Then
ao.DoAddCommand Request
Else If String.Compare(ctl,"Modify") = 0 Then
ao.DoModifyCommand Request
Else
App.EventLog "No Action Found", 4
End If
...
...
Dim ctl As String
Dim ao As Worker
ctl = Request.Form("ctl")
CallByName ao, ctl, vbMethod, Request
...
if/else
代码段也完全删除了,而且还可以在不改变命令发送器的情况下增加新的命令类型。Worker
对象的方法。如果命令发送器仍对 access control 负责,那么,只要程序员在 Worker
类中创建了新方法,就必须修改发送器的 access control 代码。如果无法修改 access control 代码,那么一些 Worker
方法就不具有任何 access control 权限。Worker
对象负责执行 access control 检查。下面是一段重新修改的代码示例:
...
Dim ctl As String
Dim ao As Worker
ctl = Request.Form("ctl")
If ao.checkAccessControl(ctl,Request) = True Then
CallByName ao, "Do" & ctl & "Command", vbMethod, Request
End If
...
NSData *imageData = [NSData dataWithContentsOfFile:file];
CC_MD5(imageData, [imageData length], result);
let encodedText = text.cStringUsingEncoding(NSUTF8StringEncoding)
let textLength = CC_LONG(text.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
let digestLength = Int(CC_MD5_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLength)
CC_MD5(encodedText, textLength, result)
...
private static final String salt = "";
...
PBEKeySpec pbeSpec=new PBEKeySpec(password);
SecretKeyFactory keyFact=SecretKeyFactory.getInstance(CIPHER_ALG);
PBEParameterSpec defParams=new PBEParameterSpec(salt,100000);
Cipher cipher=Cipher.getInstance(CIPHER_ALG);
cipher.init(cipherMode,keyFact.generateSecret(pbeSpec),defParams);
...
...
const salt = "";
crypto.pbkdf2(
password,
salt,
iterations,
keyLength,
"sha256",
function (err, derivedKey) { ... }
);
...
CCKeyDerivationPBKDF(kCCPBKDF2,
password,
passwordLen,
"",
0,
kCCPRFHmacAlgSHA256,
100000,
derivedKey,
derivedKeyLen);
...
...
$hash = hash_pbkdf2('sha256', $password, '', 100000);
...
from hashlib import pbkdf2_hmac
...
dk = pbkdf2_hmac('sha256', password, '', 100000)
...
...
dk = OpenSSL::PKCS5.pbkdf2_hmac(password, "", 100000, 256, digest)
...
...
let ITERATION = UInt32(100000)
...
CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordLength,
"",
0,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
ITERATION,
derivedKey,
derivedKeyLength)
...
PKCS5_PBKDF2_HMAC(pass, strlen(pass), "2!@$(5#@532@%#$253l5#@$", 2, ITERATION, EVP_sha512(), outputBytes, digest);
...
...
private static final String salt = "2!@$(5#@532@%#$253l5#@$";
...
PBEKeySpec pbeSpec=new PBEKeySpec(password);
SecretKeyFactory keyFact=SecretKeyFactory.getInstance(CIPHER_ALG);
PBEParameterSpec defParams=new PBEParameterSpec(salt,100000);
Cipher cipher=Cipher.getInstance(CIPHER_ALG);
cipher.init(cipherMode,keyFact.generateSecret(pbeSpec),defParams);
...
...
const salt = "some constant value";
crypto.pbkdf2(
password,
salt,
iterations,
keyLength,
"sha256",
function (err, derivedKey) { ... }
);
...
CCKeyDerivationPBKDF(kCCPBKDF2,
password,
passwordLen,
"2!@$(5#@532@%#$253l5#@$",
2,
kCCPRFHmacAlgSHA256,
100000,
derivedKey,
derivedKeyLen);
...
...
$hash = hash_pbkdf2('sha256', $password, '2!@$(5#@532@%#$253l5#@$', 100000)
...
...
from hashlib import pbkdf2_hmac
dk = pbkdf2_hmac('sha256', password, '2!@$(5#@532@%#$253l5#@$', 100000)
...
...
dk = OpenSSL::PKCS5.pbkdf2_hmac(password, '2!@$(5#@532@%#$253l5#@$', 100000, 256, digest)
...
...
let ITERATION = UInt32(100000)
let salt = "2!@$(5#@532@%#$253l5#@$"
...
CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordLength,
salt,
salt.lengthOfBytesUsingEncoding(NSUTF8StringEncoding),
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
ITERATION,
derivedKey,
derivedKeyLength)
...
...
crypt(password, "2!@$(5#@532@%#$253l5#@$");
...
...
salt := "2!@$(5#@532@%#$253l5#@$"
password := get_password()
sha256.Sum256([]byte(salt + password)
...
...
Encryptor instance = ESAPI.encryptor();
String hash1 = instance.hash(input, "2!@$(5#@532@%#$253l5#@$");
...
javap -c
命令访问已经过反汇编的代码,而在这些代码中恰恰包含着用户使用过的 salt 值。
...
crypt($password, '2!@$(5#@532@%#$253l5#@$');
...
...
from django.contrib.auth.hashers import make_password
make_password(password, salt="2!@$(5#@532@%#$253l5#@$")
...
require 'openssl'
...
password = get_password()
salt = '2!@$(5#@532@%#$253l5#@$'
hash = OpenSSL::Digest::SHA256.digest(salt + password)
...
...
Rfc2898DeriveBytes rdb8 = new Rfc2898DeriveBytes(password, salt,50);
...
...
#define ITERATION 50
...
PKCS5_PBKDF2_HMAC(pass, sizeof(pass), salt, sizeof(salt), ITERATION, EVP_sha512(), outputBytes, digest);
...
...
final int iterationCount=50;
PBEParameterSpec pbeps=new PBEParameterSpec(salt,iterationCount);
...
...
const iterations = 50;
crypto.pbkdf2(
password,
salt,
iterations,
keyLength,
"sha256",
function (err, derivedKey) { ... }
);
...
#define ITERATION 50
...
CCKeyDerivationPBKDF(kCCPBKDF2,
password,
passwordLen,
salt,
saltLen
kCCPRFHmacAlgSHA256,
ITERATION,
derivedKey,
derivedKeyLen);
...
...
$hash = hash_pbkdf2('sha256', $password, $salt, 50);
...
...
from hashlib import pbkdf2_hmac
dk = pbkdf2_hmac('sha256', password, salt, 50)
...
bcrypt_hash = bcrypt(b64pwd, 11)
bcrypt
API 时,请务必注意的是,成本参数在确定底层散列过程的计算复杂性方面发挥着重要的作用。强烈建议将成本参数设置为至少 12 的值,以确保达到足够的安全级别。该值直接影响计算散列所需的时间,这使得潜在攻击者执行暴力或字典攻击的计算成本更高。
require 'openssl'
...
key = OpenSSL::PKCS5::pbkdf2_hmac(pass, salt, 50, 256, 'SHA256')
...
let ITERATION = UInt32(50)
...
CCKeyDerivationPBKDF(CCPBKDFAlgorithm(kCCPBKDF2),
password,
passwordLength,
saltBytes,
saltLength,
CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256),
ITERATION,
derivedKey,
derivedKeyLength)
...
...
<param name="keyObtentionIterations" value="50"/>
...
CL_ABAP_HMAC->UPDATE
的调用,这将会导致创建不基于任何数据的散列:
...
DATA: obj TYPE REF TO cl_abap_hmac.
CALL METHOD cl_abap_hmac=>get_instance
EXPORTING
if_key = 'ABCDEFG123456789'
RECEIVING
ro_object = obj.
obj->final( ).
....
CryptCreateHash
的调用,这将会导致创建不基于任何数据的散列:
...
if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, 0)) {
break;
}
if(!CryptHashData(hHash, (BYTE*)hashData, strlen(hashData), 0)) {
break;
}
...
MessageDigest.update()
的调用,这将会导致创建不基于任何数据的散列:
...
MessageDigest messageDigest = MessageDigest.getInstance("SHA-512");
io.writeLine(MyUtilClass.bytesToHex(messageDigest.digest()));
....
...
string hashname = ConfigurationManager.AppSettings["hash"];
...
HashAlgorithm ha = HashAlgorithm.Create(hashname);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 hash
属性来操纵散列算法。一旦程序发布,撤消与用户控制的算法相关的问题就会非常困难,因为很难知道恶意用户是否确定了特定加密散列的算法参数。
...
Properties prop = new Properties();
prop.load(new FileInputStream("config.properties"));
String algorithm = prop.getProperty("hash");
...
MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
messageDigest.update(hashInput.getBytes("UTF-8"));
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 hash
属性来操纵散列算法。一旦程序发布,撤消与用户控制的算法相关的问题就会非常困难,因为很难知道恶意用户是否确定了特定加密散列的算法参数。
require 'openssl'
require 'csv'
...
CSV.read(my_file).each do |row|
...
hash = row[4]
...
digest = OpenSSL::Digest.new(hash, data)
...
end
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 CSV 文件中的 hash
来操纵散列算法。一旦程序发布,撤消与用户控制的算法相关的问题就会非常困难,因为很难知道恶意用户是否确定了特定加密散列的算法参数。
...
String minimumBits = prop.getProperty("minimumbits");
Hashing.goodFastHash(minimumBits).hashString("foo", StandardCharsets.UTF_8);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人都可以通过修改 minimumBits
属性来操纵用于对密码执行散列的最小位。一旦程序发布,撤消有关用户控制的最小位的问题就会非常困难,因为您无法知道密码散列的最小位是否由恶意用户设置。
string salt = ConfigurationManager.AppSettings["salt"];
...
Rfc2898DeriveBytes rfc = new Rfc2898DeriveBytes("password", Encoding.ASCII.GetBytes(salt));
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
属性来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
salt = getenv("SALT");
PKCS5_PBKDF2_HMAC(pass, sizeof(pass), salt, sizeof(salt), ITERATION, EVP_sha512(), outputBytes, digest);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改环境变量 SALT
来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
Properties prop = new Properties();
prop.load(new FileInputStream("local.properties"));
String salt = prop.getProperty("salt");
...
PBEKeySpec pbeSpec=new PBEKeySpec(password);
SecretKeyFactory keyFact=SecretKeyFactory.getInstance(CIPHER_ALG);
PBEParameterSpec defParams=new PBEParameterSpec(salt,100000);
Cipher cipher=Cipher.getInstance(CIPHER_ALG);
cipher.init(cipherMode,keyFact.generateSecret(pbeSpec),defParams);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
属性来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
app.get('/pbkdf2', function(req, res) {
...
let salt = req.params['salt'];
crypto.pbkdf2(
password,
salt,
iterations,
keyLength,
"sha256",
function (err, derivedKey) { ... }
);
}
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
属性来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
@property (strong, nonatomic) IBOutlet UITextField *inputTextField;
...
NSString *salt = _inputTextField.text;
const char *salt_cstr = [salt cStringUsingEncoding:NSUTF8StringEncoding];
...
CCKeyDerivationPBKDF(kCCPBKDF2,
password,
passwordLen,
salt_cstr,
salt.length,
kCCPRFHmacAlgSHA256,
100000,
derivedKey,
derivedKeyLen);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 UITextField inputTextField
中的文本来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
function register(){
$password = $_GET['password'];
$username = $_GET['username'];
$salt = getenv('SALT');
$hash = hash_pbkdf2('sha256', $password, $salt, 100000);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改环境变量 SALT
来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
import hashlib, binascii
def register(request):
password = request.GET['password']
username = request.GET['username']
salt = os.environ['SALT']
dk = hashlib.pbkdf2_hmac('sha256', password, salt, 100000)
hash = binascii.hexlify(dk)
store(username, hash)
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改环境变量 SALT
来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
salt=io.read
key = OpenSSL::PKCS5::pbkdf2_hmac(pass, salt, iter_count, 256, 'SHA256')
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
中的文本来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
@IBOutlet weak var inputTextField : UITextField!
...
let salt = (inputTextField.text as NSString).dataUsingEncoding(NSUTF8StringEncoding)
let saltPointer = UnsafePointer<UInt8>(salt.bytes)
let saltLength = size_t(salt.length)
...
let algorithm : CCPBKDFAlgorithm = CCPBKDFAlgorithm(kCCPBKDF2)
let prf : CCPseudoRandomAlgorithm = CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256)
CCKeyDerivationPBKDF(algorithm,
passwordPointer,
passwordLength,
saltPointer,
saltLength,
prf,
100000,
derivedKeyPointer,
derivedKeyLength)
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 UITextField inputTextField
中的文本来操纵用于派生密钥或密码的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
salt = getenv("SALT");
password = crypt(getpass("Password:"), salt);
...
Example 1
将成功运行,但任何有权使用此功能的人将能够通过修改环境变量 SALT
来操纵用于对密码执行散列的 salt。此外,此代码还使用了 crypt()
函数,该函数不应用于对密码执行加密散列。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
func someHandler(w http.ResponseWriter, r *http.Request){
r.parseForm()
salt := r.FormValue("salt")
password := r.FormValue("password")
...
sha256.Sum256([]byte(salt + password))
}
Example 1
中的代码将成功运行,但任何有权使用此功能的人可以通过修改 salt
环境变量来操纵用于对密码执行散列的 salt。此外,此代码还会使用 Sum256
加密散列函数,而该函数不应该用于对密码执行加密散列。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
Properties prop = new Properties();
prop.load(new FileInputStream("local.properties"));
String salt = prop.getProperty("salt");
...
MessageDigest digest = MessageDigest.getInstance("SHA-256");
digest.reset();
digest.update(salt);
return digest.digest(password.getBytes("UTF-8"));
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
属性来操纵用于对密码执行散列的 salt。一旦程序发布,撤消有关用户控制的 salt 的问题就会非常困难,因为人们可能无法知道密码散列的 salt 是否已经被恶意用户确定。
import hashlib, binascii
def register(request):
password = request.GET['password']
username = request.GET['username']
salt = os.environ['SALT']
hash = hashlib.md5("%s:%s" % (salt, password,)).hexdigest()
store(username, hash)
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 SALT
环境变量来操纵用于对密码执行散列的 salt。此外,此代码还会使用 md5()
加密散列函数,而该函数不应该用于对密码执行加密散列。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
salt = req.params['salt']
hash = @userPassword.crypt(salt)
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人将能够通过修改 salt
参数来操纵用于对密码执行散列的 salt。此外,此代码还使用了 String#crypt()
函数,该函数不应用于对密码执行加密散列。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
let saltData = userInput.data(using: .utf8)
sharedSecret.hkdfDerivedSymmetricKey(
using: SHA256.self,
salt: saltData,
sharedInfo: info,
outputByteCount: 1000
)
示例 1
中的代码将成功运行,但任何有权使用此功能的人可以通过修改 userInput
的值来操纵用于派生加密密钥的 salt。一旦程序发布,撤消与用户控制的 salt 相关的问题就会非常困难,因为很难知道恶意用户是否确定了密码散列的 salt。
...
String seed = prop.getProperty("seed");
Hashing.murmur3_32_fixed(Integer.parseInt(seed)).hashString("foo", StandardCharsets.UTF_8);
...
Example 1
中的代码将成功运行,但任何有权使用此功能的人可以通过修改 seed
属性来操纵用于对密码执行散列的种子。一旦程序发布,撤消有关用户控制的种子的问题就会非常困难,因为您无法知道密码散列的种子是否由恶意用户确定。k
,该值必须是加密随机、对外保密且绝不能重复使用的。如果攻击者可以猜出 k
值或者诱骗签名者使用其提供的值,则他们可以恢复私钥,然后伪造任何签名,从而冒充合法签名者。类似地,如果重复使用 k
值对多条消息进行签名,则攻击者可以恢复私钥。k
,该值必须是加密随机、对外保密且绝不能重复使用的。如果攻击者可以猜出 k
值或者诱骗签名者使用其提供的值,则他们可以恢复私钥,然后伪造任何签名,从而冒充合法签名者。类似地,如果重复使用 k
值对多条消息进行签名,则攻击者可以恢复私钥。k
,该值必须是加密随机、对外保密且绝不能重复使用的。如果攻击者可以猜出 k
值或者诱骗签名者使用其提供的值,则他们可以恢复私钥,然后伪造任何签名,从而冒充合法签名者。类似地,如果重复使用 k
值对多条消息进行签名,则攻击者可以恢复私钥。k
,该值必须是加密随机、对外保密且绝不能重复使用的。如果攻击者可以猜出 k
值或者诱骗签名者使用其提供的值,则他们可以恢复私钥,然后伪造任何签名,从而冒充合法签名者。类似地,如果重复使用 k
值对多条消息进行签名,则攻击者可以恢复私钥。
...
DSA dsa = new DSACryptoServiceProvider(1024);
...
...
DSA_generate_parameters_ex(dsa, 1024, NULL, 0, NULL, NULL, NULL);
...
...
dsa.GenerateParameters(params, rand.Reader, dsa.L1024N160)
privatekey := new(dsa.PrivateKey)
privatekey.PublicKey.Parameters = *params
dsa.GenerateKey(privatekey, rand.Reader)
...
...
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DSA", "SUN");
SecureRandom random = SecureRandom.getInstance("SHA256PRNG", "SUN");
keyGen.initialize(1024, random);
...
...
from Crypto.PublicKey import DSA
key = DSA.generate(1024)
...
require 'openssl'
...
key = OpenSSL::PKey::DSA.new(1024)
...
EVP_SignUpdate
的调用,这将会导致创建不基于任何数据的签名:
...
rv = EVP_SignInit(ctx, EVP_sha512());
...
rv = EVP_SignFinal(ctx, sig, &sig_len, key);
...
update
的调用,这将会导致创建不基于任何数据的签名:
...
Signature sig = Signature.getInstance("SHA256withRSA");
sig.initSign(keyPair.getPrivate());
...
byte[] signatureBytes = sig.sign();
...
示例 2:以下代码使用
Properties props = System.getProperties();
...
properties.setProperty("org.jcp.xml.dsig.secureValidation", "false");
XMLCryptoContext.setProperty
禁用 XML 签名安全验证:
DOMCryptoContext cryptoContext = new DOMCryptoContext() {...};
...
cryptoContext.setProperty("org.jcp.xml.dsig.secureValidation", false);
...
CCCrypt(kCCEncrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding,
key,
kCCKeySizeDES, // 64-bit key size
iv,
plaintext,
sizeof(plaintext),
ciphertext,
sizeof(ciphertext),
&numBytesEncrypted);
...
...
let iv = getTrueRandomIV()
...
let cStatus = CCCrypt(UInt32(kCCEncrypt),
UInt32(kCCAlgorithmDES),
UInt32(kCCOptionPKCS7Padding),
key,
keyLength,
iv,
plaintext,
plaintextLength,
ciphertext,
ciphertextLength,
&numBytesEncrypted)
...
String
会导致熵大量丢失。String
示例 1:以下代码创建了加密密钥,然后将其转换为 String
。
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
...
KeyGenerator keygen = KeyGenerator.newInstance("AES");
...
SecretKey cryptoKey = keygen.generateKey();
byte[] rawCryptoKey = cryptoKey.getEncoded();
...
String key = new String(rawCryptoKey);
...
String
,但是对于为构造函数分配了字符集有效范围外的字节时将发生何种变化,却没有相关说明。事实上,与原始的 rawCryptoKey
加密密钥相比,key
很可能会造成熵的大量丢失。
static public byte[] EncryptWithRSA(byte[] plaintext, RSAParameters key) {
try {
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(key);
return rsa.Encrypt(plaintext, false);
}
catch(CryptographicException e) {
Console.WriteLine(e.Message);
return null;
}
}
void encrypt_with_rsa(BIGNUM *out, BIGNUM *in, RSA *key) {
u_char *inbuf, *outbuf;
int ilen;
...
ilen = BN_num_bytes(in);
inbuf = xmalloc(ilen);
BN_bn2bin(in, inbuf);
if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, RSA_NO_PADDING)) <= 0) {
fatal("encrypt_with_rsa() failed");
}
...
}
...
import "crypto/rsa"
...
plaintext := []byte("Attack at dawn")
cipherText, err := rsa.EncryptPKCS1v15(rand.Reader, &k.PublicKey, plaintext)
...
public Cipher getRSACipher() {
Cipher rsa = null;
try {
rsa = javax.crypto.Cipher.getInstance("RSA/NONE/NoPadding");
}
catch (java.security.NoSuchAlgorithmException e) {
log("this should never happen", e);
}
catch (javax.crypto.NoSuchPaddingException e) {
log("this should never happen", e);
}
return rsa;
}
+ (NSData *) encryptData:(NSData *) plaintextData withKey:(SecKeyRef *) publicKey {
CFErrorRef error = nil;
NSData *ciphertextData = (NSData*) CFBridgingRelease(
SecKeyCreateEncryptedData(*publicKey,
kSecKeyAlgorithmRSAEncryptionPKCS1,
(__bridge CFDataRef) plaintextData,
&error));
if (error) {
// handle error ...
}
return ciphertextData;
}
function encrypt($input, $key) {
$output='';
openssl_public_encrypt($input, $output, $key, OPENSSL_NO_PADDING);
return $output;
}
...
from Crypto.PublicKey import RSA
message = 'Attack at dawn'
key = RSA.importKey(open('pubkey.der').read())
ciphertext = key.encrypt(message)
...
require 'openssl'
...
key = OpenSSL::PKey::RSA.new 2048
public_encrypted = key.public_encrypt(data) #padding type not specified
...
Example 1
中,仅使用字符串来调用 OpenSSL::PKey::RSA#public_encrypt
,不指定要使用的填充类型。填充类型默认为 OpenSSL::PKey::RSA::PKCS1_PADDING
。
func encrypt(data plaintextData:Data, publicKey:SecKey) throws -> Data {
var error: Unmanaged<CFError>?
guard let ciphertextData = SecKeyCreateEncryptedData(publicKey,
.rsaEncryptionPKCS1,
plaintextData as CFData,
&error) else {
throw error!.takeRetainedValue() as Error
}
return ciphertextData as Data;
}