万能密码 'or'='or'如何防


万能密码 'or'='or'如何防

文章插图
【万能密码 'or'='or'如何防】一般用户在登陆时 , 系统会要求输入用户名及密码 , 然后将这些数据传输到指定页 , 进行验证 , 大致的代码如下:Set Conn= Server.CreateObject("ADODB.Connection") '定义连接数据库的对象Const AccessFile="jmdcw.mdb" '数据库地址Conn.ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath(AccessFile) '连接到数据库Conn.Open '打开数据库....................name=request("name") '得到所提交的用户名pass=request("pass") '得到所提交来的密码............Set Jmdcw=Server.CreateObject("ADODB.RecordSet") '定义操作数据库的对象SQL="SELECT username,userpass FROM User WHERE username='"&name&"' AND userpass='"&pass&"'" 'SQL语句Jmdcw.Open SQL,Conn,1,1 '执行查询......If Jmdcw.EOF AND Jmdcw.BOF Then '如果没有查询到response.redirect "onerror.html" '显示错误页end if'如果正确 , 就继续执行 。.......... 以上就是一段简单的用户验证代码 , 当注入漏洞被广泛发掘之后 , 类似这样的漏洞就越来越少了 , 但少并不表示程序员在写代码时已经具备了防范意识 , 无意之中还是会出现这样或那样的漏洞 。OK , 书归正传 , 先来测试一下上面的代码 。输入的用户名是:jmdcw , 密码是:123456 。(典型的弱口令密码 , 哈哈) , 这样SQL语句就是:select username,userpass from user where username='jmdcw' and userpass='123456' 程序会查询user表中是否有jmdcw用户 , 并且该用户的密码是否为123456 。如果username='jmdcw'的结果为真 , userpass='123456'的结果也为真 , 那么“真 And 真 ”的结果就是真 , 验证通过 。当然 , 如果用户名和密码其中之一的结果为假 , “真 And 假 ”的结果就是假 , 当然“ 假 And 假 ”的结果也是假 , 呵呵 。没有用户名或密码怎么进入?试一下'or''='吧 , 在提交用户名处输入 jmdcw'or''=' , 这样的SQL语句就是select username,userpass from user where username='jmdcw'or''='' and userpass='12345678' 在逻辑表达式中 , AND的优先级要高于OR , 所以语句会先对 “''='' and userpass='12345678'” 进行判断 , 虽然 ''='' 为真 , 但密码为假 , 所以结果为假 , 但因为我们加入了OR连接符 , 这样 , 虽然后面的结果为假 , 但username的结果为真 , 所以也一样能进入这个用户的后台 。但如果不知道用户的名称 , 那么就要在输入的密码后也加入一个'or''=' , 这样 , SQL语句就是select username,userpass from user where username='jmdcw11'or''='' and userpass='12345678'or''='' 在执行and语句 , ''='' and userpass='12345678'的结果为假 , 然后是 'jmdcw11'or假  , 结果为假 , 再接下来是:假or ''='' , 这个结果就是真了 。但现在的密码都用MD5加密 , 对提交来的密码在进入SQL语句之前 , 先用MD5进行了转换 , 这样 , 就算在密码后加入了'or''=' , 也发挥不了作用 。对于密码采用md5加密的 , 不妨在用户名处再加入一个or''='' , 也 就是在用户名处输入:jmdcw'or''=''or''=' , 这样的SQL 语句就是:select username,userpass from user where username='jmdcw11'or''=''or''='' and userpass='12345678' 先执行and语句 , 结果为假 , 然后是username='jmdcw11'or''='' , 结果为真 , 接下来是:真or假 , 结果还是真 , 这样又绕过了验证 。说到这儿 , 我忽然想起 , 在文章开头所提到的网站 , 其密码也是用md5加密的 , 并且我也不知道任何一个用户名 , 也只用了一个or语句 , 为什么却进入了呢?思来思去 , 莫不是SQL语句中的用户与密码的位置有所不同 , 其的SQL语句是这样的:select username,userpass from user where WHERE userpass='"&pass&"'" and username='"&name&"' ,  密码在前面 , 用户在后面 , 这样 , 当我在用户名处输入:jm'or''='后 , 其语句就变成了select username,userpass from user where WHERE userpass='123456" and username='jm'or''='' 按照优先级 , 先运算ANd语句 , 结果为假 , 然后是OR语句 , 假or''='' , 结果就是真了 。看来代码中的位置发生变化也能演绎成一种漏洞 。上面所提到的方法主要是针对于ACCESS数据库 , 但如果程序所对应的数据库是SQL , 那危害就大很了 , 先不要说别的 , 还是说一下登陆的事情 , 直接用:存在的用户名';-- 这个可以不用密码就登陆到指定的用户之中,如果不知道呢:就用:任意名称'or''='';-- 这样所进入的会是第一个用户,很有可能是管理员的用户之中. 如何防止这种漏洞呢?很简单 , 就是在接收字符的语句中加入replace过滤语句 , 比如name就是:name=replace(request("name"),"'","") 将'过滤为空 。密码过滤的方法也类似 。当然 , 这是简单的过滤方法 , 还有更多复杂的 。比如过滤一些特殊字符 , 空格、chr(0)、%、script等一些字符 , 防止写入XSS代码 。

推荐阅读