{"action":"created","comment":{"url":"https://api.github.com/repos/montekki/www/pulls/comments/208456242","pull_request_review_id":144267820,"id":208456242,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDIwODQ1NjI0Mg==","diff_hunk":"@@ -172,16 +208,131 @@ in other words, approximate an identity function. If the trained autoencoder\n is given an anomalous sample it is likely to re-create it with a high degree\n of error.\n \n+So, basically, autoencoder model consists of two parts: coder and decoder. The task of\n+the encoder is to compress the input data into a special representation. The task\n+of the decoder part is to learn how to decode correctly from a special representation\n+to the original form. If the certain input differs greatly from other data, the decoder\n+can't reconstruct a representation correctly.\n+\n+That means that the model has never seen the data like this. So this input is considered\n+as an anomaly.\n+\n ![autoencoder](images/detecting-web-attacks-rnn-02.png)\n \n-### The result\n+*image taken from [What to do when data is missing, Part II](http://curiousily.com/data-science/2017/02/02/what-to-do-when-data-is-missing-part-2.html)*\n \n-Finally, we ended up with a seq2seq autoencoder model that proved to be able to find\n-anomalies in HTTP requests. Pre-processed request data is fed both to inputs\n-and the outputs of the model, thus it learns to re-create the sequences it sees.\n+Our solution is made up of several parts: model definition, training part, prediction\n+part for setting specific constants and validation.\n+\n+We avoid explanation of typical code in the [solution](https://github.com/PositiveTechnologies/seq2seq-web-attack-detection) and comment on a few aspects only.\n+\n+For working with raw data we made several useful utils. The code is really simple\n+and obvious, so, we hid its realization in the baseline and took it to the data folder.\n+\n+In the model definition part we define `Seq2Seq` class where in `__init__` method\n+we initialize main model parameters:\n+```\n+batch_size - the number of samples in a batch\n+embed_size - the dimension of embedding space (should be less than vocabulary size)\n+hidden_size - the number of hidden states in lstm\n+num_layers - the number of lstm blocks\n+checkpoints - path to checkpoint directory\n+std_factor - the number of stds that is used for defining a model threshold\n+dropout - the probability that each element is kept\n+vocab - the Vocabulary object\n+```\n \n-We built our model into our WAF and trained against our test vulnerable application\n-of a bank.\n+Then we define autoencoder's layers. For the encoder's part this way:\n+```python\n+  # Encoder\n+  cells = [self._lstm_cell(args['hidden_size']) for _ in range(args['num_layers'])]\n+  multilstm = tf.contrib.rnn.MultiRNNCell(cells, state_is_tuple=True)\n+\n+  _, enc_state = tf.nn.dynamic_rnn(\n+      multilstm,\n+      enc_embed_input,\n+      sequence_length=self.lengths,\n+      swap_memory=True,\n+      dtype=tf.float32)\n+```\n+\n+The decoder's part like that:\n+```python\n+  # Decoder\n+output_lengths = tf.reduce_sum(tf.to_int32(tf.not_equal(self.targets, 1)), 1)\n+helper = tf.contrib.seq2seq.TrainingHelper(\n+    dec_embed_input,\n+    output_lengths,\n+    time_major=False)\n+\n+cells = [self._lstm_cell(args['hidden_size']) for _ in range(args['num_layers'])]\n+dec_cell = tf.contrib.rnn.MultiRNNCell(cells, state_is_tuple=True)\n+\n+decoder = tf.contrib.seq2seq.BasicDecoder(dec_cell, helper, enc_state)\n+\n+dec_outputs = tf.contrib.seq2seq.dynamic_decode(\n+    decoder,\n+    output_time_major=False,\n+    impute_finished=True,\n+    maximum_iterations=self.max_seq_len, swap_memory=True)\n+```\n+\n+In short, the training process is quite typical for training models. We just fit in\n+our model on each step and run the tensorflow session.\n+\n+In case of anomaly detection problem we reconstruct input data, so targets and\n+inputs are the same. Thus our `feed_dict` looks this way:\n+\n+```python\n+feed_dict = {\n+  model.inputs: X,\n+  model.targets: X,\n+  model.lengths: L,\n+  model.dropout: self.dropout,\n+  model.batch_size: self.batch_size,\n+  model.max_seq_len: seq_len}\n+```\n+\n+The best model version we save as a checkpoint. Then at the stage of prediction,\n+we load it. In our proof of concept, we had not only Jupiter notebook but a running\n+web application where we can load model and manually exploit some vulnerabilities\n+to test our solution better.\n+\n+Being inspired by the attention mechanism we tried to apply it to autoencoder but\n+noticed that probabilities output from the last layer works better. We began to\n+use the probabilities to mark the malicious parts of a given request.","path":"content/posts/detecting-web-attacks-rnn.md","position":188,"original_position":188,"commit_id":"b4074b97df9a04dba9b51bd568b22458b3e583d0","original_commit_id":"b4074b97df9a04dba9b51bd568b22458b3e583d0","user":{"login":"amurzina","id":7440482,"node_id":"MDQ6VXNlcjc0NDA0ODI=","avatar_url":"https://avatars0.githubusercontent.com/u/7440482?v=4","gravatar_id":"","url":"https://api.github.com/users/amurzina","html_url":"https://github.com/amurzina","followers_url":"https://api.github.com/users/amurzina/followers","following_url":"https://api.github.com/users/amurzina/following{/other_user}","gists_url":"https://api.github.com/users/amurzina/gists{/gist_id}","starred_url":"https://api.github.com/users/amurzina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amurzina/subscriptions","organizations_url":"https://api.github.com/users/amurzina/orgs","repos_url":"https://api.github.com/users/amurzina/repos","events_url":"https://api.github.com/users/amurzina/events{/privacy}","received_events_url":"https://api.github.com/users/amurzina/received_events","type":"User","site_admin":false},"body":"fixed","created_at":"2018-08-08T04:56:10Z","updated_at":"2018-08-08T04:56:10Z","html_url":"https://github.com/montekki/www/pull/3#discussion_r208456242","pull_request_url":"https://api.github.com/repos/montekki/www/pulls/3","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/montekki/www/pulls/comments/208456242"},"html":{"href":"https://github.com/montekki/www/pull/3#discussion_r208456242"},"pull_request":{"href":"https://api.github.com/repos/montekki/www/pulls/3"}},"in_reply_to_id":208233869},"pull_request":{"url":"https://api.github.com/repos/montekki/www/pulls/3","id":204117617,"node_id":"MDExOlB1bGxSZXF1ZXN0MjA0MTE3NjE3","html_url":"https://github.com/montekki/www/pull/3","diff_url":"https://github.com/montekki/www/pull/3.diff","patch_url":"https://github.com/montekki/www/pull/3.patch","issue_url":"https://api.github.com/repos/montekki/www/issues/3","number":3,"state":"open","locked":false,"title":"add a little bit code and results","user":{"login":"amurzina","id":7440482,"node_id":"MDQ6VXNlcjc0NDA0ODI=","avatar_url":"https://avatars0.githubusercontent.com/u/7440482?v=4","gravatar_id":"","url":"https://api.github.com/users/amurzina","html_url":"https://github.com/amurzina","followers_url":"https://api.github.com/users/amurzina/followers","following_url":"https://api.github.com/users/amurzina/following{/other_user}","gists_url":"https://api.github.com/users/amurzina/gists{/gist_id}","starred_url":"https://api.github.com/users/amurzina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amurzina/subscriptions","organizations_url":"https://api.github.com/users/amurzina/orgs","repos_url":"https://api.github.com/users/amurzina/repos","events_url":"https://api.github.com/users/amurzina/events{/privacy}","received_events_url":"https://api.github.com/users/amurzina/received_events","type":"User","site_admin":false},"body":"","created_at":"2018-07-26T11:54:16Z","updated_at":"2018-08-08T04:56:10Z","closed_at":null,"merged_at":null,"merge_commit_sha":"c5521cb1b3e5c362eecec3afdf4910159531bdfd","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/montekki/www/pulls/3/commits","review_comments_url":"https://api.github.com/repos/montekki/www/pulls/3/comments","review_comment_url":"https://api.github.com/repos/montekki/www/pulls/comments{/number}","comments_url":"https://api.github.com/repos/montekki/www/issues/3/comments","statuses_url":"https://api.github.com/repos/montekki/www/statuses/b4074b97df9a04dba9b51bd568b22458b3e583d0","head":{"label":"amurzina:patch-1","ref":"patch-1","sha":"b4074b97df9a04dba9b51bd568b22458b3e583d0","user":{"login":"amurzina","id":7440482,"node_id":"MDQ6VXNlcjc0NDA0ODI=","avatar_url":"https://avatars0.githubusercontent.com/u/7440482?v=4","gravatar_id":"","url":"https://api.github.com/users/amurzina","html_url":"https://github.com/amurzina","followers_url":"https://api.github.com/users/amurzina/followers","following_url":"https://api.github.com/users/amurzina/following{/other_user}","gists_url":"https://api.github.com/users/amurzina/gists{/gist_id}","starred_url":"https://api.github.com/users/amurzina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amurzina/subscriptions","organizations_url":"https://api.github.com/users/amurzina/orgs","repos_url":"https://api.github.com/users/amurzina/repos","events_url":"https://api.github.com/users/amurzina/events{/privacy}","received_events_url":"https://api.github.com/users/amurzina/received_events","type":"User","site_admin":false},"repo":{"id":142133795,"node_id":"MDEwOlJlcG9zaXRvcnkxNDIxMzM3OTU=","name":"www","full_name":"amurzina/www","owner":{"login":"amurzina","id":7440482,"node_id":"MDQ6VXNlcjc0NDA0ODI=","avatar_url":"https://avatars0.githubusercontent.com/u/7440482?v=4","gravatar_id":"","url":"https://api.github.com/users/amurzina","html_url":"https://github.com/amurzina","followers_url":"https://api.github.com/users/amurzina/followers","following_url":"https://api.github.com/users/amurzina/following{/other_user}","gists_url":"https://api.github.com/users/amurzina/gists{/gist_id}","starred_url":"https://api.github.com/users/amurzina/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/amurzina/subscriptions","organizations_url":"https://api.github.com/users/amurzina/orgs","repos_url":"https://api.github.com/users/amurzina/repos","events_url":"https://api.github.com/users/amurzina/events{/privacy}","received_events_url":"https://api.github.com/users/amurzina/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/amurzina/www","description":"AI Village website","fork":true,"url":"https://api.github.com/repos/amurzina/www","forks_url":"https://api.github.com/repos/amurzina/www/forks","keys_url":"https://api.github.com/repos/amurzina/www/keys{/key_id}","collaborators_url":"https://api.github.com/repos/amurzina/www/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/amurzina/www/teams","hooks_url":"https://api.github.com/repos/amurzina/www/hooks","issue_events_url":"https://api.github.com/repos/amurzina/www/issues/events{/number}","events_url":"https://api.github.com/repos/amurzina/www/events","assignees_url":"https://api.github.com/repos/amurzina/www/assignees{/user}","branches_url":"https://api.github.com/repos/amurzina/www/branches{/branch}","tags_url":"https://api.github.com/repos/amurzina/www/tags","blobs_url":"https://api.github.com/repos/amurzina/www/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/amurzina/www/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/amurzina/www/git/refs{/sha}","trees_url":"https://api.github.com/repos/amurzina/www/git/trees{/sha}","statuses_url":"https://api.github.com/repos/amurzina/www/statuses/{sha}","languages_url":"https://api.github.com/repos/amurzina/www/languages","stargazers_url":"https://api.github.com/repos/amurzina/www/stargazers","contributors_url":"https://api.github.com/repos/amurzina/www/contributors","subscribers_url":"https://api.github.com/repos/amurzina/www/subscribers","subscription_url":"https://api.github.com/repos/amurzina/www/subscription","commits_url":"https://api.github.com/repos/amurzina/www/commits{/sha}","git_commits_url":"https://api.github.com/repos/amurzina/www/git/commits{/sha}","comments_url":"https://api.github.com/repos/amurzina/www/comments{/number}","issue_comment_url":"https://api.github.com/repos/amurzina/www/issues/comments{/number}","contents_url":"https://api.github.com/repos/amurzina/www/contents/{+path}","compare_url":"https://api.github.com/repos/amurzina/www/compare/{base}...{head}","merges_url":"https://api.github.com/repos/amurzina/www/merges","archive_url":"https://api.github.com/repos/amurzina/www/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/amurzina/www/downloads","issues_url":"https://api.github.com/repos/amurzina/www/issues{/number}","pulls_url":"https://api.github.com/repos/amurzina/www/pulls{/number}","milestones_url":"https://api.github.com/repos/amurzina/www/milestones{/number}","notifications_url":"https://api.github.com/repos/amurzina/www/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/amurzina/www/labels{/name}","releases_url":"https://api.github.com/repos/amurzina/www/releases{/id}","deployments_url":"https://api.github.com/repos/amurzina/www/deployments","created_at":"2018-07-24T09:09:45Z","updated_at":"2018-07-24T09:09:47Z","pushed_at":"2018-08-06T12:40:24Z","git_url":"git://github.com/amurzina/www.git","ssh_url":"git@github.com:amurzina/www.git","clone_url":"https://github.com/amurzina/www.git","svn_url":"https://github.com/amurzina/www","homepage":"https://aivillage.org/","size":30544,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":null,"forks":0,"open_issues":0,"watchers":0,"default_branch":"code"}},"base":{"label":"montekki:detecting-web-attacks-rnn","ref":"detecting-web-attacks-rnn","sha":"9e41e877a3eaf0bd7868b5141a281ac7aefc47bc","user":{"login":"montekki","id":56672,"node_id":"MDQ6VXNlcjU2Njcy","avatar_url":"https://avatars0.githubusercontent.com/u/56672?v=4","gravatar_id":"","url":"https://api.github.com/users/montekki","html_url":"https://github.com/montekki","followers_url":"https://api.github.com/users/montekki/followers","following_url":"https://api.github.com/users/montekki/following{/other_user}","gists_url":"https://api.github.com/users/montekki/gists{/gist_id}","starred_url":"https://api.github.com/users/montekki/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/montekki/subscriptions","organizations_url":"https://api.github.com/users/montekki/orgs","repos_url":"https://api.github.com/users/montekki/repos","events_url":"https://api.github.com/users/montekki/events{/privacy}","received_events_url":"https://api.github.com/users/montekki/received_events","type":"User","site_admin":false},"repo":{"id":140855470,"node_id":"MDEwOlJlcG9zaXRvcnkxNDA4NTU0NzA=","name":"www","full_name":"montekki/www","owner":{"login":"montekki","id":56672,"node_id":"MDQ6VXNlcjU2Njcy","avatar_url":"https://avatars0.githubusercontent.com/u/56672?v=4","gravatar_id":"","url":"https://api.github.com/users/montekki","html_url":"https://github.com/montekki","followers_url":"https://api.github.com/users/montekki/followers","following_url":"https://api.github.com/users/montekki/following{/other_user}","gists_url":"https://api.github.com/users/montekki/gists{/gist_id}","starred_url":"https://api.github.com/users/montekki/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/montekki/subscriptions","organizations_url":"https://api.github.com/users/montekki/orgs","repos_url":"https://api.github.com/users/montekki/repos","events_url":"https://api.github.com/users/montekki/events{/privacy}","received_events_url":"https://api.github.com/users/montekki/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/montekki/www","description":"AI Village website","fork":true,"url":"https://api.github.com/repos/montekki/www","forks_url":"https://api.github.com/repos/montekki/www/forks","keys_url":"https://api.github.com/repos/montekki/www/keys{/key_id}","collaborators_url":"https://api.github.com/repos/montekki/www/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/montekki/www/teams","hooks_url":"https://api.github.com/repos/montekki/www/hooks","issue_events_url":"https://api.github.com/repos/montekki/www/issues/events{/number}","events_url":"https://api.github.com/repos/montekki/www/events","assignees_url":"https://api.github.com/repos/montekki/www/assignees{/user}","branches_url":"https://api.github.com/repos/montekki/www/branches{/branch}","tags_url":"https://api.github.com/repos/montekki/www/tags","blobs_url":"https://api.github.com/repos/montekki/www/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/montekki/www/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/montekki/www/git/refs{/sha}","trees_url":"https://api.github.com/repos/montekki/www/git/trees{/sha}","statuses_url":"https://api.github.com/repos/montekki/www/statuses/{sha}","languages_url":"https://api.github.com/repos/montekki/www/languages","stargazers_url":"https://api.github.com/repos/montekki/www/stargazers","contributors_url":"https://api.github.com/repos/montekki/www/contributors","subscribers_url":"https://api.github.com/repos/montekki/www/subscribers","subscription_url":"https://api.github.com/repos/montekki/www/subscription","commits_url":"https://api.github.com/repos/montekki/www/commits{/sha}","git_commits_url":"https://api.github.com/repos/montekki/www/git/commits{/sha}","comments_url":"https://api.github.com/repos/montekki/www/comments{/number}","issue_comment_url":"https://api.github.com/repos/montekki/www/issues/comments{/number}","contents_url":"https://api.github.com/repos/montekki/www/contents/{+path}","compare_url":"https://api.github.com/repos/montekki/www/compare/{base}...{head}","merges_url":"https://api.github.com/repos/montekki/www/merges","archive_url":"https://api.github.com/repos/montekki/www/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/montekki/www/downloads","issues_url":"https://api.github.com/repos/montekki/www/issues{/number}","pulls_url":"https://api.github.com/repos/montekki/www/pulls{/number}","milestones_url":"https://api.github.com/repos/montekki/www/milestones{/number}","notifications_url":"https://api.github.com/repos/montekki/www/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/montekki/www/labels{/name}","releases_url":"https://api.github.com/repos/montekki/www/releases{/id}","deployments_url":"https://api.github.com/repos/montekki/www/deployments","created_at":"2018-07-13T14:16:51Z","updated_at":"2018-07-18T03:47:30Z","pushed_at":"2018-08-06T12:40:24Z","git_url":"git://github.com/montekki/www.git","ssh_url":"git@github.com:montekki/www.git","clone_url":"https://github.com/montekki/www.git","svn_url":"https://github.com/montekki/www","homepage":"https://aivillage.org/","size":30113,"stargazers_count":0,"watchers_count":0,"language":"HTML","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":3,"mirror_url":null,"archived":false,"open_issues_count":1,"license":null,"forks":3,"open_issues":1,"watchers":0,"default_branch":"code"}},"_links":{"self":{"href":"https://api.github.com/repos/montekki/www/pulls/3"},"html":{"href":"https://github.com/montekki/www/pull/3"},"issue":{"href":"https://api.github.com/repos/montekki/www/issues/3"},"comments":{"href":"https://api.github.com/repos/montekki/www/issues/3/comments"},"review_comments":{"href":"https://api.github.com/repos/montekki/www/pulls/3/comments"},"review_comment":{"href":"https://api.github.com/repos/montekki/www/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/montekki/www/pulls/3/commits"},"statuses":{"href":"https://api.github.com/repos/montekki/www/statuses/b4074b97df9a04dba9b51bd568b22458b3e583d0"}},"author_association":"NONE"}}
{"actor":{"display_login":"amurzina"}}