Twitter OAuth dance使用获得身份验证,但Apex CSRF保护仅为帖子提供

Twitter OAuth dance使用获得身份验证,但Apex CSRF保护仅为帖子提供,oauth,twitter,twitter-oauth,apex-code,visualforce,Oauth,Twitter,Twitter Oauth,Apex Code,Visualforce,这是我想弄清楚的安全问题。一切正常,我可以让用户通过Twitter的身份验证,从我的托管包中发送到AppExchange。问题是Twitter OAuth 1.0进程(或“dance”)有一些通信步骤,这些步骤与从Twitter返回到我的应用程序的GET进行通信。尽管这是可行的,但根据安全测试通过情况以及现在Eclipse中的CxViewer,这是安全审查过程的一个危险信号 但我需要从Twitter上获取这些信息,并以某种方式为每个用户存储这些信息。此问题的一个示例代码入口点(Twitter从我

这是我想弄清楚的安全问题。一切正常,我可以让用户通过Twitter的身份验证,从我的托管包中发送到AppExchange。问题是Twitter OAuth 1.0进程(或“dance”)有一些通信步骤,这些步骤与从Twitter返回到我的应用程序的GET进行通信。尽管这是可行的,但根据安全测试通过情况以及现在Eclipse中的CxViewer,这是安全审查过程的一个危险信号

但我需要从Twitter上获取这些信息,并以某种方式为每个用户存储这些信息。此问题的一个示例代码入口点(Twitter从我的一个auth_令牌请求中回调)是:

第页:


顶点:

公共页面引用完成授权()
{
String token=ApexPages.currentPage().getParameters().get('oauth_token');
CustomObject\uuuuC=新CustomObject\uuuC(名称=令牌);

插入c;//以下是我发现的问题。问题涉及到让GET参数指定有关Salesforce中所选对象的任何内容,然后将数据保存到该对象。我不认为曾经存在过真正的安全问题,并且我的新代码安全测试毫无问题地通过。实际发生的情况是:

String token = ApexPages.currentPage().getParameters().get('oauth_token');

CustomObject__c pcs = [
SELECT Id, User__c, Token__c 
FROM CustomObject__c 
WHERE Id = :UserInfo.getUserId() 
AND Token__c = :EncodingUtil.urlEncode(token, 'UTF-8'];
由于整个交换都是从我的上下文开始的,我对当前用户(UserInfo.getUserId())有100%的把握,因此我不需要检查此特定令牌是否匹配,因为用户是有保证的(至少与我启动此过程有关)。因此,以下选择很好:

CustomObject__c pcs = [
SELECT Id, User__c, Token__c 
FROM CustomObject__c 
WHERE Id = :UserInfo.getUserId()];
然后,如果稍后我更新此对象:

update pcs;
它没有抱怨,因为传入的GET值与为写入选择的对象没有任何联系

WHERE Id = :UserInfo.getUserId()
原因是,无论攻击试图向我的代码中注入什么虚假令牌,它仍然针对当前用户进行验证,如果用户不匹配,在任何情况下都会失败。但在Salesforce中,与大多数系统一样,不可能同时让两个用户登录,因此令牌eck从一开始就太过分了,因为我从不与Twitter共享我的用户ID

需要存储的实际令牌(oauth_令牌和oauth_秘密)可以作为POST参数进行检索,因此具有内置的Salesforce CSRF保护。检索方式如下:

Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint(accessTokenURL);
req.setBody('');
sign(req);
HttpResponse res = new HttpResponse();
String resParams = res.getBody();
Map<String,String> rp = new Map<String,String>();

if(resParams != null)
{
   for(String s : resParams.split('&')) 
   {
      List<String> kv = s.split('=');
      rp.put(kv[0],kv[1]);
   }
}

tK.Secret__c = rp.get('oauth_token_secret');
tK.Token__c = rp.get('oauth_token');

upsert tK; // No problem, it's from a POST body
httph=newhttp();
HttpRequest req=新的HttpRequest();
请求设置方法(“POST”);
请求setEndpoint(accessTokenURL);
要求立根体(“”);
签名(req);
HttpResponse res=新的HttpResponse();
字符串resParams=res.getBody();
Map rp=新Map();
if(resParams!=null)
{
对于(字符串s:resParams.split('&'))
{
列表kv=s.split('=');
rp.put(千伏[0],千伏[1]);
}
}
tK.Secret_uuuc=rp.get('oauth_令牌_Secret');
tK.Token_uuc=rp.get('oauth_Token');
upsert tK;//没问题,这是从一个POST body得到的

我正要发布一份赏金;)

以下是我发现的问题。问题涉及到让GET参数指定有关Salesforce中所选对象的任何内容,然后将数据保存到该对象。我认为从来没有真正的安全问题,而我的新代码安全测试通过时没有问题。发生的是基本上是:

String token = ApexPages.currentPage().getParameters().get('oauth_token');

CustomObject__c pcs = [
SELECT Id, User__c, Token__c 
FROM CustomObject__c 
WHERE Id = :UserInfo.getUserId() 
AND Token__c = :EncodingUtil.urlEncode(token, 'UTF-8'];
由于整个交换都是从我的上下文开始的,我对当前用户(UserInfo.getUserId())有100%的把握,因此我不需要检查此特定令牌是否匹配,因为用户是有保证的(至少与我启动此过程有关)。因此,以下选择很好:

CustomObject__c pcs = [
SELECT Id, User__c, Token__c 
FROM CustomObject__c 
WHERE Id = :UserInfo.getUserId()];
然后,如果稍后我更新此对象:

update pcs;
它没有抱怨,因为传入的GET值与为写入选择的对象没有任何联系

WHERE Id = :UserInfo.getUserId()
原因是,无论攻击试图向我的代码中注入什么虚假令牌,它仍然针对当前用户进行验证,如果用户不匹配,在任何情况下都会失败。但在Salesforce中,与大多数系统一样,不可能同时让两个用户登录,因此令牌eck从一开始就太过分了,因为我从不与Twitter共享我的用户ID

需要存储的实际令牌(oauth_令牌和oauth_秘密)可以作为POST参数进行检索,因此具有内置的Salesforce CSRF保护。检索方式如下:

Http h = new Http();
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint(accessTokenURL);
req.setBody('');
sign(req);
HttpResponse res = new HttpResponse();
String resParams = res.getBody();
Map<String,String> rp = new Map<String,String>();

if(resParams != null)
{
   for(String s : resParams.split('&')) 
   {
      List<String> kv = s.split('=');
      rp.put(kv[0],kv[1]);
   }
}

tK.Secret__c = rp.get('oauth_token_secret');
tK.Token__c = rp.get('oauth_token');

upsert tK; // No problem, it's from a POST body
httph=newhttp();
HttpRequest req=新的HttpRequest();
请求设置方法(“POST”);
请求setEndpoint(accessTokenURL);
要求立根体(“”);
签名(req);
HttpResponse res=新的HttpResponse();
字符串resParams=res.getBody();
Map rp=新Map();
if(resParams!=null)
{
对于(字符串s:resParams.split('&'))
{
列表kv=s.split('=');
rp.put(千伏[0],千伏[1]);
}
}
tK.Secret_uuuc=rp.get('oauth_令牌_Secret');
tK.Token_uuc=rp.get('oauth_Token');
upsert tK;//没问题,这是从一个POST body得到的

我正要发布一个悬赏;)

也许有一个更一般的问题可能有用。有没有人有开发自己的CSRF预防机制的经验?Force.com为帖子内置了保护,但没有为GET内置保护,因为GET可能不应该向缓存/数据库写入任何内容。但是如果我有自己的CSRF保护n例如,使用每个用户会话的自定义唯一令牌,我可能会通过AppExchange安全审查。我想我可以在返回端点中将其作为参数返回Twitter回复(&mytoken=fb3428943y2923cdkwc),但我只是在寻找正确的方法。也许一个更一般的问题可能有用。有没有人有开发自己的CSRF预防机制的经验?Force.com内置了