php sprintf函数漏洞

0x01 了解sprintf()函数

1,sprintf(),函数是php中的函数

2,作用是将格式化字符串写入变量中

3,函数形式为sprintf(format,arg1,arg2,arg++)

参数说明:

参数 描述
format

必需。规定字符串以及如何格式化其中的变量。

可能的格式值:

%% - 返回一个百分号 %

%b - 二进制数

%c - ASCII 值对应的字符

%d - 包含正负号的十进制数(负数、0、正数)

%e - 使用小写的科学计数法(例如 1.2e+2)

%E - 使用大写的科学计数法(例如 1.2E+2)

%u - 不包含正负号的十进制数(大于等于 0)

%f - 浮点数(本地设置)

%F - 浮点数(非本地设置)

%g - 较短的 %e 和 %f

%G - 较短的 %E 和 %f

%o - 八进制数

%s - 字符串

%x - 十六进制数(小写字母)

%X - 十六进制数(大写字母)

附加的格式值。必需放置在 % 和字母之间(例如 %.2f):

+ (在数字前面加上 + 或 - 来定义数字的正负性。默认情况下,只有负数才做标记,正数不做标记)

' (规定使用什么作为填充,默认是空格。它必须与宽度指定器一起使用。例如:%'x20s(使用 "x" 作为填充))

- (左调整变量值)

[0-9] (规定变量值的最小宽度)

.[0-9] (规定小数位数或最大字符串长度)

注释:如果使用多个上述的格式值,它们必须按照以上顺序使用。

arg1 必需。规定插到 format 字符串中第一个 % 符号处的参数。
arg2 可选。规定插到 format 字符串中第二个 % 符号处的参数。
arg++ 可选。规定插到 format 字符串中第三、四等 % 符号处的参数。

**若%符号多于arg参数,则需要占位符,占位符格式为“%number\$” 其中number表示该项与第几个arg匹配,如若与第一个匹配     则占位符为“%1\$”

以下是一些例子帮助更好的理解sprintf()函数:

#1.不带占位符的:

<?php

$num1=9999;
$char=96; echo sprintf("%%b=%b",$num1)."</br>";
echo sprintf("%%c=%c",$char)."</br>";
echo sprintf("%%s=%s",$num1)."</br>";
echo sprintf("%%x=%x",$num1)."</br>"; ?>

输出结果:

%b=10011100001111

%c=`

%s=9999

%x=270f

#2.带有占位符:

<?php

$num=123;
sprintf("the number is %1\$d",&num); ?>

结果:

the number is 123

0x02 sprintf()的注入原理

sprintf()的底层实现方法

switch (format[inpos]) {
case 's':
{
zend_string * t;
zend_string * str = zval_get_tmp_string(tmp, &t);
php_sprintf_appendstring( & result, &outpos, ZSTR_VAL(str), width, precision, padding, alignment, ZSTR_LEN(str), 0, expprec, 0);
zend_tmp_string_release(t);
break;
}
case 'd':
php_sprintf_appendint( & result, &outpos, zval_get_long(tmp), width, padding, alignment, always_sign);
break;
case 'u':
php_sprintf_appenduint( & result, &outpos, zval_get_long(tmp), width, padding, alignment);
break;
case 'g':
case 'G':
case 'e':
case 'E':
case 'f':
case 'F':
php_sprintf_appenddouble( & result, &outpos, zval_get_double(tmp), width, padding, alignment, precision, adjusting, format[inpos], always_sign);
break;
case 'c':
php_sprintf_appendchar( & result, &outpos, (char) zval_get_long(tmp));
break;
case 'o':
php_sprintf_append2n( & result, &outpos, zval_get_long(tmp), width, padding, alignment, 3, hexchars, expprec);
break;
case 'x':
php_sprintf_append2n( & result, &outpos, zval_get_long(tmp), width, padding, alignment, 4, hexchars, expprec);
break;
case 'X':
php_sprintf_append2n( & result, &outpos, zval_get_long(tmp), width, padding, alignment, 4, HEXCHARS, expprec);
break;
case 'b':
php_sprintf_append2n( & result, &outpos, zval_get_long(tmp), width, padding, alignment, 1, hexchars, expprec);
break;
case '%':
php_sprintf_appendchar( & result, &outpos, '%');
break;
default:
break;
}

通过底层实现代码可以发现,sprintf()方法就是对15种类型做了匹配,15种类型以外的就直接break了没有做任何处理,所以就会导致一个问题:

如果我们输入"%\"或者"%1$\",他会把反斜杠当做格式化字符的类型,然而找不到匹配的项那么"%\","%1$\"就因为没有经过任何处理而被替换为空。

因此sprintf注入的原理就是

我们用一个15种类型之外的"\" 来代替格式字符类型让函数替换为空,则“%1$\'”后面的单引号就能闭合前面的单引号,以下是一些例子帮助我们更好的理解

#1.不带占位符的

<?php

$sql="select * from user where username='%\' and 1=1 #';";
$user='admin';
echo sprintf($sql,$user); ?>

运行结果:

select * from user where username='' and 1=1 #';

注意:username=''这里是两个单引号不是双引号

#2.带有占位符:

<?php
//addslashes()函数:在预定义前面加反斜杠,预定义符有单引号('),双引号("),反斜杠(\),NULL
$input = addslashes ("%1$' and 1=1#" );
$b = sprintf ("AND b='%s'", $input );
$sql = sprintf ("SELECT * FROM t WHERE a='%s' $b ", 'admin' );
//对$input与$b进行了拼接
//$sql = sprintf ("SELECT * FROM t WHERE a='%s' AND b='%1$\' and 1=1#' ", 'admin' );
//很明显,这个句子里面的\是由addsashes为了转义单引号而加上的,使用%s与%1$\类匹配admin,那么admin只会出现在%s里,%1$\为空
echo $sql ;
?>

运行结果:

SELECT * FROM t WHERE a='admin' AND b='' and 1=1#'

#3.%c的利用

<?php

$input1='%1$c) or 1=1 /*';
$input2=39;
$sql="select * from foo where bar in('$input1') and baz=%s";
$sql=sprintf($sql,$input2);
echo $sql; ?>

运行结果:

select * from foo where bar in('') or 1=1 /*') and baz=39

0x04总结

漏洞利用条件

1、sql语句进行了字符拼接

2、拼接语句和原sql语句都用了vsprintf/sprintf 函数来格式化字符串

相关题目练习:https://blog.csdn.net/WQ_BCJ/article/details/85215662

解析php sprintf函数漏洞的更多相关文章

  1. PHP 函数漏洞总结

    1.MD5 compare漏洞 PHP在处理哈希字符串时,会利用"!="或"=="来对哈希值进行比较,它把每一个以"0E"开头的哈希值都解释 ...

  2. sprintf函数 %6.2f

    %6.2f6表示数据表示至少6位,后面的.2表示小数点后保留两位 比如2342.123415用这个表示的话,结果就是2342.12如果不足六位就会在前面补空格超过六位的话正常显示 代码例子:int m ...

  3. CVE-2012-0003 Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞 分析

    [CNNVD]Microsoft Windows Media Player ‘winmm.dll’ MIDI文件解析远程代码执行漏洞(CNNVD-201201-110)    Microsoft Wi ...

  4. php sprintf 函数的用法

    sprintf() 函数把格式化的字符串写入变量中. arg1.arg2.++ 参数将被插入到主字符串中的百分号(%)符号处.该函数是逐步执行的.在第一个 % 符号处,插入 arg1,在第二个 % 符 ...

  5. sprintf()函数的用法

    Visual C++ sprintf()函数用法 转:http://blog.csdn.net/masikkk/article/details/5634886 在将各种类型的数据构造成字符串时,spr ...

  6. sprintf函数

    sprintf函数用法举例 #include<stdio.h> int main() { //1.连接字符串 char a1[] = {'A', 'B', 'C', 'D', 'E', ' ...

  7. arduino上使用sprintf()函数输出float值出错

    如果尝试使用sprintf()函数在arduino上进行对float指转换为一个字符串的话,你会发现,it doesn't work.弄了很久,还以为是没学c++的原因.其实在arduino上,这个函 ...

  8. sprintf函数php的详细使用方法

    PHP sprintf() 函数 先说下为什么要写这个函数的前言,这个是我在微信二次开发的一个token验证文档也就是示例文档看到的一个函数,当时非常不理解,于是查了百度,但是很多结果都很笼统,结果也 ...

  9. [转]PHP echo, print, printf, sprintf函数的区别和使用

    1. echo函数: 输出函数,是命令,不能返回值.echo后面可以跟很多个参数,之间用分号隔开,如: echo $myvar1; echo 1,2,$myvar,"<b>bol ...

随机推荐

  1. let声明的全局变量不是window对象属性

    今天在控制台写删除数组第一个元素的代码时,发现了一个问题,以下是书中源码, let arr = [1,2,3,4,5] Array.prototype.reIndex = function (myAr ...

  2. 使用配置文件方式记录Python程序日志

    开发者可以通过三种方式配置日志记录: 调用配置方法的Python代码显式创建记录器.处理程序和格式化程序. 创建日志配置文件并使用fileConfig() 函数读取. 创建配置信息字典并将其传递给di ...

  3. 我画着图,FluentAPI 她自己就生成了

    在 Newbe.ObjectVistor 0.3 版本中我们非常兴奋的引入了一个紧张刺激的新特性:使用状态图来生成任意给定的 FluentAPI 设计. 开篇摘要 在非常多优秀的框架中都存在一部分 F ...

  4. 微信公众号Makrdown编辑器,语法你懂吗?

    感谢 WeChat Format 源码: https://github.com/lyricat/wechat-format! 其他工具推荐: 微信公众号编辑器 Makrdown: https://md ...

  5. 画echart图时,安卓手机正常,苹果手机上tooltip 在坐标轴下一层

    问题: 解决: 在tooltip 中添加如下代码: tooltip:{ position:function(point, params , dom, rect, size){ dom.style.tr ...

  6. 在 macOS 中使用 Podman

    原文链接:https://fuckcloudnative.io/posts/use-podman-in-macos/ Podman 是一个无守护程序与 Docker 命令兼容的下一代 Linux 容器 ...

  7. 【转】Java工程师知识图谱

    一.Java工程师知识图谱(思维导图版) 二.Java工程师知识图谱(文字链接版) 专业基石 数据结构 数组 链表 队列 栈 哈希表 堆 树 图 BitMap 算法思想 排序 查找 分支算法 动态规划 ...

  8. 使用Folx下载热门电影居然这么简单

    在闲暇的时候,很多人会选择观看电影.电视剧来打发时间.对于一些热门的资源,可以通过网页搜索的方式,找到很多与之相对应的种子资源. 但有时候,一些不那么热门的资源就要花费较多时间搜索.有了Folx bt ...

  9. Mac下载工具folx如何下载常用的软件

    最近,多档综艺节目都开展得如火如荼,比如<中国新说唱>.<这就是街舞>等深受年轻人喜欢的综艺节目.虽然手机端也可观看,但可以的话,当然是使用电脑屏幕观看节目比较过瘾. 接下来, ...

  10. redlock分布式锁真的安全吗

    此文是对http://zhangtielei.com/posts/blog-redlock-reasoning-part2.html文章的个人归纳,如有问题请联系删除 什么是redlock redlo ...