服务器渗透测试练习(part3:网页设计(2))

#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就会看到文件被修改的提示,确认即可。

网站搭建就完成了(暂时),下一篇文章开始就要进行攻击练习了。

上一篇:Part3-复制表


下一篇:Java学习笔记第04期——Java基础语法Part3