看到有人说了判断能否sql注入的方法:

简单的在参数后边加一个单引号,就可以快速判断是否可以进行SQL注入,这个百试百灵,如果有漏洞的话,一般会报错。

下面内容参考了这两篇文章

http://blog.csdn.net/stilling2006/article/details/8526458

http://www.aichengxu.com/view/43982

nginx配置文件位置:/usr/local/etc/nginx/nginx.conf

主目录位置:/usr/local/Cellar/nginx/1.10.1/

Symfony位置:/Users/baidu/Documents/Data/Work/Installed/symfony/mywebsite/web

先在主目录创建一个文件 test.php,内容如下:

<?php
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);
$sql = 'select nickname from user where id = 1';
$result = mysql_query($sql);print_r('rows:' . mysql_num_rows($result) . '<br/>');
while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');
}mysql_close($con);
?>

上面,注意几个细节:

1. mysql连接要关的,使用mysql_close,之前因为没关,始终有连接存在

2. mysql_num_rows获得行数,mysql_fetch_array获得每次结果。

然后,nginx运行之后,得到运行结果:

http://localhost:8080/test.php

PHP version:5.5.30
rows:1
abc

下面,改造成从参数拿sql参数。

<?php
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);$input_id = trim($_GET['id']);
$sql = 'select nickname from user where id = ' . $input_id;
var_dump('SQL is:' . $sql);
$result = mysql_query($sql);if ($result != null) {print_r('rows:' . mysql_num_rows($result) . '<br/>');while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');}
}mysql_close($con);
?>

在上面,会使用id参数添加到sql里面,并且会将sql打印出来。

得到结果

http://localhost:8080/test.php?id=3

PHP version:5.5.30
string(50) "SQL is:select nickname from user where id = 3
" rows:1
microhttp://localhost:8080/test.php?id=3 or 1=1

PHP version:5.5.30
string(57) "SQL is:select nickname from user where id = 3 or 1=1
" rows:4
abc
micro
helloworld
你好注意,开始的时候上面输出'你好'的是中文乱码。只需要在php文件开始加上下面这句,就可以避免乱码:<?php
header('Content-Type: text/html; charset=utf-8');

从上面可以看出,发生了sql注入。用户可以打印出所有的用户信息。

再引申一下。有的时候,我们会用引号将参数包住,但是这样仍然不能解决问题。

将PHP改成如下:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);$input_id = trim($_GET['id']);
$sql = 'select nickname from user where id = \'' . $input_id . '\'';
print_r('SQL is:' . $sql . '<br/>');
$result = mysql_query($sql);if ($result != null) {print_r('rows:' . mysql_num_rows($result) . '<br/>');while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');}
}mysql_close($con);
?>

上面把var_dump换成了print_r,以免sql语句总是换行。

这时候,不同url访问获得的结果如下:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
SQL is:select nickname from user where id = '3'
rows:1
microhttp://localhost:8080/test.php?id=3 or 1=1

PHP version:5.5.30
SQL is:select nickname from user where id = '3 or 1=1'
rows:1
microhttp://localhost:8080/test.php?id=3' or '1'='1

PHP version:5.5.30
SQL is:select nickname from user where id = '3' or '1'='1'
rows:4
abc
micro
helloworld
你好

上面可以看到,加了引号,对于之前的情况是能够避免了。但是只要稍作调整,又能够成功进行sql注入了。

有时候,攻击者还会在参数里面加上'--'。这是因为sql会认为 -- 右边的都是注释,这样能够更方便对sql的控制。

首先将test.php改成如下,增加一个参数:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);$input_id = trim($_GET['id']);
$name = trim($_GET['name']);
$sql = 'select nickname from user where id = \'' . $input_id . '\' and nickname = \'' . $name . '\'';
print_r('SQL is:' . $sql . '<br/>');
$result = mysql_query($sql);if ($result != null) {print_r('rows:' . mysql_num_rows($result) . '<br/>');while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');}
}mysql_close($con);
?>

然后对于不同url的访问结果:

http://localhost:8080/test.php?id=3

PHP version:5.5.30
SQL is:select nickname from user where id = '3' and nickname = ''
rows:0http://localhost:8080/test.php?id=3&name=micro

PHP version:5.5.30
SQL is:select nickname from user where id = '3' and nickname = 'micro'
rows:1
microhttp://localhost:8080/test.php?id=3 or 1=1

PHP version:5.5.30
SQL is:select nickname from user where id = '3 or 1=1' and nickname = ''
rows:0http://localhost:8080/test.php?id=3' or '1'='1

PHP version:5.5.30
SQL is:select nickname from user where id = '3' or '1'='1' and nickname = ''
rows:1
micro
http://localhost:8080/test.php?id=3' or '1'='1&name=micro

PHP version:5.5.30SQL is:select nickname from user where id = '3' or '1'='1' and nickname = 'micro'rows:1micro

以上例子可以看出,即使加了sql注入,但是拼出来的sql仍然受到了限制只能返回一行。不过,加了 -- 注释符号,情况就又不一样了。

http://localhost:8080/test.php?id=3' or 1=1 --'

PHP version:5.5.30
SQL is:select nickname from user where id = '3' or 1=1 --'' and nickname = ''
rows:1
microhttp://localhost:8080/test.php?id=3' or 1=1 -- '

PHP version:5.5.30
SQL is:select nickname from user where id = '3' or 1=1 -- '' and nickname = ''
rows:4
chaoliu
micro
helloworld
你好http://localhost:8080/test.php?id=3' or 1=1; -- '

PHP version:5.5.30
SQL is:select nickname from user where id = '3' or 1=1; -- '' and nickname = ''
rows:4
chaoliu
micro
helloworld
你好

这3个例子要仔细看。一定要注意,-- 的前后都要加上空格才会生效。

另外,在参数里加上分号; 对于拼接sql的代码,也是会生效的。

现在试试,直接在url里面对数据库内容进行修改。

http://localhost:8080/test.php?id=3'; update user set nickname='a' where id=1; -- '

PHP version:5.5.30
SQL is:select nickname from user where id = '3'; update user set nickname='a' where id=1; -- '' and nickname = ''貌似运行没有成功。
但是直接把sql贴到Mysql客户端运行是可以成功的。

PHP的error log是在

/usr/local/var/log/php_errors.log

但是没有看到有打印错误内容。

去查看了Mysql的error日志,在Mysql机器上面的

/home/work/.jumbo/var/lib/mysql 目录里面有几种日志,也没有看到信息。

所以想到查binlog看看。binlog的查看方法(在Mysql客户端里面):

mysql> show binlog events in 'mysql-bin.000005'\G*************************** 207. row ***************************Log_name: mysql-bin.000005Pos: 18070Event_type: QueryServer_id: 1
End_log_pos: 18144Info: BEGIN
*************************** 208. row ***************************Log_name: mysql-bin.000005Pos: 18144Event_type: QueryServer_id: 1
End_log_pos: 18254Info: use `springdemo`; update user set nickname='abc' where id=1
*************************** 209. row ***************************Log_name: mysql-bin.000005Pos: 18254Event_type: XidServer_id: 1
End_log_pos: 18281Info: COMMIT /* xid=7772 */
209 rows in set (0.00 sec)

里面只记录了更新的日志。而且发现通过上面修改的更新是没有的。

还有一些其他binlog相关的命令:

mysql> show master status\G
*************************** 1. row ***************************File: mysql-bin.000005Position: 18281Binlog_Do_DB:
Binlog_Ignore_DB:
1 row in set (0.00 sec)mysql> show binary logs;
+------------------+-----------+
| Log_name         | File_size |
+------------------+-----------+
| mysql-bin.000001 |     29776 |
| mysql-bin.000002 |   1036239 |
| mysql-bin.000003 |       769 |
| mysql-bin.000004 |       397 |
| mysql-bin.000005 |     18281 |
+------------------+-----------+
5 rows in set (0.00 sec)另外,也可以用mysqlbinlog工具查看。还没有试过。

看起来这条url是不能生效的。

http://localhost:8080/test.php?id=3%27;%20update%20user%20set%20nickname=%27ab%27%20where%20id=1;%20--%20%27

又试了下drop table的命令

http://localhost:8080/test.php?id=3%27;%20drop%20table%20users;%20--%20%27对于下面这个表:
mysql> create table users ( a varchar(20), b varchar(10), primary key (a) );
Query OK, 0 rows affected (0.12 sec)运行上面的url之后,仍然存在PHP version:5.5.30SQL is:select nickname from user where id = '3'; drop table users; -- '' and nickname = ''

与原文描述的不一样了:http://blog.sina.com.cn/s/blog_6a384fce0100n95f.html

下面来说解决的办法:

1. 通过正则表达式匹配校验,或其他格式的校验(较复杂不规范)

2. 通过addslashes或者str_replace(比如把引号'替换成\引号')处理(有漏洞)

3. 通过mysql_real_escape_string处理(有漏洞)

4. 通过mysqli处理,用PreparedStatement(推荐)

5. 通过PDO(PHP Data Object)处理,也是用PreparedStatement(推荐)

对于1,太复杂琐碎,不做讨论。

对于2其中的str_replace,也不规范,不做讨论。

2其中的addslashes和mysql_real_escape_string 都存在由于客户端和Mysql服务器编码方式不一致导致的编码转换丢失和字符一分为二导致的漏洞。后面详述,先看本来的方案。

参考 http://www.aichengxu.com/view/43982

addslashes:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);$input_id = addslashes($_GET['id']);
$name = addslashes($_GET['name']);
$sql = 'select nickname from user where id = \'' . $input_id . '\' and nickname = \'' . $name . '\'';
print_r('SQL is:' . $sql . '<br/>');
$result = mysql_query($sql);if ($result != null) {print_r('rows:' . mysql_num_rows($result) . '<br/>');while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');}
}mysql_close($con);
?>

测试上面的一些URL:

http://localhost:8080/test.php?id=3&name=microPHP version:5.5.30SQL is:select nickname from user where id = '3' and nickname = 'micro'rows:1micro注:正常

http://localhost:8080/test.php?id=3%27%20or%201=1;%20--%20%27

PHP version:5.5.30
SQL is:select nickname from user where id = '3\' or 1=1; -- \'' and nickname = ''
rows:0注:防御成功

mysql_real_escape_string:

<?php
header('Content-Type: text/html; charset=utf-8');
echo "PHP version:" . PHP_VERSION . "<br/>";$con = mysql_connect('10.117.146.21:8306', 'root', '[password]');
mysql_select_db('springdemo', $con);$input_id = mysql_real_escape_string($_GET['id']);
$name = mysql_real_escape_string($_GET['name']);
$sql = 'select nickname from user where id = \'' . $input_id . '\' and nickname = \'' . $name . '\'';
print_r('SQL is:' . $sql . '<br/>');
$result = mysql_query($sql);if ($result != null) {print_r('rows:' . mysql_num_rows($result) . '<br/>');while ($row = mysql_fetch_array($result)) {print_r($row['nickname'] . '<br/>');}
}mysql_close($con);
?>

注,mysql_real_escape_string函数需要连到Mysql服务器才能够工作。

测试一些URL:

http://localhost:8080/test.php?id=3&name=micro

PHP version:5.5.30
SQL is:select nickname from user where id = '3' and nickname = 'micro'
rows:1
microhttp://localhost:8080/test.php?id=3%27%20or%201=1;%20--%20%27

PHP version:5.5.30
SQL is:select nickname from user where id = '3\' or 1=1; -- \'' and nickname = ''
rows:0

讨论上面两个函数里面的漏洞 http://www.t086.com/article/5027:

主要是针对这个字符:chr(0xbf).chr(0x27).该漏洞最早2006年被国外用来讨论数据库字符集设为GBK时,0xbf27本身不是一个有效的GBK字符,但经过  addslashes()  转换后变为0xbf5c27,前面的0xbf5c是个有效的GBK字符,所以0xbf5c27会被当作一个字符0xbf5c和一个单引号来处理,结果漏洞就触发了。mysql_real_escape_string() 也存在相同的问题,只不过相比  addslashes() 它考虑到了用什么字符集来处理,因此可以用相应的字符集来处理字符。
意思是如果客户端和服务器能够设置一样的字符集,那么可以避免这个漏洞。当mysql_real_escape_string检测到的编码方式跟client设置的编码方式(big5/bgk)不一致时,mysql_real_escape_string跟addslashes是没有区别的 。[client]
default-character-set=latin1
+
mysql_query("SET  CHARACTER  SET  'gbk'",  $mysql_conn);
这种情况下mysql_real_escape_string  是基于  latin1工作的,是不安全的。[client]
default-character-set=gbk
+
mysql_query("SET  CHARACTER  SET  'gbk'",  $mysql_conn);
这种情况下mysql_real_escape_string  是基于  gbk工作的,是安全的。
但是文中作者测试了,仍然是有漏洞的。(存疑)

看了下Mysql 服务器的设置,的确有client这个分组,不过没有加上上面提到的字符集设置:

位置:
/home/work/.jumbo/etc/mysql/my.cfg里面关于client的内容:
# The following options will be passed to all MySQL clients
[client]
#password       = your_password
port            = 8306
socket          = /home/work/.jumbo/var/run/mysqld/mysqld.sock

可能是需要加上 default-character-set=gbk 这样的设置吧。不过仍然不是很规范,不推荐。

文章作者还提到,可以用iconv来转换,不过更近粗暴,转不成功后面的就会截断,不太好。另外iconv之后,还需要再加上addslashes函数。

$this->sName=iconv('gbk//IGNORE', 'utf-8', $this->sName);              

下面就讨论两个推荐的方式:mysqli 和 PDO,他们的初始方法分别如下所示:

// PDO
$pdo = new PDO("mysql:host=localhost;dbname=database", 'username', 'password');  // mysqli, procedural way
$mysqli = mysqli_connect('localhost','username','password','database');  // mysqli, object oriented way
$mysqli = new mysqli('localhost','username','password','database');  

另外,他们其实也都是有转码的函数的,不过更推荐的是更好的PreparedStatement方式:

推荐采用prepared statements的方式绑定查询来代替PDO::quote() 和 mysqli_real_escape_string().

看mysqli, PDO是否安装,可以通过php_info()打印出来的信息来看:

http://localhost:8080/index.php
调用了php_info()API Extensions    mysqli,pdo_mysql,mysqlmysqliMysqlI Support    enabled
Client API library version    mysqlnd 5.0.11-dev - 20120503 - $Id: 15d5c781cfcad91193dceae1d2cdd127674ddb3e $
Active Persistent Links    0
Inactive Persistent Links    0
Active Links    0PDO
PDO support    enabled
PDO drivers    mysql, sqlite看起来都安装了。

另起一篇,来看mysqli 和 PDO等的操作和对sql注入的处理吧。

转载于:https://www.cnblogs.com/charlesblc/p/5987951.html

SQL注入实验,PHP连接数据库,Mysql查看binlog,PreparedStatement,mysqli, PDO相关推荐

  1. 搭建sql注入实验环境(基于windows)

    搭建服务器环境 1.下载xampp包 地址:http://www.apachefriends.org/zh_cn/xampp.html 很多人觉得安装服务器是件不容易的事,特别是要想添加MySql, ...

  2. SEED实验系列:Collabtive系统SQL注入实验

    本课程原文链接为:https://www.shiyanlou.com/courses/291,实验楼已经为此课程的实践提供了在线实验环境,想要尝试体验的,可以直接前往实验楼进行实践操作. 你能够喜欢我 ...

  3. 合天——SQL注入实验一

    实例一 通过网址:10.1.1.11:81  进入web渗透测试实验打开 在后面加'%20and%20'1'%20=%20'1(%20是空格的编码)          可以看出左右两边不一样,说明存在 ...

  4. mysql查看binlog日志内容

    2019独角兽企业重金招聘Python工程师标准>>> (一) binlog介绍 binlog,即二进制日志,它记录了数据库上的所有改变,并以二进制的形式保存在磁盘中: 它可以用来查 ...

  5. SQL注入之联合查询(MySQL)

    SQL注入之联合查询 0x00 前期准备 0x01 联合查询前提 0x02 注入步骤 0x03个人小结 一.Mysql注释 二.Mysql系统函数 三.其他 0x00 前期准备 环境搭配:Apache ...

  6. SQL注入【二】——MYSQL注入的基本流程

    ** 在对MYSQL注入的基本流程讲解前先来科普一下MySQL 5.0以上和MySQL 5.0以下版本的区别 ** MySQL 5.0以上版本存在一个存储着数据库信息的信息数据库--INFORMATI ...

  7. 1+X 网络安全运营平台与管理 sql注入实验报告

    目录 项目化考核 1+X 证书(网络安全运营平台管理) 实验目的: 实验设备 (环境) 实验要求: 实验原理: 实验步骤: 实验总结: 加油各位( •̀ ω •́ )y 期待与君再相逢 项目化考核 1 ...

  8. mysql 手工sql注入_【sql注入专题02】Mysql手工注入流程

    0x00 SQL注入的语句介绍 SQL注入的本质 sql注入的本质就是查询某个数据库下的某个表中的某些字段的内容,比如我们平时在数据库查询一条数据时操作. mysql> use security ...

  9. 合天——SQL注入实验二

    实例一: 将单引号放在%23(#)后转义掉后面的内容.发现存在注入点. 通过order by 数字判断表有几个字段,在数字为5时,仍能出现信息,但当 变成6时,变成空,说明有5个字段 通过union联 ...

最新文章

  1. jquery mobie导致超链接不可用
  2. Hadoop “Unable to load native-hadoop library for y
  3. python的pip安装-pip安装python库的方法总结
  4. MVC中HtmlHelper用法大全
  5. [ASP.NET笔记] 5.验证控件
  6. python 三引号_Python 基础(一):入门必备知识
  7. 简单计算器 (关于栈的一种应用)
  8. Android安全笔记-进程间通信基本概念(intent、bundle、Parcelable、parcel)
  9. Linux备份策略(第二版)
  10. javascript——forEach跳出循环
  11. 营业执照15位注册号码含义和查询规则
  12. 带你近距离了解小米这家公司
  13. python 中文乱码
  14. matlabGUI入门
  15. Py 实现导线测量的内业计算
  16. 武昌职业学院与湖北美和易思教育科技有限公司校企签约揭牌仪式隆重举行
  17. linux fat32分区容量,FAT32格式对硬盘分区容量有限制的吗?
  18. smtp协议支持身份认证与不认证两种状态。
  19. GHOST XP SP2 遐想网络 专用加强版
  20. 柯桥西班牙语培训,西班牙语关于篮球的词汇

热门文章

  1. eos操作系统_【EOS币资讯】EOS币与以太坊有什么不同?
  2. etcd nginx 容器_Etcd+confd实现动态修改nginx文件
  3. python的设计哲学_Python的设计哲学
  4. 如何维持手机电池寿命_手机如何正确充电,电池寿命长。
  5. 用windows开发ios app_开发一个APP至少需要多少人|安卓|ios|产品经理
  6. R语言ggplot2画图3
  7. 常见花材的固定的方法有哪些_什么是zeta电位?常见zeta电位分析方法有哪些?...
  8. mysql教程日志_MySQL日志
  9. plsql能连mysql吗_80后中年夫妻做冬季热饮,一天卖300杯,女顾客:能连杯子端走吗...
  10. 系统学习机器学习之增强学习(一)--模型基础