Python 隐式行连接会给你挖什么坑?

admin 2025年1月10日19:16:24评论1 views字数 2409阅读8分1秒阅读模式

Python 隐式行连接会给你挖什么坑?

Python 隐式行连接常被用于长行的分割,例如分割超长的字符串或者语句,而这个特性一不小心就会造成诡异的 bug。

两个例子 🌰

出题时间!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
data = ['1111111111',
'2222222222',
'3333333333',
'4444444444',
'5555555555',
'6666666666',
'7777777777',
'8888888888',
'9999999999'
'0000000000',
'aaaaaaaaaa',
'bbbbbbbbbb',
'cccccccccc',
'dddddddddd',
'eeeeeeeeee',
'ffffffffff',
'AAAAAAAAAA',
'BBBBBBBBBB',
'CCCCCCCCCC',
'DDDDDDDDDD',
'EEEEEEEEEE',
'FFFFFFFFFF']

print('0000000000' in data)
print('AAAAAAAAAA' in data)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
rules = {
'''
2019-11-01 09:55:32
todo: 新增关键字
'''

# git 泄露关键字
'/.git/config': ['[core]', '[remote]', '[branch]', '[repositoryformatversion]'],

# 其他
'/config': ['debug']
}

print(rules.get('/.git/config', None))

上面两个例子,看看能不能正确地判断出上面的结果是什么?(答案在文章最后面,可以放心地往下看)

隐式行连接

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
In [1]: a = '1234567890abcdefABCDEF'

In [2]: a
Out[2]: '1234567890abcdefABCDEF'

In [3]: a = ('1234567890''abcdefABCDEF')

In [4]: a
Out[4]: '1234567890abcdefABCDEF'

In [5]: a = ('1234567890' 'abcdefABCDEF')

In [6]: a
Out[6]: '1234567890abcdefABCDEF'

In [7]: a = ('1234567890'
...: 'abcdefABCDEF') # 分割长行,这样可读性会比较好

In [8]: a
Out[8]: '1234567890abcdefABCDEF'


过长的字符串先分割为多个短字符串,最后再外面套上括号即可。注意分割符只能是或者单/多个空白符(空格或者换行之类的),比如你用逗号分割那就变成元组了对吧?

很简单吧?看起来似乎也没什么问题。。。

坑点解析

Python 的隐式行连接不仅仅是小括号才能使用,中括号和大括号也是可以使用的。但是仅仅是这一句话,你可能会以为这三个相等:

1
2
3
4
5
In [25]: a = ('1234567890' 'abcdefABCDEF')
...: b = ['1234567890' 'abcdefABCDEF']
...: c = {'1234567890' 'abcdefABCDEF'}
...:
...: a == b == c

但是实际上,b 是个列表,c 是个字典,只有 a 是字符串。原因呢?如果你经常使用元组,你很快就能意识,在创建只有一个元素的元组时,需要在最后加个逗号,否则就变成这个元素本身了:

1
2
3
4
5
In [32]: ('1')
Out[32]: '1'

In [33]: ('1',)
Out[33]: ('1',)




道理是一样的。扯远了扯远了,回到这个坑本身来吧。

所以如果你在定义一个字符串列表的时候,忘记在某个元素之后加括号,那么 Python 就会帮你拼接上去:

1
2
3
4
5
6
In [34]: [
...: '1',
...: '2'
...: '3',
...: ]
Out[34]: ['1', '23']


你看,在大多数情况下,这个结果不是我们想要的吧?

你可能会想,这有什么呢?我一眼就可以看得出来少了个逗号。但是如果一个字符串列表比较大,元素又比较长,是很难直接发现少了个不起眼的逗号的。

第一个例子,这个例子我是在自己写的 CVE 爬虫里遇到过的。CVE 种类繁多,有些漏洞我不感兴趣,比如 Chrome、Safari 的漏洞,iOS 的漏洞、一些小众 CMS 的漏洞等等,我就写了个 list,只要在这个 list 里的就排除不做推送。当然这个 list 不是一次性就写好了,大概用了有一个月吧,过几天就会补几个关键字,慢慢的就有几百个元素了。然后有一天我发现一直在推送 iOS 的漏洞,找了半天没发现 bug,最后仔仔细细检查了大概 300 行的 list,终于发现问题所在。。。

第二个例子,是一个我负责的项目。简单来说,键 是路径,后面 值 中的列表是 关键字,逻辑是只要在这个路径中找到其中一个关键字,就视为匹配成功。然后我无意中发现一直没法匹配到 /.git/config 这个路径。这个例子如果没有经验的话,其实比第一个例子更难发现哪有问题:Python 把多行注释和 /.git/config 拼在了一起,所以根本没有 /.git/config 这个键。幸亏之前在 CVE 爬虫那踩过坑,定位并解决只花了 1 分钟左右。

答案

1
2
False
True
1
None

一些思考

Python 有很多很好使的特性,但是有一些实在是让人心情复杂。比如多行注释,别人家的语言一般都有特定的多行注释,比如 /**/<!----> 等,而 Python 使用三个连续的单引号 ''' 或者三个连续的双引号 """ 注释多行内容,实际上就是定义了一个字符串,只不过是没用上而已,照这个思路,单行注释还可以这样呢:"这是一个注释"。你说有什么问题吧,似乎一下也说不上来;说没问题吧,就是感觉怪怪的,至少本文提到的问题就是多行注释引起的。

Python 隐式行连接会给你挖什么坑?

- By:tr0y.wang


免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2025年1月10日19:16:24
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Python 隐式行连接会给你挖什么坑?http://cn-sec.com/archives/3615888.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息