php代码审计之sql注入 审计有几种方法,通读,指定函数,或者功能点 通读也就是每一个php都阅读一下,发现每一个页面实现的功能(对于我刚开始接触php来说,不可能) 功能点 自己使用源码,phpstudy搭建环境,使用AWVA,appscan,nessus等工具进行扫描,在输入框,文件上传等功能点进行测试,还可以根据回显,例如:不允许此类型文件上传,使用seay审计系统查询,审计相关方法 此篇为sql注入 sql注入产生的原因:用户输入恶意构造的语句,服务器后端未进行足够的校验,恶意语句直接添加sql语句中执行 从原理看 服务端需要做的事情:获取用户输入,校验,执行,返回。只有了解对应的函数才能够完成对php的解读 获取用户输入值的相关函数 $_GET $_POST $_REQUEST (可以获取以POST方法和GET方法提交的数据)
S
E
R
V
E
R
包
含
了
诸
如
头
信
息
(
h
e
a
d
e
r
)
、
路
径
(
p
a
t
h
)
、
以
及
脚
本
位
置
(
s
c
r
i
p
t
l
o
c
a
t
i
o
n
s
)
等
等
信
息
的
数
组
以
下
均
已
_SERVER 包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组 以下均已
S?ERVER包含了诸如头信息(header)、路径(path)、以及脚本位置(scriptlocations)等等信息的数组以下均已_GET为例,
R
E
Q
U
E
S
T
可
以
使
用
_REQUEST可以使用
R?EQUEST可以使用_GET,$_POST需要使用hackbar勾选下方的post data即可 原理相同 <?php $conn = mysql_connect('localhost', 'root', 'root') or die('bad!'); mysql_query("SET NAMES binary'"); mysql_select_db('test', $conn) OR emMsg("数据库连接失败"); $id = isset($_GET['id']) ? $_GET['id'] : 1; $sql = "SELECT * FROM news WHERE id={$id}"; $result = mysql_query($sql, $conn) or die(mysql_error()); ?>
以此段为例 isset($_GET[‘id’]) ?
G
E
T
[
′
i
d
′
]
:
1
这
条
语
句
为
三
目
运
算
符
,
i
s
s
e
t
验
证
是
否
存
在
,
整
体
语
句
内
容
为
,
如
果
通
过
g
e
t
方
法
获
取
到
i
d
的
内
容
就
将
i
d
的
值
赋
给
_GET['id'] : 1这条语句为三目运算符,isset验证是否存在,整体语句内容为,如果通过get方法获取到id的内容就将id的值赋给
G?ET[′id′]:1这条语句为三目运算符,isset验证是否存在,整体语句内容为,如果通过get方法获取到id的内容就将id的值赋给id ,mysql_select_d()使用$conn中的数据库账号密码连接本地数据库,mysql_query()执行对应的查询语句,在这段语句中通过get获取的参数,服务端没有进行校验,连单引号双引号等都没有,存在数字类型注入 <?php $conn = mysql_connect('localhost', 'root', 'root') or die('bad!'); mysql_query("SET NAMES binary'"); mysql_select_db('test', $conn) OR emMsg("数据库连接失败"); $tmp_id = isset($_GET['id']) ? $_GET['id'] : 1; $title = isset($_GET['title']) ? $_GET['title'] : 'news title'; $id = str_replace("'",'',$tmp_id); $sql = "SELECT * FROM news WHERE id='{$id}' and title='{$title}'"; echo $sql.'
'; ?>
以这段代码为例,id=’{KaTeX parse error: Expected 'EOF', got '}' at position 3: id}?'和id='id’没有任何区别,虽然采用了str_replace()将单引号替换为空,但并没有对title进行过滤,title参数存在字符类型注入 <?php $conn = mysql_connect('localhost', 'root', 'root') or die('bad!'); mysql_query("SET NAMES binary'"); mysql_select_db('test', $conn) OR emMsg("数据库连接失败"); $tmp_id = isset($_GET['id']) ? $_GET['id'] : 1; $id = addslashes($id); $id = stripslashes($tmp_id); $sql = "SELECT * FROM news WHERE id='{$id}'"; echo $sql.'
'; $result = mysql_query($sql, $conn) or die(mysql_error()); ?>
在这段代码中,addslashes() 函数,在每个双引号(")前添加反斜杠,stripslashes():删除反斜杠, 但是KaTeX parse error: Expected '}', got 'EOF' at end of input: …ews WHERE id='{id}’";用的是单引号,和双引号没关系,又因为mysql_error()返回报错信息,所以存在报错注入 <?php $conn = mysql_connect('localhost', 'root', 'root') or die('bad!'); mysql_query("SET NAMES binary'"); mysql_select_db('test', $conn) OR emMsg("数据库连接失败"); $id = isset($_GET['id']) ? $_GET['id']: 1; $sql = "SELECT * FROM news WHERE id='".$id."'"; $result = mysql_query($sql, $conn) or die(mysql_error()); $sql2 = "SELECT * FROM news WHERE id=".$id; $result2 = mysql_query($sql2, $conn) or die(mysql_error()); ?>
以此段代码为例,你需要注意到的是id=’".
i
d
.
"
′
其
中
点
的
作
用
表
示
连
接
,
个
人
感
觉
实
际
上
输
出
与
i
d
=
′
id."'其中点的作用表示连接,个人感觉实际上输出与id='
id."′其中点的作用表示连接,个人感觉实际上输出与id=′id’没啥区别,而第二个id直接拼接 属于数字类型注入 关于$_SERVER注入 <?php function get_ip(){ if(getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"),"unknown")){ $ip=getenv("HTTP_CLIENT_IP"); }else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv("HTTP_X_FORWARDED_FOR"),"unknown")){ $ip=getenv("HTTP_X_FORWARDED_FOR"); }else if (getenv("REMOTE_ADDR") && strcasecmp(getenv("REMOTE_ADDR"),"unknown")){ $ip=getenv("REMOTE_ADDR"); }else if (isset($_SERVER['REMOTE_ADDR']) && $_SERVER['REMOTE_ADDR'] && strcasecmp($_SERVER['REMOTE_ADDR'],"unknown")){ $ip=$_SERVER['REMOTE_ADDR']; }else{ $ip="unknown" ; } return $ip; } $ip=get_ip(); $conn = mysql_connect('localhost', 'root', 'root') or die('bad!'); mysql_query("SET NAMES binary'"); mysql_select_db('test', $conn) OR emMsg("数据库连接失败"); $id = get_ip(); $sql = "SELECT * FROM news WHERE id='".$ip."'";; $result = mysql_query($sql, $conn) or die(mysql_error()); ?>
在这段函数中,getenv()取得系统的环境变量 &&并且的意思,strcasecmp()忽略大小写进行比较,次函数中为unknown即kong 简而言之,如果环境变量中存在那种变量,并且不为空,就将值赋给$ip 带入到查询语句中进行查询
以上代码借用https://www.cnblogs.com/shellr00t/p/5701184.html但原文章代码中存在require_once(‘common.php’);也就是此文件包含common.php common.php中的规则 本php需要遵守 但我并未见到common.php 所以做了些许修改, 除了查询语句中可能出现注入,在insert 和update中也有可能产生,太晚了,不写了,明天再写
|