字符串破绽剖析:字符串衔接与花样字符串 | 申博官网
登录
  • 欢迎进入申博官网!
  • 如果您觉得申博官网对你有帮助,那么赶紧使用Ctrl+D 收藏申博官网并分享出去吧
  • 这里是申博官方网!
  • 申博官网是菲律宾sunbet官网品牌平台!
  • 申博开户专业品牌平台!

字符串破绽剖析:字符串衔接与花样字符串

申博_新闻事件 申博 116次浏览 已收录 0个评论

假如我们挑选JavaScript作为编程的首选言语,那末我们没必要忧郁字符串衔接题目。然则我们常常碰到的一个重复涌现的题目是必须守候JavaScriptnpm包管理器装置完成一切必须的依靠项。

字符串破绽剖析:字符串衔接与花样字符串

在这篇文章中,我们研讨了为何字符串衔接是一个庞杂的题目,为何不能在没有转换的情何况在初级编程言语中衔接差别范例的两个值,以及字符串衔接怎样致使破绽。 我们还将剖析假如花样字符串包含某些范例数据的占位符,假如它们遭到进击者掌握,则会致使严重题目。以后,我们将挑选一种简朴的要领来处置惩罚他们。

起首,让我们看一下JavaScript字符串衔接,它在衔接差别范例的数据时会碰到差别的状况。 这里有些例子:

1 + 1 === 2                               // 很显著

'1' + 1 === '11'                            // 很直观

1 + true === 2                          // 对吗?

1 + {} === '1[object Object]'    // 什么时候须要这类状况?
true + undefined === NaN   // 这显著不是一个数字,但它是什么?

typeof NaN === 'number'    // 好 那接下来呢?

毕竟,JavaScript并非那末圆满。 而且,虽然在JavaScript中衔接两个差别范例的值很轻易,但它不一定会发作预期且有效的效果。 一些殽杂是因为:在JavaScript中,衔接运算符与增加运算符雷同,因而它必须决定是衔接值照样增加它们。

让我们来看看另一种不是异常严谨的言语,比方PHP。 它怎样处置惩罚串连? 好吧,在PHP中你没有plus运算符。 而是运用如图所示的点:

"The number one: " . 1          // 如其事情

"10" . 1 === "101"                      // 这只是在字符串10中增加1

"10" . 1.0 + "1.0"                       // 猜想下这个语句是用来做什么的?

显著,这是(float)102。我们将字符串“10”float 1.0衔接起来,这天生字符串“101”。 然后将字符串“1.0”增加到字符串“101”中,末了获得(浮点)102。 这异常轻易明白。 我们可以将两个字符串一同增加,末了获得float范例的值。

字符串衔接的基础知识

我们可以议论PHP的输出体系存在的题目以及它怎样致使现实生活中的破绽(拜见PHP范例破绽的细致申明)。 然则我们不能不认可JavaScript和PHP中的字符串衔接异常轻易。

假如运用像C如许的初级言语如许做会发作什么吗? 假如我们试图在字符串中增加一个浮点数,C言语并不会预期实行。

字符串破绽剖析:字符串衔接与花样字符串

在此示例中,C不晓得我们要完成的目标。 C以至不许可你将两个字符串增加到一同来衔接它们,更不用说差别数据范例的字符串了。 这里,字符串只是一个字符序列,末端有一个NULL字节。 平常,有一个指向字符串第一个字节的指针。 毛病音讯中的char *援用该指针。

JavaScript中,我们须要忧郁NULL字节或指针。 字符串在JavaScript中也是不可变的,因而我们不能只变动个中的数据。 相反,假如须要变动数据,则须要建立一个新字符串,并坚持旧字符串稳定。

字符串破绽剖析:字符串衔接与花样字符串

在这个例子中,我们试图将“String”一词改成“Strong”,但它不起作用。 x变量不会转变。 虽然这个功用作用有限,然则它实际上是一个异常好的功用。它可以提醒我们曾用过JavaScript中的对象。

衔接差别的数据范例很难

double是指所谓的“双精度浮点数”。关于那些不晓得的人,浮点数作为一个神奇的字节序列存储在内存中,但好像如许没有意义。如许做的原因是它们平常以IEEE 754中定义的花样存储在科学记数法中(拜见分步教程二进制分数和浮点数)。

C怎样将一个字符串到场一个新鲜的字节组合,即浮点数,在内存中一同保存它们的初始寄义?

答案是:不能。假如将浮点数附加到字符串的末端并响应地挪动NULL字节,则只会将这些字节视为文本,并尝试打印没法显现的渣滓或字符。这在JavaScript中是不可设想的;这是C编程中的常见题目。

因而,为了将浮点数增加到字符串,C须要起首将其IEEE 754花样转换为人类可读的字符串示意。为此,C库供应* printf系列函数。

平安的C言语

假如要将任何范例的数据放入字符串中,或将字符串衔接在一同,则只需运用printf即可。 我们须要通报一个花样字符串,个中包含指定数据范例的占位符等。 我们来看一个例子。

字符串破绽剖析:字符串衔接与花样字符串

假如我们编译此代码并运转它,它将只打印'This is a string。'。 能够已猜到,%s是字符串的占位符,但也存在其他数据范例的占位符,比方整数,浮点数以至单个字符。 您还可以以十六进制示意情势打印数据。 然则,有一个题目。 假如你毛病地运用它,它是完全不平安的。

应当怎样在C中衔接两个字符串?

许多人都邑征询Stackoverflow,因为它是一个关于常见题目标直接了当的回覆网站。

最高投票的答案运用strcat,一个基础不搜检任何大小的函数,这在C中老是一件坏事,因为假如你不小心它会致使缓冲区溢出。 题目下方的批评发起运用strlcat,人们以为它是一个更平安的strcat版本。 但厥后其他人发起运用strcat_s。 这好像是另一个更平安的strcat版本。

Stackoverflow中的其他人喜好运用snprintf,依据批评,这显著是“大不了”,因为显著_snprintf是不平安的。 然则,另一个帖子叫做住手运用strncpy了! 提到它可以运用。 假如您还不熟习Stackoverflow或C,那末这个线程圆满地申清楚明了二者的题目。

花样字符串破绽

我已提到假如运用不准确,` printf`函数会很风险。 然则,一个功用,其唯一目标是花样化输出,怎样致使能够致使恣意代码实行的破绽?

细致答案超越了本博文的局限,但这里是一个概述。 局部变量和函数参数存储在内存中的特别位置 – 客栈上。 关于x86 Linux二进制文件,这平常意味着一旦挪用函数,它将直接从客栈中猎取函数参数。 那末假如你有一个没有参数的printf挪用会发作什么呢,以下所示?

printf("%x%x%x%x%x");

它将简朴地抓取客栈中的数据并以十六进制花样打印。 这能够包含客栈和返回地点,客栈cookie(旨在防备缓冲区溢出应用的平安机制),变量和函数参数的内容,以及对进击者异常有效的一切其他内容。 因而,假如printf中的花样字符串是用户可掌握的,那就异常风险。 别的,假如运用充足的花样申明符,终究能够会获得一个指向用户可控输入的客栈指针,就像花样字符串自身一样。

然后,我们可以向内存中的任何位置供应地点,并运用%s读取数据。 别的,假如启用了%n,则可以在内存中的任何位置写入恣意数据,即已打印的字节数。 这听起来不是许多,但它能够许可进击者掩盖返回地点,并将代码流重定向。

Web应用顺序是不是包含花样字符串破绽?

花样字符串不仅在C中可用。以下是其他言语,我们还可以在个中找到它们用于Web应用顺序。

PHP

假如熟习PHP,那末能够晓得它还具有printf函数。 然则,PHP将搜检是不是有比函数参数更多的花样申明符(除了少数破例)。 假如在C中以不平安的体式格局运用printf,平常只会收到编译器正告.PHP会简朴地中断剧本的实行。

Ruby

Ruby类似于PHP。 当尝试运用Ruby的printf函数时,它会将参数的数目与其对应的花样申明符举行比较。 假如申明符多于参数,则实即将住手。

Perl

Perl是差别的。 Perl很愿意接收通报给它的花样申明符,但效果不会很有效。 然则,我们可以运用%n申明符掩盖已打印的字符数的变量。 这是一个代码示例:

2018铁人三项赛总决赛PWN

0x01 littlenote 保护全开的堆利用程序,有add、show、delete功能,delete模块有UAF漏洞。 add: 只能申请size为0x71或0x31的堆块 show: 显示堆块内容 delete: 存在UAF 攻击思路: 1.利用UAF,删除堆块,再读取数据,泄漏heap地址 2.再次利用UAF漏洞,将fd指针篡改到某堆块中间,就能继续输入数据改写下一个相邻chunk的size,把size改大,然后free,就能使其进入unsortedbin,从而泄漏libc地址 3.第三次利用UAF做double free,向malloc_hook填入one_gadget地址 exp: from pwn import *
env=os.environ
env[‘LD_PRELOAD’]=’./littlenote.

$str = "This is a string";
printf("AAAAAAAAAAAAAAAAAAAAAAAA%n\n",$str);
print($str); # this is 24 now, as there were 24 'A's printed

另有一个不那末显著的题目。 Perl中大批的比较效果是出人意料的。 它与PHP类似,我们须要在比较时运用“eq”标识符而不是==标记,以便举行或多或少的严厉比较。 因而,而不是1 == 1你会写1 eq 0. ==显著是大多数人的体式格局,比在每次比较中键入“eq”更轻易。 假如我们检察Perl表,我们可以看到整数0与任何字符串比拟,返回一个婚配项。 如今看下面的代码:

$databasePassword = "secret pass"; #unknown to attacker
$password = "A password"; #user supplied string
# ... some more code ...
printf("%n <somehow user controlled format string>", $password); #writes integer 0 into $password variable
# ... some more code ...
if($databasePassword == $password) { # this will match!
        print("Password matches");
} else {
        print("Password does not match");
}

此代码将打印“暗码婚配”。 这个题目是你以至不须要一个整数来经由过程搜检。 纵然字符串“0”也会起作用。 (PHP有类似的题目,但它最少须要一个整数,你不能作为GET或POST参数通报。)

假如它许可变动能够不是用户可掌握的输入值,则此要领依然有效。 这能够会致使代码中的潜伏可应用行动。 假如您想相识有关Perl中其他不平安行动的更多信息,请参阅Perl Jam 2。

Lua

是不是晓得人们在Lua中编写Web应用顺序? 以至另有一个用于特定目标的Lua Apache模块。 比方,我在路由器中看到了基于Lua的Web应用顺序。 这多是因为Lua的体积异常小,因而适合在磁盘空间慌张的路由器中运用。 Lua也可用作“魔兽天下”界面自定义的剧本言语。 好像下一个逻辑步骤是运用它来编写Web应用顺序。

它另有一个类似于printfstring.format函数。 它仅支撑一组有限的花样申明符,%n不是个中之一。 别的,它搜检参数的数目是不是与花样申明符的数目相婚配。 假如不婚配,则会发作毛病。

Java

Java中有一个System.out.printf函数。 与大多数其他言语一样,它搜检参数的数目是不是与花样申明符的数目相婚配。 一样,有一个%n申明符,但它没有做到你所希冀的。 出于某种原因,它将为正在运转的平台打印响应的行分隔符。 假如你是来自C,这会使人困惑,但你不能希望与Java的花样字符串兼容,纵然两个函数具有雷同的称号。

Python

Python是一个异常风趣的案例,因为它有两种差别的经常使用字符串花样化要领。 PyFormat网站致力于Python中的字符串花样化,以为Python本身的文档“过于理论化和手艺化”。

起首,运用我们已晓得的花样申明符的旧要领。以下所示:

print("This is %s." % "a string")

如我们所见,这运用花样字符串后跟百分号。 参数写在标记背面。 假如有多个参数,则须要运用元组。 这里%n不受支撑。 别的,将参数的数目与花样申明符的数目举行比较,假如python不婚配则抛出毛病。

然则另有一种新的字符串花样化要领。 我们可以经由过程在字符串上挪用内置的.format要领来运用它。

print("{} is {} years old".format("Alice", 42))

它以至许可我们从花样字符串中接见通报的对象的属性。

print("{person[name]} is {person[age]} years old".format(person={"name":"Alice","age":42}))

正如我们所看到的,他们两个都打印出“爱丽丝已42岁了”。 它们并不真正须要花样申明符,因为Python会在大多数时候自动将它们转换为准确的字符串示意情势。 然则,第二种要领能够会致使信息泄漏破绽。

一篇名为Be Careful with Python的新式字符串花样的博客文章很好地形貌了这类要领。 基础上,依据通报的数据,进击者可以读取敏感信息,远远超越我们的企图。 我们来看一个例子吧。

API_KEY = "1a2b3c4d5e6f"

class Person:
   def __init__(self):
       """This is the Person class"""
           self.name = "Alice"
           self.age = "42"

print("{person.name} is {person.age} years old".format(person=Person()))

虽然这一最先好像没有破绽,但假如进击者可以在此处掌握花样字符串,则可以轻松打印API_KEY变量。但它是怎样事情的?

起首,晓得person对象包含的不仅仅是我们设置的称号和岁数属性,这一点很主要。它还具有可直接接见的__init__功用。 Python实例化Person类时会自动挪用它。它依然是花样字符串中可用的用户定义函数。然则我们能在这做什么呢?我们没法从花样字符串中挪用函数。然则,我们可以接见属性。

在Python中,函数具有一些平常不须要运用的特定属性。比方__name__示意函数的称号。然则,这里有另一个有效的属性,叫做__globals__。文档形貌以下:

‘对包含函数全局变量的字典的援用 – 定义函数的模块的全局定名空间。

这很风趣,因为依据定义,API_KEY变量位于__init__函数的全局定名空间中。这给我们留下了以下花样字符串。

"API_KEY: {person.__init__.__globals__[API_KEY]}".format(person=Person())

以后输出的效果为:

API_KEY: 1a2b3c4d5e6f

另有其他如许的键,比方__doc__,它打印函数的文档字符串(能够发作一些有效的信息)。 另有其他文件名。 完全列表在Python文档内容中供应。

我对Python不太熟习,不晓得博客文章中供应的修复是不是适宜,但它类似于我发起防止运用的黑名单要领。

假如须要向用户供应花样字符串,则能够须要运用旧花样。 然则,平常来说,我发起尝试防止花样字符串中的用户输入。

JavaScript

平常,JavaScript不须要任何花样字符串。 你应当运用内置的替代功用本身完成它们,这完全不使人懊丧和过于庞杂。 有外部库模拟它们,但因为JavaScript库的总数很大,因而搜检每一个库中的不测行动是一项不能够完成的使命。

尽管如此,JavaScript为我们供应了一种花样化输出的要领,无需替代和衔接。 我们可以运用所谓的模板笔墨。 望文生义,你不能在运转时动态建立如许的字符串,除非你运用像eval如许的函数,但我强烈发起不要如许做。

这是一个例子:

const name = "Alice";
const age = 42;
console.log(`${name} is ${age} years old`)

我们运用反引号,在美圆标记背面的花括号之间写入变量名:$ {var}

因为没有简朴的要领让用户可以定义他们本身的模板笔墨而不许可他们实行恣意JavaScript代码,我想指出模板笔墨在绕过黑名单过滤器时是JavaScript中最好的东西。 为何? 如许的过滤器可以删除一切"(" and ")"字符,因而很难实行JavaScript代码。 比方,依然可以运用onerror事宜处置惩罚顺序和throw关键字,但模板笔墨更轻易,详细取决于要实行的函数。 我们只需在函数称号背面编写模板笔墨即可实行:

alert`some popup message`

这就是为何黑名单永久不是一个好主意。

花样化字符串和XSS

XSS破绽和花样字符串还存在另一个要挟。假如运用花样字符串函数天生的输出轻易遭到XSS的进击,则应尽快修复此题目。然则大多数用户都有一个平安网,除了那些在iOS以外运用Firefox的用户。大多数版本的谷歌浏览器,Safari,IE和Edge都有一个内置的XSS过滤器,按期更新。

题目在于这些过滤器的事情体式格局。它们比较用户输入和服务器发还的天生输出。假如它们充足类似而且包含风险的标签或参数,则不会显现页面或删除风险输入。这些过滤器跟着时候的推移变得更好,但它们依然不是十拿九稳的。因而,假如在服务器端处置惩罚输入并举行变动,则挑选器将不会检测到该破绽。鄙人面的示例中,Chrome现在不会检测到XSS破绽,并会实行JavaScript代码。

//server side code
printf(user_input, "Alice", 42);
        URL:
https://example.com/?user_input=<iframe src="javascript:alert(1)||%s">

输出将是<iframe src = "javascript:alert(1)||Alice">,并将涌现一个正告弹出窗口。

防止运用包含用户输入的花样字符串

花样字符串破绽的影响在很大程度上取决于我们运用的言语。 平常的履历法则是防止运用包含用户输入的花样字符串。 相反,我们应当一直将该输入作为参数通报给花样化函数,这是防止与花样字符串相干的破绽的通用要领。 固然,我们应当一直依据将要运用的上下文清算用户供应的输入。

我们如今应当对Web应用顺序和其他地方的花样字符串应用有一个基础概述。 我发起测试Netsparker Web应用顺序平安扫描顺序。 它与最盛行的延续集成处置惩罚方案和题目跟踪体系无缝集成,让我们有更多时候浏览Web应用顺序破绽,削减对它们的担心。


申博|网络安全巴士站声明:该文看法仅代表作者自己,与本平台无关。版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明字符串破绽剖析:字符串衔接与花样字符串
喜欢 (0)
[]
分享 (0)
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址