我正在修改一个通过webview使用webapp的Android应用程序。目前,webapp的代码库是用ColdFusion编写的 - 所以所有会话管理都是用CF完成的。 webapp中有一些钩子强制Android应用程序执行本机功能,有时会调用PHP中的外部脚本。
这些php脚本将数据发布给他们(userid,friendid等) - 目前php脚本只是确保发布有效数据,然后处理请求,如果数据存在且有效。
我正在寻找提高这些php脚本安全性的方法,以防止机器人/恶意用户向这些页面发布错误数据 - 此时不会阻止任何人发送正确的用户ID / friendid并让脚本执行。< / p>
会话管理将是第一道防线,但由于webapp使用不同的语言,我无法使用它 - 有时php脚本完全在不同的域上(尽管是同一台服务器)。
我考虑的另一种方法是注册创建用户令牌以与用户关联,并将其保存在Android方面 - 然后在请求这些php脚本时发送用户ID和令牌。并验证该用户的令牌是否与远程数据库匹配 - 这将使得更难以猜测恶意用户的发布凭据。显然不是最好的,因为令牌存储在本地并通过线路,但我离题了。
问题是否有更好的方法可以保护这些单独的php脚本不被执行,而不使用会话管理?我的令牌想法有意义吗?
注意:我可以在任何/所有请求中使用SSL。
答案 0 :(得分:6)
如果你能完成任务,我确切地知道你需要什么。您的API需要实现OAuth2.0。
OAuth可以为您提供的是一种安全的方式,可以将信息传入和传出您的服务,同时确保所有机密信息都保密,并且只有正确的人才能访问该信息。它为每个用户提供了一个独特的签名。
Facebook,Google,Twitter等使用OAuth为开发人员提供了一种安全的访问信息的方式,同时让每个人都不会做他们不应该做的事情。
OAuth支持ColdFusion,Java,PHP,C#,dotNet,VB.net,LIST,Javascript,Perl,Python,Ruby等。
答案 1 :(得分:3)
会话管理或OAuth是最好的解决方案,但不是最简单的解决方案。更简单的方法是在应用程序和PHP脚本中实现散列算法。当应用程序准备请求时,您使用secret方法散列一些发送到服务器的值。此哈希与请求一起发送。服务器执行相同操作并比较两个哈希值。当它们相同时,它知道请求来自应用程序(或破解算法的人)。当它们不存在时,服务器可以简单地忽略该请求。
示例:
数据: userid = 2042; name = JohnDoe; email = john-doe@someprovider.com
哈希(在PHP中,但您也应该在应用中实现它):
<?php
$userid = 2042;
$name = 'JohnDoe'
$email = 'john-doe@someprovider.com';
// Remove some letters with other letters
$name = str_replace(array('a', 'd', 'g'), array('E', 'x', '9'), $name);
// Reverse a string
$email = strrev($email);
// Make a super secret hash (with salt!)
$hash = sha1('fnI87' . $useris . '87bk;s.' . $name . 'unf%gd' . $email);
// Some more fun
$hash = str_rot13($hash);
?>
现在,服务器可以应用相同的散列方法,并将生成的散列与请求发送的散列进行比较。
答案 2 :(得分:2)
我想建议一种更抽象的方法,但与Jonathan的方法类似。
我做出以下假设:
您需要的是识别您的应用发送请求的方式,而不是其他人。
我们的想法是为每个只有你的应用程序的请求生成一个签名(即一个salt +一个哈希)。
$input = array(
"userid" => 1234,
"friendid" => 2345
"etc" => "..."
);
$salt = "s3kr4tsal7"; // this is essentially your app signature
$signature = md5($salt . serialize($input)); // you could also use json_encode or any other to-string serialization
// pick whichever is easy to do in PHP and in your app
$request = array(
"input" => $input,
"signature" => $signature
); // send this
然后在PHP脚本中检查签名是否与计算出的签名匹配。这类似于Jonathan的解决方案,但它允许任何输入,它不依赖于$email
或任何其他属性。我也认为你不需要一个过于复杂的散列算法,只需md5
盐就足够了。
你应该注意另一种类型的攻击,那就是重放攻击。
如果您查看线路上的 RAW 数据,您可以捕获它并再次播放。如果您知道哪个动作有什么输出,您可以简单地重复输出。
重放攻击的典型解决方案是试验和响应。 SSL会为您执行此操作,但您也可以进行自定义实现(但这要复杂得多)。
答案 3 :(得分:2)
与往常一样,这取决于您需要什么级别的保护,以及您愿意投入多少。由于您无法使用会话,因此需要某种无状态方式进行身份验证。通常有两种方法:每次发布凭证(例如,基本身份验证)或发送某种令牌(BTW,会话ID就是这样,一个链接到服务器上的实时会话的令牌)。
生成令牌时,最好使用标准且经过验证的算法,而不是发明自己的和/或依赖默默无闻。即使它看起来大部分都是安全的,也可能不是。例如,上面已经存在针对MD5想法的攻击(很容易在不知道密钥的情况下将数据附加到消息并获得另一个有效的MAC)。 HMAC-SHA1旨在避免这些。
首先要做的是:如果可以,做对所有请求使用SSL。这将同时完成一些事情:
您似乎已经有经过身份验证的用户,因此发放令牌应该相对容易。您可能想要考虑要实现的协议,但是当您考虑更多情况时,您将更接近重新发明OAuth和朋友。有些事情需要考虑:
为了确保您(即您的网络应用程序)是唯一可以发出所述令牌的人,您只需要使用密钥签名即可。由于签名者和验证者是相同的(您),您不必使用公钥加密,HMAC应该这样做。例如,您可以连接用户名,发布时间和任何其他相关信息,并将它们用作HMAC的输入。将这些参数与签名(HMAC输出)一起打包以创建令牌,并让应用程序随每个请求发送它。在服务器上验证并在有效时允许访问,如果过期则需要重新登录(新令牌),否则拒绝访问。
或者,如果您只想对应用进行身份验证,而不是在此处混淆用户信息,则可以使用类似的方法在客户端(应用程序端)签署请求。如果选择这种方式,请使用标准算法。当然,这需要签名密钥(以某种形式)在应用程序中,因此如果有人掌握它(通过逆向工程等),他们可以发出任意数量的请求。有一些方法可以缓解这种情况:
当然,最简单的方法是在服务器上要求基本或摘要式身份验证(当然是通过SSL),并在应用程序中嵌入用户名和密码(充分混淆)。在服务器端只需要更改服务器配置,在客户端添加了几行。缺点是,如果这些凭证遭到入侵,实际上无法更改这些凭据(缺少发布新版本并阻止旧版本访问以强制人们更新;不太漂亮)。