手把手教学_手把手记录SQL注入后绕过后台登陆验证

更新时间:2019-08-11    来源:经典短信    手机版     字体:

【www.bbyears.com--经典短信】

下面直接进入正题吧。一提到绕过后台登陆验证直接进入网站后台管理系统,想必大家都能想到经典的万能密码:or=or吧,今天要给大家分享的一个技巧也和这个差不多,不过是这个方法比较另类。

在讲该技巧之前我们还是先来简单回顾下经典的or=or原理,更详细的原理大家可以网上搜索相关资料了解下。我们都知道后台登陆验证一般的方式都是 将用户在登录口输入的账号密码拿去与数据库中的记录做验证,并且要求输入的账号密码要等于数据库中某条记录的账号密码,验证通过则程序就会给用户一个 sssion,然后进入后台,否则就返回到登陆口。而对于or=or漏洞,我们先来看以下代码:

 代码如下 <%
pwd = request.form("pwd") 获取用户输入的密码,再把值赋给pwd
name = request.form("name") 获取用户输入的用户名再把值赋给name
都没有进行任何过滤
Set rs = Server.CreateObject("ADODB.Connection")
sql = "select * from Manage_User where UserName=" & name & " And PassWord="&encrypt(pwd)&"" 将用户名和密码放入查询语句中查询数据库,
Set rs = conn.Execute(sql) 执行SQL语句,执行后并得到rs对象结果,“真”或“假”
If Not rs.EOF = True Then 如果是真则执行以下代码
Session("Name") = rs("UserName") 将UserName的属性赋给Name的Session自定义变量
Session("pwd") = rs("PassWord") 将PassWord的属性赋给pwd的Session自定义变量
Response.Redirect("Manage.asp")了 利用Response对象的Redirect方法重定向Manage.asp
Else 否则执行以下代码
Response.Redirect "Loginsb.asp?msg=您输入了错误的帐号或口令,请再次输入!"
End If
%>



以上就是一个典型的or=or漏洞例子,针对以上例子我们只需要在用户名处提交or=or,这样就使得SQL语句变成:select * from Manage_User where UserName=’or‘=or And PassWord=123456。执行后得到rs对象的结果为真,这样就能顺利的进入后台了。

为了避免出现这个漏洞,现在基本上的后台验证都不会使用这类方式,而是取得用户输入的账号和密码,在SQL中先将用户名与数据库中的记录做对比,若 数据库中某条记录的用户名等于用户输入的用户名,则取出该条记录中的密码,然后再与用户输入的密码对比,正确就通过,不正确就返回。例如一下代码:

 代码如下
<%
pwd = request.form("pwd") 获取用户输入的密码,再把值赋给pwd
name = request.form("name") 获取用户输入的用户名再把值赋给name
都没有进行任何过滤
Set rs = Server.CreateObject("ADODB.Connection")
sql = "select * from Manage_User where UserName=" & name & "" 将用户名和密码放入查询语句中查询数据库,
Set rs = conn.Execute(sql) 执行SQL语句,执行后并得到rs对象结果,“真”或“假”
If Not rs.EOF = True Then 如果是真则执行以下代码
password=rs("password") 取得密码数据
if password=md5(pwd) then
Session("Name") = rs("UserName") 将UserName的属性赋给Name的Session自定义变量
Session("pwd") = rs("PassWord") 将PassWord的属性赋给pwd的Session自定义变量
Response.Redirect("Manage.asp")了 利用Response对象的Redirect方法重定向Manage.asp
else
response.write "密码错误!!!!"
end if
Else 否则执行以下代码
Response.Redirect "Loginsb.asp?msg=您输入了错误的帐号或口令,请再次输入!"
End If
%>



通过以上例子可知道,密码的验证不再是直接在SQL语句中做验证了,而是根据用户名,取出对应的密码,然后再与用户输入的做对比。这样一来就造成了 我们不能使用or=or绕过了。有的朋友在这里可能有疑问了,若我们提交or=or那么SQL语句就变成:

 代码如下 select * from Manage_User where UserName=or=or,



这样一来得到的结果也应该是真啊,为什么就不能绕过呢?

其实就算SQL查询的地方得到的值是真,可别忘了后面还有密码的验证,若我们提交以上SQL,得到账号是真的,那么后面根据账号去数据库中取出来的密码与用户提交的密码是绝对通不过的。

好了,对于or=or漏洞的分析先就暂且说到这里,以上的均为我个人对该漏洞的理解,并不代表就是完全正确的,若有不当的地方还望大家多多指教,接下来就是我们的重头戏了。

昨天在帮流年看站的时候就遇到了一个旁站,当时是想注入,后来流年拿下服务器后顺便就将程序打包下来我研究了下,经过两个多小时的分析和测试,终于可以成功绕过了那套系统的后台登陆验证,接下来就结合程序代码,将我的整个分析过程给大家详细讲解下。

程序类型是国外的一个小型商城系统,在检测的时候我就顺便构造了个关键词用google搜索下发现还有不少的网站。加之又是国外的,所决定要深入研 究下,不过国外程序员在写程序的时候习惯和国内还是有不少的差异,往往国外的目录文件和程序结构分枝都很深,这点还让我在分析源代码的时候被代码牵着鼻子 到处转……

在拿到程序原本是首先看前台的注入的,但在打开数据库找到管理密码后我就放弃了从前台寻找注入的打算,因为管理的密码根本没法破解,就算找到注入用处也不大。因此要寻找程序的致命弱点只有往网后台或者无需验证的上传页面方向去了,然后查看了下所有的上传都需要后台验证才能上传。到此,唯一的路就是想法突破后台了。

首先我们来看看后台登陆口(login.asp)的代码:

 代码如下
<%
if request.form("Submit") = " Login " then
if trim(request("yanzheng"))=session("ValidCode") then
if DoLogin(request.form("LoginId"),request.form("Password")) = 1 then
response.redirect("index.asp")
end if
else
response.Redirect("login.asp?p=login")
end if
end if
%>



通过以上代码可以看出,login.asp页面验证登陆是将用户输入的账号和密码交给DoLogin函数验证,在DoLogin函数中,验证通过将返回一个值为1(通过验证进入后台),反之不等于则重定向到登陆页面。我们现在来看看DoLogin函数的内容。

 代码如下
<%
private function DoLogin(login, pass)
set rsLogin = server.createobject("ADODB.recordset")
rsLogin.cursortype = 3
strSQL = "Select admin_id, admin_salt, admin_password FROM admin_users Where admin_login = " & login & ""
rsLogin.open strSQL, adoCon
response.Write strSQL
if not rsLogin.eof then
correctPass = rsLogin("admin_password")
controlPass = hashEncode(pass & rsLogin("admin_salt"))
if correctPass = controlPass then
DoLogin = 1
session("admin_user_id") = rsLogin("admin_id")
session("session_id") = session.SessionID
session("order_flag") = 1
else
DoLogin = 0
end if
else
DoLogin = 0
end if
rsLogin.close
set rsLogin = nothing
end Function
%>



“private function DoLogin(login, pass)”中的login何pass分别就是在上面的login.asp中的request.form("LoginId")和 request.form("Password"),从以上代码中可以看到用户输入的账号和密码没有经过任何的过滤就带入到SQL语句中查询了。查询后的 验证方式就和上文中提及的验证方式大同小异了。

现在知道用户输入的账号和密码没有经过过滤(这点很重要),接下来我们还需要清楚管理员表的结构,这里我给大家截图上来,管理员表名是admin_users,结构如下图:


\



可以看到管理员表中有四个字段,分别是ID号、用户名、以及salt和密码,密码在第四列。有了这些信息后我们就要开始着手构造SQL语句绕过后台登陆了。

 

通过对登陆验证代码的分析,我们可以将整个验证过程简单描述为:验证函数取得用户输入的账号和密码,然后从管理员表中查询某条用户名等于用户输入用 户名的记录,如果查询后得知管理表中存在某条记录,则继续取出该条记录的密码,然后再将此密码与用户输入的密码进行对比(用户输入的密码要经过加密),若密码验证成功则通过后台验证。

现在我们的突破策略就是:提交某个SQL语句,让程序从管理员表中查询某条用户名等于用户输入用户名的记录结果为真,这样程序就会继续验证密码,然后我们再让程序从上步查询中得到一个密码的密文,这样一来就会顺利的通过验证了。

突破程序查询用户名得到一个真值比较容易能做到,但后面的让程序同时得到一个密码的密文我想还真不容易办到,而且还要在一步中完成。但是办法确实是有的,这里我就直接给大家贴出来,这个办法也是我从自然兄那里学来的,说实在的我真是非常佩服想出这个办法的牛人。

本文来源:http://www.bbyears.com/zhufuduanxin/61526.html

热门标签

更多>>

本类排行