#0:注册页面
打开signup.php,编写如下代码:
<?php function get_real_ip(){ //同前 $ip=false; if(!empty($_SERVER['HTTP_CLIENT_IP'])){ $ip=$_SERVER['HTTP_CLIENT_IP']; } if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ips=explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']); if($ip){ array_unshift($ips, $ip); $ip=FALSE; } for ($i=0; $i < count($ips); $i++){ if(!eregi ('^(10│172.16│192.168).', $ips[$i])){ $ip=$ips[$i]; break; } } } return ($ip ? $ip : $_SERVER['REMOTE_ADDR']); } ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>sign up</title> <style>body{text-align: center}</style> <script> function check(){//对用户输入进行检测 if(document.frm.uname.value==""){ alert("请填写用户名!"); document.frm.uname.focus(); return false; } else{ if(document.frm.ipass.value==""){ alert("请填写密码!"); document.frm.ipass.focus(); return false; } else{ if(document.frm.epass.value==""){ alert("请确认密码!"); document.frm.epass.focus(); return false; } else{ return true; } } } } </script> </head> <body> <?php error_reporting(0); $un=$_POST["uname"]; $i_p=$_POST["ipass"]; $e_p=$_POST["epass"]; $r=0; $id=0; if(isset($un)&& isset($i_p)&& isset($e_p)){ if($i_p==$e_p){ $p=md5($e_p); $xml=simplexml_load_file(".\\AuthInfo.xml"); $ulist=$xml->children(); foreach($ulist as $i){ $id+=1; if($i->name==$un){ $r=1; break; } else{ $r=0; } } if($r==0){ $newuser=$xml->addChild("user");//修改xml文件 $newuserid=$newuser->addChild("id",$id); $newusername=$newuser->addChild("name",$un); $newuserpass=$newuser->addChild("pass",$p); $newuserpermissions=$newuser->addChild("permissions",0); $modi=$xml->asXML(); file_put_contents(".\\AuthInfo.xml",$modi); $ip=get_real_ip(); $f=fopen("tmp\\session@".$ip.".txt","w"); fwrite($f,time()."\r\n".$un."\r\n"."0"."\r\n".$ip); fclose($f); echo 已成功注册; echo '<script>window.open("index.php");</script>'; echo '<script>window.close();</script>'; } else{ echo 此用户已存在; } } else{ echo 两次输入密码不一致,请检测输入; } } ?> <form method="post" name="frm" action=""> 输入用户名: <br> <input type="text" name="uname"> <br> 输入密码: <br> <input type="password" name="ipass"> <br> 确认密码: <br> <input type="password" name="epass"> <br> <br> <input type="submit" name="sub" value="确定"> </form> </body> </html>
在前面的都完成之后就会发现其实还是蛮简单的,如果有信心的人可以自己尝试写后面的东西(阅读页面,新建文档页面,给主页面添加搜索功能等)。
打开浏览器,访问刚才的注册页面,然后多注册几个账号,后面会用到(返回DW之后(如果你用的是DW)会发现提示说AuthInfo.xml文件在外部被修改(如果你在DW里打开了这个文件),只需要点击确定就行了)。
#1:文章列表
打开articles_list.xml,编写如下信息:
<?xml version="1.0" encoding="utf-8"?> <articles> <article><name>test</name><title>测试</title><type>txt</type><writer>root</writer></article> <article><name>test</name><title>xml测试</title><type>xml</type><writer>root</writer></article> </articles>
name是文件的本地名称,title是文件的显示名称,type是文件的类型,writer是作者,除了type其他的都可以随意命名(其实type也不是不可以用别的类型,但是txt和xml需要两种显示方式,所以用了这两个来进行举例)。
#2:阅读页面
这个其实不是很难,主要是读取文档并进行显示。打开read.php,编写如下代码:
<!doctype html> <html> <head> <meta charset="utf-8"> <title>read online</title> <style>body{text-align: center}</style> <script> function back(){ history.back(); } </script> </head> <body> <?php error_reporting(0); if(isset($_GET["name"]) && $_GET["name"]!==""){//这里使用明文进行数据传输,因为传输的是一个文件名,应该不会有什么问题,但这恰恰是问题所在(其实用post也是一样的,反正Burp suite也可以拦截请求) $n=$_GET["name"]; if(file_exists(".\\book\\".$n)){ $xml=simplexml_load_file(".\\articles_list.xml");//进行查询 $alist=$xml->children(); foreach($alist as $i){ $n_arr=explode('.',$n); if($i->name==$n_arr[count($n_arr)-2] && $i->type==$n_arr[count($n_arr)-1]){ break; } } $t=$i->title; $w=$i->writer; $ty=$n_arr[count($n_arr)-1]; $f=".\\book\\".$n; echo '<h2>'.$t.'</h2><h4>Write By: '.$w.'</h4>';//输出标题和作者 echo '<div style="border: 2px solid #000000;background: #9e9e9e;width: 50%;margin-left: 25%;text-align: left">';//正文部分 $f_arr=file($f); if(array_search($ty,array('xml','XXX'))!==false){//带有html或/和xml标签的输出方式(XXX是笔者自定的一种格式,主要用于方便识别带有前述标签的文本文档) foreach($f_arr as $l){ echo '<p style="word-wrap: break-word;word-break: break-all">'.htmlspecialchars($l)."</p>";//处理后输出 } } elseif(array_search($ty,array('txt',''))!==false){//txt和没有后缀的文件直接输出 foreach($f_arr as $l){ echo '<p style="word-wrap: break-word;word-break: break-all">'.$l."</p>"; } } else{//其余用列表的方式进行输出(一行为一项) echo $f_arr; } echo '</div>'; } else{ echo 文件不存在; } } else{ echo 请给出“name”参数; } ?> <button onClick="back()">返回</button> </body> </html>
在之前新建的test.txt和test.xml中随便输点什么(xml要有xml的标签,且是完整的xml文档),然后打开刚才编写的read.php页面,应该会看到对name参数的提示,只需要在当前地址的后面加上?name=test.txt(或xml)就能看见两种显示方式的效果。
但是,这个页面需要人手动进行访问,不方便,所以我们在主页面加上显示文章的功能。
#3:主页面改善(2)
之前已经对主页面进行一次修改了,这下再增加一些东西。在页面开头(get_real_ip()的后面)加上两个函数:
function sch($n){//用于显示搜索结果 $result=array(); $xml=simplexml_load_file(".\\articles_list.xml"); $alist=$xml->children(); foreach($alist as $i){ if(strpos($i->name,$n)!==false || strpos($i->title,$n)!==false){ $rn=$i->name; $rt=$i->type; $rw=$i->writer; $rtt=$i->title; array_push($result,array($rn,$rt,$rw,$rtt)); } } if($result==array()){ echo '<br>没有找到关于"'.$n.'"的文章。';//一般情况会认为在显示的地方会有问题,但是问题恰恰出现在这个地方,只因为没有检查输入 } else{ foreach($result as $i){ if($i[1]=='xml'){ $content='暂不支持该文件类型预览。'; } else{ $f=fopen(".\\book\\".$i[0].'.'.$i[1],'r'); $content=fread($f,101).'...'; }
//文章链接 echo '<br><div style="border: 2px solid #000000;background: #9e9e9e;width: 50%;margin-left: 25%;text-align: left"><a href="read.php?name='.$i[0].'.'.$i[1].'"><font size="7">'.$i[3].'</font></a><br><font size="4"">By:'.$i[2].'</font><br><font size="3">预览:'.$content.'</font></div>'; } } } function recommendation(){//用于在没有搜索时显示所有文章 $xml=simplexml_load_file(".\\articles_list.xml"); $alist=$xml->children(); foreach($alist as $i){ $rn=$i->name; $rt=$i->type; $rw=$i->writer; $rtt=$i->title; if(array_search($rt,array('xml','XXX'))!==false){ $content='暂不支持该文件类型预览。'; } else{ $f=fopen(".\\book\\".$rn.'.'.$rt,'r'); $content=fread($f,101).'...'; }
//同上 echo '<br><div style="border: 2px solid #000000;background: #9e9e9e;width: 50%;margin-left: 25%;text-align: left"><a href="read.php?name='.$rn.'.'.$rt.'"><font size="7">'.$rtt.'</font></a><br><font size="4"">By:'.$rw.'</font><br><font size="3">预览:'.$content.'</font></div>'; } }
然后在body标签中的php部分的最后加上:
echo '<br><form method="post" name="frm" action=""><input type="search" name="in"><input type="submit" name="sub" value="search"></form>';//搜索表单 if(isset($_POST["sub"]) && isset($_POST["in"])){ sch($_POST["in"]); } else{ recommendation(); }
重新访问index页面,就会发现之前的两个test文档已经出现在下面了,点击就会跳转到刚才的阅读页面。
#4:新建文档页面
仅仅只有两个文档的网站显然没有什么吸引力。那么就需要一个可以让用户自己写东西的地方(类似于我现在正在用来写博的这个东西,但是当时我还不知道有这个编辑器,所以是自己造的*)。
打开newdoc.php,编写如下代码:
<?php function get_real_ip(){ //同前,因为需要session验证 $ip=false; if(!empty($_SERVER['HTTP_CLIENT_IP'])){ $ip=$_SERVER['HTTP_CLIENT_IP']; } if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ips=explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']); if($ip){ array_unshift($ips, $ip); $ip=FALSE; } for ($i=0; $i < count($ips); $i++){ if(!eregi ('^(10│172.16│192.168).', $ips[$i])){ $ip=$ips[$i]; break; } } } return ($ip ? $ip : $_SERVER['REMOTE_ADDR']); } if(isset($_POST["name"]) && isset($_POST["ty"]) && isset($_POST["tt"]) && isset($_POST["content"]) && isset($_POST["h"])){//保存文件操作 $n=$_POST["name"]; $ty=$_POST["ty"]; $tt=$_POST["tt"]; $ct=$_POST["content"]; $wr=$_POST["h"]; $r=0; $xml=simplexml_load_file(".\\articles_list.xml");//添加到列表中 $alist=$xml->children(); foreach($alist as $i){ if($i->name==$n && $i->type==$ty){//验证文件是否已经存在 $r=1; break; } } if($r==0){ $newdoc=$xml->addChild("article"); $newdocname=$newdoc->addChild("name",$n); $newdoctitle=$newdoc->addChild("title",$tt); $newdoctype=$newdoc->addChild("type",$ty); $newdocwriter=$newdoc->addChild("writer",$wr); $modi=$xml->asXML(); file_put_contents(".\\articles_list.xml",$modi);//保存到服务器 file_put_contents('.\\book\\'.$n.'.'.$ty,$ct); echo '<script>alert("已成功保存!");</script>'; } else{ echo '<script>alert("该文件名已经使用!");</script>'; } } ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>editor</title> <style>body{text-align: center}</style> <script> function check(){//验证输入(文档名称即保存在本地的名字和标题即显示的文字不能省略) if(document.frm.name.value==""){ alert("请填写文档名称!"); document.frm.name.focus(); return false; } else{ if(document.frm.tt.value==""){ alert("请填写文档标题!"); document.frm.pass.focus(); return false; } else{ return true; } } } function back(){//返回 window.open("index.php"); window.close(); } </script> </head> <body> <?php error_reporting(0); $user=get_real_ip(); if(file_exists("tmp\\session@".$user.".txt")){//session验证 $f_arr=file("tmp\\session@".$user.".txt"); if((floatval($f_arr[0])+3600)<time()){ unlink("tmp\\session@".$user.".txt"); echo '<script>alert("登录已过期,游客身份无法发表文章!");</script>'; if(isset($_GET["an"])){ echo '<script>window.open("'.$_SERVER["HTTP_REFERER"].'");</script>'; echo '<script>window.close();</script>'; } else{ echo '<script>window.close();</script>'; } } else{ $w=str_replace(PHP_EOL,'',$f_arr[1]); if(!isset($_GET["an"])){ if(isset($_POST["name"]) && isset($_POST["ty"]) && isset($_POST["tt"]) && isset($_POST["content"])){
//已经提交之后的肯定不希望没有通过而表单清空,所以会有这一条 echo '<form method="post" name="frm" action=""><input type="hidden" name="h" value="'.$w.'"><textarea name="name" cols="172" rows="1" wrap="virtual" placeholder="文档名称" >'.$_POST["name"].'</textarea> <textarea name="ty" cols="24" rows="1" wrap="virtual" placeholder="文档类型(txt、xml...)" >'.$_POST["ty"].'</textarea><br><textarea name="tt" cols="200" rows="1" wrap="virtual" placeholder="文档标题" >'.$_POST["tt"].'</textarea><br><textarea name="content" cols="200" rows="60" wrap="virtual" placeholder="文档正文(支持HTML格式)">'.$_POST["content"].'</textarea><br><input type="submit" name="sub" value="提交" style="height: 30px;width: 100px" onClick="return check()"></form>'; } else{ echo '<form method="post" name="frm" action=""><input type="hidden" name="h" value="'.$w.'"><textarea name="name" cols="172" rows="1" wrap="virtual" placeholder="文档名称" ></textarea> <textarea name="ty" cols="24" rows="1" wrap="virtual" placeholder="文档类型(txt、xml...)" ></textarea><br><textarea name="tt" cols="200" rows="1" wrap="virtual" placeholder="文档标题" ></textarea><br><textarea name="content" cols="200" rows="60" wrap="virtual" placeholder="文档正文(支持HTML格式)"></textarea><br><input type="submit" name="sub" value="提交" style="height: 30px;width: 100px" onClick="return check()"></form>'; } } } } else{ echo '<script>alert("游客身份无法发表文章!");</script>'; if(isset($_GET["an"])){ echo '<script>window.open("'.$_SERVER["HTTP_REFERER"].'");</script>'; echo '<script>window.close();</script>'; } else{ echo '<script>window.close();</script>'; } } ?> <button onClick="back()">返回</button> </body> </html>
访问newdoc页面(先登录),随便写点什么,然后点击提交,就会发现提交成功的消息,返回DW就会看到和AuthInfo.xml相似的提示,确认就行了,查看book文件夹(你的可能是别的名字,反正都是你自己用)下多出来了文件,点击打开就是你刚刚写的东西。
然后打开index.php,找到三处注销按钮,在每一处的下方都加上:
echo '<form method="post" name="edt" action="newdoc.php"><input type="submit" name="sub" value="新建文档"></form>';
再访问index页面,会发现出现了新建文档的按钮,点击就会跳转到刚刚的newdoc页面,两篇test的下面也出现了文章的标题和预览,点击就能看到文档内容。
#5:账号管理页面(主管)(因为暂时只写了这些(这是目前为止最后一个页面,是主管将普通用户设为管理员用的,但是肯定还没完)但是后面会增加用户对自己账号的管理页面(也许吧)所以这里特意标记了主管)
新建(因为之前的架构中没有这个文件)accmgt.php,编写如下代码:
<?php function get_real_ip(){ //同前,需要使用session $ip=false; if(!empty($_SERVER['HTTP_CLIENT_IP'])){ $ip=$_SERVER['HTTP_CLIENT_IP']; } if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){ $ips=explode (', ', $_SERVER['HTTP_X_FORWARDED_FOR']); if($ip){ array_unshift($ips, $ip); $ip=FALSE; } for ($i=0; $i < count($ips); $i++){ if(!eregi ('^(10│172.16│192.168).', $ips[$i])){ $ip=$ips[$i]; break; } } } return ($ip ? $ip : $_SERVER['REMOTE_ADDR']); } if(isset($_POST["sub"])){//提交之后的处理 if(isset($_POST["un"])){ $un=$_POST["un"]; $xml=simplexml_load_file(".\\AuthInfo.xml"); $ulist=$xml->children(); foreach($ulist as $u){ if($u->name==$un){ $u->permissions=1; $modi=$xml->asXML(); file_put_contents(".\\AuthInfo.xml",$modi); echo '<script>alert("修改成功");</script>'; break; } } } } ?> <!doctype html> <html> <head> <meta charset="utf-8"> <title>Account management</title> <style>body{text-align: center}</style> <script> function back(){ window.open("index.php"); window.close(); } </script> </head> <body> <?php error_reporting(0); $user=get_real_ip(); if(file_exists("tmp\\session@".$user.".txt")){//检测session $f_arr=file("tmp\\session@".$user.".txt"); //print_r($f_arr); if((floatval($f_arr[0])+3600)<time()){ unlink("tmp\\session@".$user.".txt"); echo '<script>alert("登录已过期,非主管不能管理账号!");</script>'; echo '<script>window.open("'.$_SERVER["HTTP_REFERER"].'");</script>'; echo '<script>window.close();</script>'; } else{ if($f_arr[2]==2){ $xml=simplexml_load_file(".\\AuthInfo.xml");//打开用户列表并输出 $ulist=$xml->children(); echo '<div style="border: 2px solid #000000;background: #9e9e9e;width: 50%;margin-left: 25%;text-align: left">'; foreach($ulist as $i){ if($i->permissions==0){//判断是否为普通用户 echo '<form method="post" action="" name="frm"><input type="text" name="un" readonly="readonly" value="'.$i->name.'"><input type="submit" name="sub" value="设置为管理员"></form>'; } else{ echo '<input type="text" name="un" readonly="readonly" value="'.$i->name.'"><button>对象已是管理员或主管</button><br>'; } } echo '</div>'; echo '<button onClick="back()">返回</button>'; } else{ echo '<script>alert("非主管不能管理账号!");</script>'; echo '<script>window.open("'.$_SERVER["HTTP_REFERER"].'");</script>'; echo '<script>window.close();</script>'; } } } else{ echo '<script>alert("非主管不能管理账号!");</script>'; echo '<script>window.open("'.$_SERVER["HTTP_REFERER"].'");</script>'; echo '<script>window.close();</script>'; } ?> </body> </html>
然后打开index.php,找到主管的新建文档按钮,在其下方添加如下代码:
echo '<form method="post" name="amt" action="accmgt.php"><input type="submit" name="sub" value="管理账号"></form>';
访问登录页面,以root账号登录(或者你自己设置的主管账号),然后点击刚才添加的按钮,就会跳转到刚刚编写的accmgt.php页面,随便点击一个普通用户名字后的“设为管理员”按钮,然后会出现提示信息说已经修改成功,返回DW就会看到文件被修改的提示,确认即可。
网站搭建就完成了(暂时),下一篇文章开始就要进行攻击练习了。