windows下sqli-labs的搭建及学习(POST篇)

来源:互联网 发布:mac 卸载百度云盘 编辑:程序博客网 时间:2024/06/10 19:28

windows下sqli-labs的搭建及学习(GET篇):

http://blog.csdn.net/sherlock17/article/details/64454449

Less-11:基于错误的_post_单引号_字符型注入

     post型的注入一般都是登录绕过,测试的方法与get都类似,通过查看源码我们知道以post方式传递的两个参数是uname和passwd,那么首先来尝试下单引号

     从这里的报错中可以知道后台的sql语句应该是select username,password from table where username='$_GET['uname']' and password='$_GET['passwd']' limit 0,1

     而这里之所以报错是因为加号没有被转义,可以换成--%20来注释后面的limit,然后我们可以构造永真语句绕过登录

     接着猜字段数

     再试试3,报错,说明用select查询的是两个字段


    于是 用union来爆数据库名


     依次爆表名,字段

     最后的payload:

     这里还有一个需要注意的地方,username和password的输入框都可以作为注入点,但是在前一个参数处注入时只能注释掉后面的语句,而在最后一个参数处注入时既可以注释也可以闭合,闭合即uname=&passwd=' or 1='1,后一个1前的单引号会与limit前的单引号匹配(闭合)可以正常执行,之所以username那里不能使用闭合,是因为一旦使用后语句将变成:

     select username,password from table where username='$_GET['uname']' or 1=1 and password='$_GET['passwd']' limit 0,1

     这里的and运算符优先级比or高,语句会先执行1=1 and password='$_GET['passwd']',因为我们并不知道正确的password值,故该语句必为flase,且username的值也是flase,两者进行or运算,其结果也必然是flase


Less-12:基于错误的_双引号_post_字符型_变形注入

     尝试单引号没反应,再试试双引号

     绕过登录:

     方法同之前一样,payload:


Less-13:单引号_post_字符型_双注入_变形注入

     尝试之前的方法,可以登入但没有返回用户信息

     从源码中可以看到,输出被注释了

     于是尝试双注入,直接上payload:



Less-14:双引号_post_字符型_双注入_变形注入

     把less-13改成双引号就行了


Less-15:单引号_post_bool型/时间型盲注

     输入单引号和双引号出错但都没显示报错,加入永真式单引号可以登入,但也没有用户信息

     尝试双注入,仍然没有用户信息返回

     查看源码发现,他将输出和sql报错都注释了,less-13仅注释了输出所以可以用双注入

     这里只能考虑盲注了,因为合法输入和非法输入返回的是不同的页面,所以这里可以用bool盲注,盲注通常都是先确定数据库名,表名,字段名的长度,然后再匹配内容,如下测试数据库名的长度



     由此可以确定数据库名的长度是8,接着来匹配名字的8位字母

     于是可以确定数据库名的第一个字母是's',按照这个方法逐个去匹配,最好的方式还是写个脚本,省时省力


Less-16:双引号_post_bool型/时间型盲注

     输入uname=&passwd=") or 1=1%23显示登入,其余的和less-15没有什么不同,但也可以用来练下时间型盲注,可以构造如下两种:

     uname=&passwd=") or (ascii(substr((select database()) ,1,1))) >115 or if(1=1, sleep(5), null)%23

     uname=&passwd=") or if(ascii(substr((select database()) ,1,1))>115,1,sleep(5))%23


Less-17:基于错误的_post_更新查询注入

     单双引号尝试后,他的画风始终是这样子的

     注意到他的提示password reset,估计后台会用到update,于是去翻了下源码,果然

     他的大概执行过程是接收到username和password后,首先根据username的值查询数据库返回username和password,然后再将原有的password值用接收到的值替换掉,这里有一个问题是,username在接收时用了一个自定义的过滤函数check_input(),这个函数首先做了判空处理,合法就截取username的前15个字符,然后是通过get_magic_quotes_gpc()的返回值判断magic_quotes_gpc的值是on还是off:

     magic_quotes_gpc=on时, 不用对输入和输出数据库的字符串数据作addslashes()和stripslashes()的操作,数据也会正常显示。

如果此时对输入的数据作了addslashes()处理,那么在输出的时候就必须使用stripslashes()去掉多余的反斜杠。
     magic_quotes_gpc=off 时,必须使用addslashes()对输入数据进行处理,但并不需要使用stripslashes()格式化输出,因为addslashes()并未将反斜杠一起写入数据库,只是帮助mysql完成了sql语句的执行。
     最后,他用了ctype_digit()判断username值的类型是否是数字,是字符就用mysql_real_escape_string对特殊字符进行转义

     显然,username这里并不好注入,只有通过弱口令爆破,像是admin之类的,但是他对password的接收没有做过滤的处理,于是我们可以在这里动手脚

     对于update的注入有几种思路,我们将他连同insert和delete一起来总结一下:
     1、子查询注入
     子查询注入原理即双注入,对于dateup、delete和insert通常都是结合or的逻辑判断,本题为例我们对update可以构造如下语句
     获取数据库名:

     获取表名:

     获取字段名:

     获取用户信息;

    这里就 直接放insert和delete的后台语句了,利用原理和构造的语句与update都是一样的:
INSERT INTO users (username, password) VALUES ('admin',' or (SELECT 1 FROM(SELECT count(*),concat((SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e) FROM information_schema.tables),floor(rand()*2))x FROM information_schema.tables group by x)a)%23);

DELETE FROM users WHERE id=1 or (SELECT 1 FROM(SELECT count(*),concat((SELECT concat(0x7e,0x27,cast(database() as char),0x27,0x7e) FROM information_schema.tables),floor(rand()*2))x FROM information_schema.tables group by x)a)%23;
     2、通过name_const():    
     name_const(name,value):
返回给定值,当用来产生一个结果集合列时, name_const()促使该列使用给定名称
     但他的使用范围受限,只适用于一些数据库版本高于5.0.12,但又稍旧的版本,像现在的5.7版本就不用想了...然而我用的就是较新的版本,注入只能显示数据库的版本信息,想要查询其他的信息,会显示Incorrect arguments to NAME_CONST,所以,这里我就不截图了,直接放payload:
     获取数据库:
' or (SELECT * FROM (SELECT(name_const(database(),1)),name_const(database(),1))a) where username='admin'%23
     获取表名:
' or (SELECT * FROM(SELECT name_const((SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'),1),name_const(( SELECT group_concat(table_name) FROM information_schema.tables WHERE table_schema='security'),1))a)%23
     总的来说,对于update,insert和delete都有一个固定的结构:... or (select * from(select name_const((select ...),1),name_const((select...),1))a) ...
     3、通过updatexml():
     updatexml(xml_target,xpath_expr,new_xml)函数是MYSQL对XML文档数据进行查询和修改的XPATH函数,xml_target是目标xml,形式类似于节点目录,xpath_expr是xml的表达式,new_xml是用来替换的xml,简单来说就是,用new_xml把xml_target中包含xpath_expr的部分节点(包括xml_target)替换掉,比如,updatexml(<a><b><c>asd</c></b><e></e></a>,'//b',<f>abc</f>)运行结果是<a><f>abc</f><e></e></a>,其中'//b'的斜杠表示不管b节点在哪一层都替换掉,而'/b'则是指在根目录下替换,此处xml_target的根目录节点是a
     利用updatexml()获取数据的固定payload是:... or updatexml(1,concat(0x7e,(...)),0) ....updatexml()的xml_target和new_xml参数随便设定一个数就行,这里主要让他报错
     首先获取数据库名:

     获取表名:

     获取字段名:

     获取用户信息:

     报错了,百度一下,说是不能先select出同一表中的某些值,再update这个表(在同一语句中),也就是说将select出的结果再通过中间表select一遍,这样就规避了错误,其实之前在子查询注入中也有用到此方法,同时,还要给多加的一重select赋一个别名
     注意,这个问题只出现于mysql,mssql和Oracle不会出现此问题

     最后总结一下payload:or updatexml(1,concat(0x7e,(select * from(select ....)a),0x7e),0)%23
     4、通过extractvalue():
     extractvalue(xml,value)函数也是MYSQL5.1以后推出的对XML文档数据进行查询和修改的XPATH函数,注入时第一个参数随便给一个数字
     直接上payload:

     payload:or extractvalue(1,concat(0x7e,(select * from(select ....)a),0x7e))%23

Less-18:基于错误的_post_用户代理_头部注入
    




参考文献:
http://blog.csdn.net/ysynhtt/article/details/45115849
http://blog.csdn.net/priestmoon/article/details/8016121

0 0
原创粉丝点击