HACK80 首页  立即注册  登录
现在注册
已注册用户请  登录
HACK80    技术文档

IP地址混淆

  •   EvilGod ·2017-12-5 17:01:11·886 次点击 ·阅读模式     

    马上注册,加入HACK80!与我们一起交流。

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 EvilGod 于 2017-12-5 17:02 编辑

    不知有多少人了解IP地址127.0.0.1 一定程度上是完全等价于127.1 和0x7f.1 的,不过我从上回看到ping 127.1 能正常工作开始,就一直很好奇背后的原因,最近又在 一个CTF题目 用到基于IP表示法的技巧,于是决定稍微探索一下。
    我发现一个IPv4地址可能拥有上百个不同的表示形式,而由于一些历史原因,在这方面的标准尚未完全统一,因此这些形式在大部分情况下都是可被正常解析的(举个例子,URL http://000000300.0x000000000a8.00102.00000000351 会解析成http://192.168.66.233/ ),这就在绕过限制和其他一些安全问题上提供了想象的空间。
    本文主要介绍这些混淆背后的历史原因和原理,至于如何生成适用形式的IP也不复杂,并且常常需要考虑具体场景。不过我写了个小脚本,放在了GitHub 上,有需要可作为参考。

    关于IP和IPv4地址
    IPv4是应用于分组交换网络的无状态协议,是网际协议(Internet Protocol , IP)的第四个版本,也是第一个投入生产的版本,1983年开始首先应用在ARPANET项目中。
    IP地址用以标记使用IP接入网络的设备。IPv4把IP地址定义为32位二进制数,可表示 2**32 约42亿个网络设备接口,早期使用分类网络(Classful Addressing)的方法划分为五类,随着IP地址需求的增长,这种分类法被无类别域间路由(Classless Inter-Domain Routing , CIDR)取代。【参见RFC 1517-1519】

    IPv4 地址句法的历史与现状
    一个IPv4地址除了被机器解析外,还会用在很多需要人类阅读理解的地方,而一个32位二进制数(如11000000101010000100001011101001 )对人类是很不友好的,因此人们必然会需要某种文本描述(textual representation) 。我们现在最常见到的点分十进制表示法(dotted-decimal notation) 就是其一。什么是点分十进制呢?就是由点号分隔开的四个十进制数(如192.168.66.233 ) ,其中每个十进制数表示一个字节(octets , 八位二进制数),较高有效位在左,较低有效位在右。
    尽管从上面的描述我们可以了解到IPv4地址的常见形式,但是关于IP地址的文本描述具体应该如何,似乎从来没有严谨全面的定义。另一方面,IP作为互联网中较为基础的设施之一,常常不可避免地出现在各种协议的描述里,这些描述有时顺带也会提及IP地址的写法,但提法不尽相同,也并不足够强硬和严谨。这篇 文章 细数了一些RFC文档里出现过的描述 ,可以看到不同场景下出现过#127.0.0.1 、[127.0.0.1] 、127.000.000.001 等形式的写法。
    当IETF版本的句法处于无意识发展时,BSD版本的句法悄然登场。一个权威的解释大概也不是那么重要,尤其是当一项技术的某种实现已经被广泛使用。对于IPv4地址而言,这个实现就是4.2BSD 。 4.2BSD 引入了名为inet_aton() 的用于将字符串解释为IP地址的函数,这个函数被广泛地复制和演绎,从而使得BSD版本的关于IP地址文本描述的句法成为了事实上的标准——能够被inet_aton() 解释即合标准。至于inet_aton() 接受哪些形式的IP地址,将在下文给出。
    这里先简要谈谈这两种句法的异同。

    相同点
    对于最大多数情况——不带前导0的点分十进制( dotted decimal octets with leading zeroes suppressed ) ,两者都是支持的。

    不同点
    • BSD版本的许多句法IETF版本都不支持
    • 最重要的。IETF版本的句法在所有表述中始终如一地暗示要将带有前导0的数字解释为十进制,而BSD版本的句法在实现中将带有前导0的数字解释为八进制。举个例子,前者认为192.168.1.011 等价于192.168.1.11 ,而后者认为等价于192.168.1.9 。

    值得一提的是IPv6 的发展也对此产生了一定的影响。IPv6中的函数inet_pton() 在处理IPv4地址时只接受点分十进制,并且明确地拒绝了一些能够被inet_aton() 接受的句法。然而,对于是否接受前导0语焉不详。
    此外,2005年的RFC 3986 提出取两者安全的公共子集作为严格的IP地址句法定义,形成倾向于IETF的标准,但同时保持对BSD实现的后向兼容。这个子集的定义如下,简单说就是用点号分隔的四个十进制数,禁止使用前导0。
    1. A 32-bit IPv4 address is divided into four octets.  Each octet is
    2. represented numerically in decimal, using the minimum possible number
    3. of digits (leading zeroes are not used, except in the case of 0
    4. itself).  The four encoded octets are given most-significant first,
    5. separated by period characters.
    6.         IPv4address = d8 "." d8 "." d8 "." d8
    7.         d8          = DIGIT               ; 0-9
    8.                     / %x31-39 DIGIT       ; 10-99
    9.                     / "1" 2DIGIT          ; 100-199
    10.                     / "2" %x30-34 DIGIT   ; 200-249
    11.                     / "25" %x30-35        ; 250-255
    复制代码

    inet_aton()允许哪些形式的IP地址


    1.         a single number giving the entire 32-bit address.
    2.         dot-separated octet values.
    3.         It also interpreted two intermediate syntaxes:
    4.             octet-dot-octet-dot-16bits, intended for class B addresses
    5.             octet-dot-24bits, intended for class A addresses.
    6.         It also allowed some flexibility in how the individual numeric parts were specified. it allowed octal and hexadecimal in addition to decimal, distinguishing these radices by using the C language syntax involving a prefix “0” or “0x”, and allowed the numbers to be arbitrarily long.

    复制代码

    归纳起来有这么几种情况
    • IP地址只有一个部分,表示为a ,每部分表示32位二进制数
    • IP地址有两个部分,表示为a.b ,a 表示8位二进制数,b 表示24位二进制数
    • IP地址有三部分,表示为a.b.c ,a 和b 各表示8位二进制数,c 表示16位二进制数
    • IP地址有四个部分,表示为a.b.c.d ,每部分表示8位二进制数
    以及这么两个重点
    • 每一个部分可以都有三种表示法,十进制、十六进制和八进制,用前缀表明进制。
    • 每部分的数字可以是任意长度。(这意味着可以把077 和0xff 表示成000000077 和0x00000ff 等)
    到此为止,可以看到127.1 属于上述第二种情况,最开始的疑惑也就不复存在。
    这应该算是一个历史遗留问题,不过在未来一段时间内,在广泛涉及URL和IP地址的浏览器和许多应用层程序(如Ping、telnet、wget、curl、GET、HEAD等)中,符合BSD版本句法的IPv4地址表示形式仍然是可接受的,而这些表示可以多达上百种,就可能在一些安全问题上发挥出人意料的作用。
    生成一个IP地址的上百种形式
    1. # coding:utf8
    2. # by https://findneo.github.io/
    3. # ref: https://linux.die.net/man/3/inet_aton
    4. #      https://tools.ietf.org/html/draft-main-ipaddr-text-rep-02
    5. #      https://tools.ietf.org/html/rfc3986
    6. #      http://www.linuxsa.org.au/pipermail/linuxsa/2007-September/088131.html
    7. import itertools as it
    8. import random
    9. ip = '192.168.66.233'
    10. i = ip.split('.')
    11. def f(x):
    12.     return hex(int(x))[2:].zfill(2)
    13. hi = [f(i[0]),
    14.       f(i[1]),
    15.       f(i[2]),
    16.       f(i[3]),
    17.       # hi[4]:part c of "a.b.c"
    18.       f(i[2]) + f(i[3]),
    19.       # hi[5]:part b of "a.b"
    20.       f(i[1]) + f(i[2]) + f(i[3]),
    21.       # hi[6]:'a'
    22.       f(i[0]) + f(i[1]) + f(i[2]) + f(i[3]),
    23.       ]
    24. def hex2oct(x):
    25.     """ arbitrary length is supported
    26.     """
    27.     moreZero = random.choice(range(10))
    28.     return oct(int(x, 16)).zfill(moreZero + len(oct(int(x, 16)))).strip('L')
    29. def hex2int(x): return str(int(x, 16))
    30. def hex2hex(x):
    31.     moreZero = random.choice(range(10))
    32.     return '0x' + '0' * moreZero + x
    33. p = [hex2hex, hex2int, hex2oct]
    34. res = []
    35. # "a.b.c.d"
    36. # Each of the four numeric parts specifies a byte of the address;
    37. # the bytes are assigned in left-to-right order to produce the binary address.
    38. res.extend(['.'.join([i[0](hi[0]), i[1](hi[1]), i[2](hi[2]), i[3](hi[3])]) for i in it.product(p, p, p, p)])
    39. # "a.b.c"
    40. # Parts a and b specify the first two bytes of the binary address.
    41. # Part c is interpreted as a 16-bit value that defines the rightmost two bytes of the binary address.
    42. res.extend(['.'.join([i[0](hi[0]), i[1](hi[1]), i[2](hi[4])]) for i in it.product(p, p, p)])
    43. # "a.b"
    44. # Part a specifies the first byte of the binary address.
    45. # Part b is interpreted as a 24-bit value that defines the rightmost three bytes of the binary address.
    46. res.extend(['.'.join([i[0](hi[0]), i[1](hi[5])]) for i in it.product(p, p)])
    47. # "a"
    48. # The value a is interpreted as a 32-bit value that is stored directly into the binary address without any byte rearrangement.
    49. res.extend(['.'.join([i[0](hi[6])]) for i in it.product(p)])
    50. for i in xrange(len(res)):
    51.     print "[%d]\t%s" % (i, res[i])
    52. # -------------------------------------------------------------------------------
    53. # test
    54. import os
    55. except_ip = []
    56. def test_notation(ip_notation):
    57.     global except_ip
    58.     x = os.popen('ping -n 1 -w 0.5 ' + ip_notation).readlines()
    59.     answer = x[0] if len(x) == 1 else x[1]
    60.     if ip not in answer:
    61.         except_ip.append(ip_notation)
    62.     return answer.decode('gbk').strip()
    63. print "\nchecking. . .",
    64. for i in xrange(len(res)):
    65.     # print "[%d] %s\t\t\t%s" % (i, res[i], test_notation(res[i]))
    66.     test_notation(res[i])
    67.     print '.',
    68. print "\n\ntotally %d notations of ip checked ,all are equivalent to %s" % (len(res), ip)
    69. if len(except_ip):
    70.     print "except for notations following:\n", except_ip
    复制代码

    结果列表
    1. [0]    0x000c0.0xa8.0x0000042.0x0e9
    2. [1]    0x0000c0.0x0000000a8.0x000042.233
    3. [2]    0x000000000c0.0x000000000a8.0x000000042.0000000000351
    4. [3]    0x000c0.0x000000a8.66.0x000000e9
    5. [4]    0xc0.0xa8.66.233
    6. [5]    0x000000c0.0x000000000a8.66.0351
    7. [6]    0x000000000c0.0x00000000a8.0000102.0x0000000e9
    8. [7]    0x0000c0.0x000a8.00102.233
    9. [8]    0x00000000c0.0x00000a8.00000000102.0000000351
    10. [9]    0x00c0.168.0x0042.0x00000e9
    11. [10]    0x000000c0.168.0x00000000042.233
    12. [11]    0x0000000c0.168.0x0042.0000000351
    13. [12]    0x00000000c0.168.66.0x000000000e9
    14. [13]    0x000000c0.168.66.233
    15. [14]    0xc0.168.66.00351
    16. [15]    0xc0.168.0000102.0x00000e9
    17. [16]    0x00c0.168.000000000102.233
    18. [17]    0x0000c0.168.00102.00000000351
    19. [18]    0x0000000c0.0000250.0x00042.0xe9
    20. [19]    0x000c0.0000000250.0x000000042.233
    21. [20]    0x0c0.0000000250.0x00042.00000000351
    22. [21]    0xc0.0000000250.66.0xe9
    23. [22]    0x0000000c0.00000250.66.233
    24. [23]    0x000c0.00250.66.000000351
    25. [24]    0x00000c0.00000250.0000102.0xe9
    26. [25]    0x00000c0.000250.00102.233
    27. [26]    0x000c0.00000250.0000000000102.00000351
    28. [27]    192.0x000000000a8.0x0042.0x0e9
    29. [28]    192.0x0000000a8.0x0042.233
    30. [29]    192.0x0000000a8.0x0000042.0000351
    31. [30]    192.0x000000a8.66.0xe9
    32. [31]    192.0x00000000a8.66.233
    33. [32]    192.0x0000000a8.66.000351
    34. [33]    192.0xa8.00102.0x0000e9
    35. [34]    192.0x00a8.00102.233
    36. [35]    192.0x00000a8.000102.0000000000351
    37. [36]    192.168.0x42.0xe9
    38. [37]    192.168.0x000042.233
    39. [38]    192.168.0x0000000042.000000351
    40. [39]    192.168.66.0x000000000e9
    41. [40]    192.168.66.233
    42. [41]    192.168.66.0000351
    43. [42]    192.168.000102.0x00e9
    44. [43]    192.168.00000102.233
    45. [44]    192.168.00000000102.00000351
    46. [45]    192.0000000250.0x0000000042.0x000e9
    47. [46]    192.000250.0x00000000042.233
    48. [47]    192.0250.0x000000042.0351
    49. [48]    192.000250.66.0x000000e9
    50. [49]    192.0000250.66.233
    51. [50]    192.0000000000250.66.000351
    52. [51]    192.000000000250.00000102.0xe9
    53. [52]    192.00250.0000000102.233
    54. [53]    192.0250.00000000102.0351
    55. [54]    0000000300.0x000a8.0x0000000042.0x0000e9
    56. [55]    000000000300.0x000000000a8.0x0000000042.233
    57. [56]    0000000300.0x000000a8.0x00000042.000351
    58. [57]    0000000300.0x0000a8.66.0x000000000e9
    59. [58]    0000000000300.0x00000000a8.66.233
    60. [59]    0000000300.0x0a8.66.0000351
    61. [60]    0000300.0x00a8.0102.0x00e9
    62. [61]    0000300.0x0000000a8.000102.233
    63. [62]    000000300.0x000000000a8.00102.00000000351
    64. [63]    0000300.168.0x000042.0xe9
    65. [64]    0300.168.0x042.233
    66. [65]    0000000300.168.0x0000000042.0000351
    67. [66]    0000000300.168.66.0x000000000e9
    68. [67]    000300.168.66.233
    69. [68]    0000300.168.66.00000351
    70. [69]    000000000300.168.00102.0x00e9
    71. [70]    0300.168.000000000102.233
    72. [71]    0000300.168.000000102.00000351
    73. [72]    0000000000300.00000000250.0x0042.0x00000000e9
    74. [73]    00300.000000000250.0x42.233
    75. [74]    00000300.000250.0x00000000042.0000351
    76. [75]    000300.000000250.66.0x000000000e9
    77. [76]    0000000000300.000000250.66.233
    78. [77]    000000300.0250.66.00000351
    79. [78]    0000000300.000250.000000102.0xe9
    80. [79]    000300.00000000250.000102.233
    81. [80]    000000000300.0000000250.000102.0000000000351
    82. [81]    0x000000c0.0x00a8.0x42e9
    83. [82]    0x0000c0.0x000a8.17129
    84. [83]    0x000000c0.0x0000a8.00041351
    85. [84]    0x000000000c0.168.0x000042e9
    86. [85]    0x0000c0.168.17129
    87. [86]    0x0000c0.168.000041351
    88. [87]    0x0000000c0.00000000250.0x000000042e9
    89. [88]    0x00000c0.000000000250.17129
    90. [89]    0x000c0.00250.00041351
    91. [90]    192.0x0a8.0x0000000042e9
    92. [91]    192.0x000a8.17129
    93. [92]    192.0x000000a8.0041351
    94. [93]    192.168.0x000042e9
    95. [94]    192.168.17129
    96. [95]    192.168.00041351
    97. [96]    192.00250.0x000000042e9
    98. [97]    192.0250.17129
    99. [98]    192.000000000250.000041351
    100. [99]    00000300.0x00000a8.0x000000042e9
    101. [100]    000000000300.0x00000a8.17129
    102. [101]    00000300.0x000a8.00000000041351
    103. [102]    0300.168.0x000000042e9
    104. [103]    0300.168.17129
    105. [104]    00000000300.168.00000000041351
    106. [105]    0300.000000000250.0x0042e9
    107. [106]    000000000300.0000250.17129
    108. [107]    000000000300.00250.00000000041351
    109. [108]    0x0c0.0x00000a842e9
    110. [109]    0x00c0.11027177
    111. [110]    0x000000c0.0052041351
    112. [111]    192.0x0000a842e9
    113. [112]    192.11027177
    114. [113]    192.000000000052041351
    115. [114]    00000300.0x0000000a842e9
    116. [115]    0000000300.11027177
    117. [116]    0000000300.000000000052041351
    118. [117]    0x0000000c0a842e9
    119. [118]    3232252649
    120. [119]    000000030052041351
    121. checking. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
    122. totally 120 notations of ip checked ,all are equivalent to 192.168.66.233
    123. [Finished in 3.1s]
    复制代码
    1. 本文链接: https://findneo.github.io/2017/11/textual-representation-of-IP-address/
    复制代码


    886 次点击  
    收藏  转播  分享
    添加一条新回复
    您需要登录后才可以回帖 登录 | 立即注册

    本节点积分规则
    QQ
    小黑屋   ·   手机版   ·   228 人在线 最高记录 5500   ·   TOP
    我们很年轻,但我们有信念、有梦想!

      我们坚信只有今天付出了,才有机会看到明天的太阳!现在!加入我们,给你一个气氛优秀的技术圈子。  
    GMT+8, 2018-7-23 06:24, Processed in 0.048439 second(s), 18 queries .