Natas Wargame Level20 Writeup(会话状态注入/篡改)

sourcecode核心代码:

  1 <?
  2
  3 function debug($msg) {
  4     if(array_key_exists("debug", $_GET)) {
  5         print "DEBUG: $msg<br>";
  6     }
  7 }
  8
  9 function print_credentials() {
 10     if($_SESSION and array_key_exists("admin", $_SESSION) and $_SESSION["admin"] == 1) {
 11     print "You are an admin. The credentials for the next level are:<br>";
 12     print "<pre>Username: natas21\n";
 13     print "Password: <censored></pre>";
 14     } else {
 15     print "You are logged in as a regular user. Login as an admin to retrieve credentials for natas21.";
 16     }
 17 }
 18
 19
 20 /* we don‘t need this */
 21 function myopen($path, $name) {
 22     //debug("MYOPEN $path $name");
 23     return true;
 24 }
 25
 26 /* we don‘t need this */
 27 function myclose() {
 28     //debug("MYCLOSE");
 29     return true;
 30 }
 31
 32 function myread($sid) {
 33     debug("MYREAD $sid");
 34     if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
 35     debug("Invalid SID");
 36         return "";
 37     }
 38     $filename = session_save_path() . "/" . "mysess_" . $sid;
 39     if(!file_exists($filename)) {
 40         debug("Session file doesn‘t exist");
 41         return "";
 42     }
 43     debug("Reading from ". $filename);
 44     $data = file_get_contents($filename);
 45     $_SESSION = array();
 46     foreach(explode("\n", $data) as $line) {
 47         debug("Read [$line]");
 48     $parts = explode(" ", $line, 2);
 49     if($parts[0] != "") $_SESSION[$parts[0]] = $parts[1];
 50     }
 51     return session_encode();
 52 }
 53
 54 function mywrite($sid, $data) {
 55     // $data contains the serialized version of $_SESSION
 56     // but our encoding is better
 57     debug("MYWRITE $sid $data");
 58     // make sure the sid is alnum only!!
 59     if(strspn($sid, "1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM-") != strlen($sid)) {
 60     debug("Invalid SID");
 61         return;
 62     }
 63     $filename = session_save_path() . "/" . "mysess_" . $sid;
 64     $data = "";
 65     debug("Saving in ". $filename);
 66     ksort($_SESSION);
 67     foreach($_SESSION as $key => $value) {
 68         debug("$key => $value");
 69         $data .= "$key $value\n";
 70     }
 71     file_put_contents($filename, $data);
 72     chmod($filename, 0600);
 73 }
 74
 75 /* we don‘t need this */
 76 function mydestroy($sid) {
 77     //debug("MYDESTROY $sid");
 78     return true;
 79 }
 80 /* we don‘t need this */
 81 function mygarbage($t) {
 82     //debug("MYGARBAGE $t");
 83     return true;
 84 }
 85
 86 session_set_save_handler(
 87     "myopen",
 88     "myclose",
 89     "myread",
 90     "mywrite",
 91     "mydestroy",
 92     "mygarbage");
 93 session_start();
 94
 95 if(array_key_exists("name", $_REQUEST)) {
 96     $_SESSION["name"] = $_REQUEST["name"];
 97     debug("Name set to " . $_REQUEST["name"]);
 98 }
 99
100 print_credentials();
101
102 $name = "";
103 if(array_key_exists("name", $_SESSION)) {
104     $name = $_SESSION["name"];
105 }
106
107 ?>
108
109 <form action="index.php" method="POST">
110 Your name: <input name="name" value="<?=$name?>"><br>
111 <input type="submit" value="Change name" />
112 </form> 

关键部分已经用红色标出,mywrite和myread是两个管理会话状态的关键函数,以下是一些参考资料:

http://php.net/manual/zh/function.session-set-save-handler.php

http://php.net/manual/zh/function.strspn.php

http://www.w3school.com.cn/php/func_string_explode.asp

http://php.net/manual/zh/function.session-encode.php

简单来说,myread首先对sid(第一次由服务器自动生成并保存在cookie中)进行校验,若非字母/数字则不返回会话状态。

若sid合法,则进入相关目录寻找/读取文件,若是老的会话/文件已经删除会新建文件保存会话,文件读取完后将session的最后一对键值覆盖到第一的位置。

mywrite则会在会话结束的时候重新读取session,并对session进行一次ksort,将排序后的键值对重新写入文件。

一开始我的思路是通过使sid带有目录路径(改cookie),使得debug输出的时候将/etc/....../natas20的文件内容读出来,但是在myread和mywrite里面都进行了检验,所以很难通过sid进行注入。

另一个思路就是,源码里面其实没有向session里面添加admin的键值对,这也提示我们可以通过“唯一”的一个name键值对进行注入:将data里面的值变为:name xxxx\nadmin 1\n

如何添加这个\n呢?既然通过get方式提交,也就要用URL编码编码后进行提交。(这里有个插曲,一开始我对mywrite的写入和myread的读取没有理解好,以为注入name xxx admin 1就可以了,实际上如果让mywrite这么写入,myread读取会话状态时$parts = explode(" ", $line, 2),只会将这仅有的一行的第一个键值对name xxx添加到session里面)。\n对应%0A (\r对应%0D,但在linux下用换行号就够了)。所以应该输入xxx\nadmin 1,第一次会显示regular,因为没有文件/状态可以读取,session里还是没有Admin的,会话关闭后xxx\nadmin1就会被写入到状态中,下次登录后session就会被加入admin 1了。

但是,这里的输入并不能直接在form中输入并提交:

因为\n即回车并不会被编码为%0A这个字节存入到file中,可以直接url中输入并提交或者改postbody。

http://natas20.natas.labs.overthewire.org/index.php?name=xxx%0Aadmin%201&debug=1(%20为空格 直接空格也行)

总结:如果用户的输入要保存为会话状态,服务端读取和写入会话时要进行防注入处理,,否则存在提权或劫持等注入问题。

flag:IFekPyrQXftziDEsUr3x21sYuahypdgJ

时间: 2024-08-29 03:59:57

Natas Wargame Level20 Writeup(会话状态注入/篡改)的相关文章

Natas Wargame Level 13 Writeup(文件上传漏洞,篡改file signature,Exif)

sourcecode核心代码: 1 <? 2 3 function genRandomString() { 4 $length = 10; 5 $characters = "0123456789abcdefghijklmnopqrstuvwxyz"; 6 $string = ""; 7 8 for ($p = 0; $p < $length; $p++) { 9 $string .= $characters[mt_rand(0, strlen($char

Natas Wargame Level 17 Writeup(Time-based Blind SQL Injection)

sourcecode核心代码: 1 <? 2 3 /* 4 CREATE TABLE `users` ( 5 `username` varchar(64) DEFAULT NULL, 6 `password` varchar(64) DEFAULT NULL 7 ); 8 */ 9 10 if(array_key_exists("username", $_REQUEST)) { 11 $link = mysql_connect('localhost', 'natas17', '&

Natas Wargame Level 19 Writeup(猜测令牌,会话劫持)

根据题目提示,这个题跟上一个题差不多,但是会话编码不再是连续的了. 一开始我跟上一个题一样,不断输入'admin':'1' 并使headers里面没有cookie,从而根据返回的set-cookie判断会话编码的方式. 结果发现编码的大多数位都是一样的,只有4个位在变化,于是我以为这个题只是给编码空间用很多位打了个'掩护',其实空间还是很小的.变使用这四个位进行猜测,无果. 实际上在这种猜测规律的时候应该采取类似于fuzz的输入,如果输入不变的话是会有猜测错误的可能性的. 输入'admin':'

Natas Wargame Level 2 Writeup 与目录泄露(强制访问)

注意到"files/pixel.png",flag可能隐藏在此图片中.但随后发现该图片仅仅是一个一像素的图标,"没有"意义--files/目录可能是可以访问的: 拿到flag:natas3:sJIJNW6ucpu6HPZ1ZAchaDtwd7oGrD14 总结:HTML/CSS/JS等客户端文件可能会泄露站长不想让客户端访问的目录,即该目录下即包含可访问文件又包含敏感文件,并且该目录没有进行权限认证(强制访问),形成一个切入点.

Natas Wargame Level 3 Writeup 与 robots.txt

从HTML的注释代码来看,"google无法搜索到这个页面" -> 说明该网站很可能设置了防爬虫机制:robots.txt 以下是robots.txt的介绍(来自维基百科): --------------------------------------------------------------------------------- robots.txt(统一小写)是一种存放于网站根目录下的ASCII编码的文本文件,它通常告诉网络搜索引擎的漫游器(又称网络蜘蛛), 此网站中的

解决和防止异常程序注入篡改文件

故障点:大部分地区访问我们的门户网站都跳转到同一条域名地址了 故障点分析: 1.大部分域名被劫持跳转到同一条域名 2.域名劫持只有部分地区,但都是访问量大的地区 3.授权DNS的工具dnspod刚好这个时间维护了 4.nginx配置文件被修改,是否有做地址重写 5.问开发说可能是js或者php文件被篡改,url地址被程序重写定向了 解决流程: 起初,我们以为部分地区被劫持,加上dnspod维护,以为是dnspod那里业务受到了影响,导致了跳转现象.但是从dnspod上的维护信息上看,只是解析业务

Bandit Wargame Level12 Writeup

Level Goal The password for the next level is stored in the file data.txt, which is a hexdump of a file that has been repeatedly compressed. For this level it may be useful to create a directory under /tmp in which you can work using mkdir. For examp

OWASP top10

PhishTank 是互联网上免费提供恶意网址黑名单的组织之一,它的黑名单由世界各地的志愿者提供,且更新频繁. 1.XSS 1.1. XSS简介 跨站脚本攻击,英文全称是Cross Site Script,本来缩写是CSS,但是为了和层叠样式表有所区分,所以在安全领域叫做"XSS". XSS攻击,通常指黑客通过"HTML注入"篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击. 1.2. XSS分类 XSS根据效果的不同可以分成如下几类 第

白帽子讲Web安全 第三章 跨站脚本攻击(XSS)

XSS----Cross Site Script; XSS攻击,通常指黑客通过"HTML注入"篡改了网页,插入了恶意的脚本,从而在用户浏览网页时,控制用户浏览器的一种攻击. 1.XSS根据效果划分三类: 1)反射型XSS(非持久型XSS):简单的把用户输入的数据"反射"给浏览器.黑客往往需要诱导用户点击一个恶意链接,才能攻击成功. 2)存储型XSS(持久型XSS):存储型会把用户输入的数据存储在服务器端.这种具有很强的稳定性. 3)DOM Based XSS:通过修