系统登录的安全设计
前几天一个测试同事,来问一个关于系统登录的测试用例。讲的大概意思是登录系统传输的数据必须加密;cookie中不能保存密码等核心信息。关于这两点我想做过web开发的人都可以理解。
如果满足上述的测试用例要求,是否就满足数据安全要求?最多算是一个合格的设计吧,我们使用密文传输的原因是什么?防止数据包被截获后看到用户名和密码,只要不是用的base64加密,这样的密文能防止70%的人来进行非法利用。实际上加密传输的最终目的是防止被别人利用到数据包,即使是密文,也存在被重复使用的风险。
怎样的数据才算是安全的?第一不使用明文形式传输(测试用例中的第一个使用密文传输);第二即使因为各种原因造成数据被抓包也需要保证不被重复使用。
造成数据被抓包的需要依赖一定的网络环境,如:代理上网、使用集线器等, 所以如何截取数据不属于本次讨论内容。只讨论数据被抓包后可能会造成的风险。
首先看一个例子,系统登录界面(10.24.12.243/cwbase/webapp),用户名叫xq,密码是aaaaaa,通过Fiddle抓包得到的提交的数据内容是:
resource=login¶ms=%5B%5B%22context%22%2C%22W3siQ29kZSI6IlR5cGVDb2RlIiwiVmFsdWUiOiJVc2VyUGFzc3dvcmQifSx7IkNvZGUiOiJCaXpEYXRlIiwiVmFsdWUiOiIyMDE0LTA3LTAzIn0seyJDb2RlIjoiVXNlcklEIiwiVmFsdWUiOiJ4cSJ9LHsiQ29kZSI6IlBhc3N3b3JkIiwiVmFsdWUiOiJhYWFhYWEifSx7IkNvZGUiOiJEZXZpY2VUeXBlIiwiVmFsdWUiOiIzIn1d%22%5D%5D&GSPWEB_VERB_TYPE=post
看到params参数感觉是进行了编码处理,在console里执行unescape解码看看内容(怎么确定params的内容,这里传递的参数都是用&分隔的,params=之后的第一个&就是截止位置),执行解码后得到的内容是:
[["context","W3siQ29kZSI6IlR5cGVDb2RlIiwiVmFsdWUiOiJVc2VyUGFzc3dvcmQifSx7IkNvZGUiOiJCaXpEYXRlIiwiVmFsdWUiOiIyMDE0LTA3LTAzIn0seyJDb2RlIjoiVXNlcklEIiwiVmFsdWUiOiJ4cSJ9LHsiQ29kZSI6IlBhc3N3b3JkIiwiVmFsdWUiOiJhYWFhYWEifSx7IkNvZGUiOiJEZXZpY2VUeXBlIiwiVmFsdWUiOiIzIn1d"]]
可以看到context参数进行了加密处理,首先检查一下密文是否用的Base64加密,解密刚才的密文后得到的内容:
[{"Code":"TypeCode","Value":"UserPassword"},{"Code":"BizDate","Value":"2014-07-03"},{"Code":"UserID","Value":"xq"},{"Code":"Password","Value":"aaaaaa"},{"Code":"DeviceType","Value":"3"}]
这个登录是碰巧采用了Base64加密,所以很容易被解密看到明文。那么如果采用其他加密算法(必须依赖私钥解密)的是否就能保证安全呢。
同样的,看另外一个登录界面(10.24.12.243/cwbase/web/login.aspx),Fiddle抓包后得到的密文是:
resource=loginspi¶ms=%5B%5B%22context%22%2C%22m8V6s3kBP85IU3yY8k6b9R8gFFlBalopTd11o8S7zXfgksQpWIFUE6XCS/esN7Psxi%2bflWsnAnHUFFn86X14cdrNx1/HTqTH766JJSERMoMM2UMJ5uKmyHKCqY7jwM141s1PZ3/qYL2PMbJ/htCKYM%2byjxDxqxUm9Lpcy9G8MPNO7/hu7Ed62z1DgqJeXqqdo2NRt6lhDBiA0iF5xzg%2bWg%3D%3D%22%5D%2C%5B%22randomKey%22%2C%22WufLiPsolCvCuFDl%22%5D%5D&GSPWEB_VERB_TYPE=post
同样的方式处理params,得到params内容为:
[["context","m8V6s3kBP85IU3yY8k6b9R8gFFlBalopTd11o8S7zXfgksQpWIFUE6XCS/esN7Psxi+flWsnAnHUFFn86X14cdrNx1/HTqTH766JJSERMoMM2UMJ5uKmyHKCqY7jwM141s1PZ3/qYL2PMbJ/htCKYM+yjxDxqxUm9Lpcy9G8MPNO7/hu7Ed62z1DgqJeXqqdo2NRt6lhDBiA0iF5xzg+Wg=="],["randomKey","WufLiPsolCvCuFDl"]]
两个参数(context和randomKey),context进行Base64解密发现不是直接使用的Base64加密。那么这种加密的内容我们是否能够利用?查看登录js代码,login.spi.js 代码是未加密的,输入用户名和密码(随意输入)。在调试过程中修改变量context和randomKey为抓包的内容。发现可以跳过验证进入系统。
那么login.spi.js进行加密和压缩之后怎么才能利用这段密文。加入我们看不到、看不懂login.spi.js的代码。我们直接修改$.ajax代码。。。。在console里执行如下代码:
var data="resource=loginspi¶ms=%5B%5B%22context%22%2C%22m8V6s3kBP85IU3yY8k6b9R8gFFlBalopTd11o8S7zXfgksQpWIFUE6XCS/esN7Psxi%2bflWsnAnHUFFn86X14cdrNx1/HTqTH766JJSERMoMM2UMJ5uKmyHKCqY7jwM141s1PZ3/qYL2PMbJ/htCKYM%2byjxDxqxUm9Lpcy9G8MPNO7/hu7Ed62z1DgqJeXqqdo2NRt6lhDBiA0iF5xzg%2bWg%3D%3D%22%5D%2C%5B%22randomKey%22%2C%22WufLiPsolCvCuFDl%22%5D%5D&GSPWEB_VERB_TYPE=post"; var fnAjax=$.ajax; $.ajax=function(){ var arg=[].slice.call(arguments,0); $.each(arg,function(index,item){ if(typeof item=="object"&&item.data!=undefined&&item.data.indexOf("resource=loginspi¶ms=")==0){ item.data=data; } }); fnAjax.apply(this,arg); }
这时候随便输入用户名和密码,登录系统,一样可以跳过身份认证进入。
上述登陆地址,是某Web平台与移动平台的登陆,通过这种方式检查了其他几家大型的管理系统,登陆全存在这样的问题。测试人员如何快速的查找系统,是否存在这种安全问题呢。满足以下情景的基本上就存在安全问题,当然不满足也可能存在安全问题,但需要手动检查(下边只是列举一定存在安全问题的场景)
使用Fiddle抓包:
1、数据包未加密,直接暴露用户名和密码。
2、密码加密,但是使用的是Base64加密(一般Base64加密内容最后两位经常是==)。
3、多次提交登录,对比历次加密内容,如果登录名和密码一样的情况下密文也一样,一定存在安全漏洞。
4、随机码随密文一起提交的。
5、…………